Commit f03359bc authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-6.9-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

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
...@@ -3758,15 +3758,43 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg) ...@@ -3758,15 +3758,43 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
goto drop_write; goto drop_write;
} }
down_write(&fs_info->subvol_sem);
switch (sa->cmd) { switch (sa->cmd) {
case BTRFS_QUOTA_CTL_ENABLE: case BTRFS_QUOTA_CTL_ENABLE:
case BTRFS_QUOTA_CTL_ENABLE_SIMPLE_QUOTA: case BTRFS_QUOTA_CTL_ENABLE_SIMPLE_QUOTA:
down_write(&fs_info->subvol_sem);
ret = btrfs_quota_enable(fs_info, sa); ret = btrfs_quota_enable(fs_info, sa);
up_write(&fs_info->subvol_sem);
break; break;
case BTRFS_QUOTA_CTL_DISABLE: 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); ret = btrfs_quota_disable(fs_info);
up_write(&fs_info->subvol_sem);
mutex_unlock(&fs_info->cleaner_mutex);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
...@@ -3774,7 +3802,6 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg) ...@@ -3774,7 +3802,6 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
} }
kfree(sa); kfree(sa);
up_write(&fs_info->subvol_sem);
drop_write: drop_write:
mnt_drop_write_file(file); mnt_drop_write_file(file);
return ret; return ret;
......
...@@ -1188,6 +1188,7 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( ...@@ -1188,6 +1188,7 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent(
ordered->disk_bytenr += len; ordered->disk_bytenr += len;
ordered->num_bytes -= len; ordered->num_bytes -= len;
ordered->disk_num_bytes -= len; ordered->disk_num_bytes -= len;
ordered->ram_bytes -= len;
if (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)) { if (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)) {
ASSERT(ordered->bytes_left == 0); ASSERT(ordered->bytes_left == 0);
......
...@@ -1342,16 +1342,10 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) ...@@ -1342,16 +1342,10 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
lockdep_assert_held_write(&fs_info->subvol_sem); lockdep_assert_held_write(&fs_info->subvol_sem);
/* /*
* Lock the cleaner mutex to prevent races with concurrent relocation, * Relocation will mess with backrefs, so make sure we have the
* because relocation may be building backrefs for blocks of the quota * cleaner_mutex held to protect us from relocate.
* 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.
*/ */
mutex_lock(&fs_info->cleaner_mutex); lockdep_assert_held(&fs_info->cleaner_mutex);
mutex_lock(&fs_info->qgroup_ioctl_lock); mutex_lock(&fs_info->qgroup_ioctl_lock);
if (!fs_info->quota_root) if (!fs_info->quota_root)
...@@ -1373,9 +1367,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) ...@@ -1373,9 +1367,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
btrfs_qgroup_wait_for_completion(fs_info, false); 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); ret = flush_reservations(fs_info);
if (ret) if (ret)
goto out_unlock_cleaner; return ret;
/* /*
* 1 For the root item * 1 For the root item
...@@ -1439,9 +1437,6 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) ...@@ -1439,9 +1437,6 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
btrfs_end_transaction(trans); btrfs_end_transaction(trans);
else if (trans) else if (trans)
ret = btrfs_commit_transaction(trans); ret = btrfs_commit_transaction(trans);
out_unlock_cleaner:
mutex_unlock(&fs_info->cleaner_mutex);
return ret; return ret;
} }
......
...@@ -3455,6 +3455,7 @@ static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info) ...@@ -3455,6 +3455,7 @@ static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info)
* alignment and size). * alignment and size).
*/ */
ret = -EUCLEAN; ret = -EUCLEAN;
mutex_unlock(&fs_info->reclaim_bgs_lock);
goto error; goto error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment