Commit f03359bc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:

 - set correct ram_bytes when splitting ordered extent. This can be
   inconsistent on-disk but harmless as it's not used for calculations
   and it's only advisory for compression

 - fix lockdep splat when taking cleaner mutex in qgroups disable ioctl

 - fix missing mutex unlock on error path when looking up sys chunk for
   relocation

* tag 'for-6.9-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: set correct ram_bytes when splitting ordered extent
  btrfs: take the cleaner_mutex earlier in qgroup disable
  btrfs: add missing mutex_unlock in btrfs_relocate_sys_chunks()
parents da87c77e 63a6ce5a
Loading
Loading
Loading
Loading
+30 −3
Original line number Diff line number Diff line
@@ -3758,15 +3758,43 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
		goto drop_write;
	}

	down_write(&fs_info->subvol_sem);

	switch (sa->cmd) {
	case BTRFS_QUOTA_CTL_ENABLE:
	case BTRFS_QUOTA_CTL_ENABLE_SIMPLE_QUOTA:
		down_write(&fs_info->subvol_sem);
		ret = btrfs_quota_enable(fs_info, sa);
		up_write(&fs_info->subvol_sem);
		break;
	case BTRFS_QUOTA_CTL_DISABLE:
		/*
		 * Lock the cleaner mutex to prevent races with concurrent
		 * relocation, because relocation may be building backrefs for
		 * blocks of the quota root while we are deleting the root. This
		 * is like dropping fs roots of deleted snapshots/subvolumes, we
		 * need the same protection.
		 *
		 * This also prevents races between concurrent tasks trying to
		 * disable quotas, because we will unlock and relock
		 * qgroup_ioctl_lock across BTRFS_FS_QUOTA_ENABLED changes.
		 *
		 * We take this here because we have the dependency of
		 *
		 * inode_lock -> subvol_sem
		 *
		 * because of rename.  With relocation we can prealloc extents,
		 * so that makes the dependency chain
		 *
		 * cleaner_mutex -> inode_lock -> subvol_sem
		 *
		 * so we must take the cleaner_mutex here before we take the
		 * subvol_sem.  The deadlock can't actually happen, but this
		 * quiets lockdep.
		 */
		mutex_lock(&fs_info->cleaner_mutex);
		down_write(&fs_info->subvol_sem);
		ret = btrfs_quota_disable(fs_info);
		up_write(&fs_info->subvol_sem);
		mutex_unlock(&fs_info->cleaner_mutex);
		break;
	default:
		ret = -EINVAL;
@@ -3774,7 +3802,6 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
	}

	kfree(sa);
	up_write(&fs_info->subvol_sem);
drop_write:
	mnt_drop_write_file(file);
	return ret;
+1 −0
Original line number Diff line number Diff line
@@ -1188,6 +1188,7 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent(
	ordered->disk_bytenr += len;
	ordered->num_bytes -= len;
	ordered->disk_num_bytes -= len;
	ordered->ram_bytes -= len;

	if (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)) {
		ASSERT(ordered->bytes_left == 0);
+8 −13
Original line number Diff line number Diff line
@@ -1342,16 +1342,10 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
	lockdep_assert_held_write(&fs_info->subvol_sem);

	/*
	 * Lock the cleaner mutex to prevent races with concurrent relocation,
	 * because relocation may be building backrefs for blocks of the quota
	 * root while we are deleting the root. This is like dropping fs roots
	 * of deleted snapshots/subvolumes, we need the same protection.
	 *
	 * This also prevents races between concurrent tasks trying to disable
	 * quotas, because we will unlock and relock qgroup_ioctl_lock across
	 * BTRFS_FS_QUOTA_ENABLED changes.
	 * Relocation will mess with backrefs, so make sure we have the
	 * cleaner_mutex held to protect us from relocate.
	 */
	mutex_lock(&fs_info->cleaner_mutex);
	lockdep_assert_held(&fs_info->cleaner_mutex);

	mutex_lock(&fs_info->qgroup_ioctl_lock);
	if (!fs_info->quota_root)
@@ -1373,9 +1367,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
	clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
	btrfs_qgroup_wait_for_completion(fs_info, false);

	/*
	 * We have nothing held here and no trans handle, just return the error
	 * if there is one.
	 */
	ret = flush_reservations(fs_info);
	if (ret)
		goto out_unlock_cleaner;
		return ret;

	/*
	 * 1 For the root item
@@ -1439,9 +1437,6 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
		btrfs_end_transaction(trans);
	else if (trans)
		ret = btrfs_commit_transaction(trans);
out_unlock_cleaner:
	mutex_unlock(&fs_info->cleaner_mutex);

	return ret;
}

+1 −0
Original line number Diff line number Diff line
@@ -3455,6 +3455,7 @@ static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info)
			 * alignment and size).
			 */
			ret = -EUCLEAN;
			mutex_unlock(&fs_info->reclaim_bgs_lock);
			goto error;
		}