Skip to content

Commit d06f23d

Browse files
jeffmahoneymasoncl
authored andcommitted
btrfs: waiting on qgroup rescan should not always be interruptible
We wait on qgroup rescan completion in three places: file system shutdown, the quota disable ioctl, and the rescan wait ioctl. If the user sends a signal while we're waiting, we continue happily along. This is expected behavior for the rescan wait ioctl. It's racy in the shutdown path but mostly works due to other unrelated synchronization points. In the quota disable path, it Oopses the kernel pretty much immediately. Cc: <[email protected]> # v4.4+ Signed-off-by: Jeff Mahoney <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]> Signed-off-by: Chris Mason <[email protected]>
1 parent d2c609b commit d06f23d

File tree

4 files changed

+13
-6
lines changed

4 files changed

+13
-6
lines changed

fs/btrfs/disk-io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3864,7 +3864,7 @@ void close_ctree(struct btrfs_root *root)
38643864
smp_mb();
38653865

38663866
/* wait for the qgroup rescan worker to stop */
3867-
btrfs_qgroup_wait_for_completion(fs_info);
3867+
btrfs_qgroup_wait_for_completion(fs_info, false);
38683868

38693869
/* wait for the uuid_scan task to finish */
38703870
down(&fs_info->uuid_tree_rescan_sem);

fs/btrfs/ioctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5084,7 +5084,7 @@ static long btrfs_ioctl_quota_rescan_wait(struct file *file, void __user *arg)
50845084
if (!capable(CAP_SYS_ADMIN))
50855085
return -EPERM;
50865086

5087-
return btrfs_qgroup_wait_for_completion(root->fs_info);
5087+
return btrfs_qgroup_wait_for_completion(root->fs_info, true);
50885088
}
50895089

50905090
static long _btrfs_ioctl_set_received_subvol(struct file *file,

fs/btrfs/qgroup.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
995995
goto out;
996996
fs_info->quota_enabled = 0;
997997
fs_info->pending_quota_state = 0;
998-
btrfs_qgroup_wait_for_completion(fs_info);
998+
btrfs_qgroup_wait_for_completion(fs_info, false);
999999
spin_lock(&fs_info->qgroup_lock);
10001000
quota_root = fs_info->quota_root;
10011001
fs_info->quota_root = NULL;
@@ -2494,7 +2494,8 @@ btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info)
24942494
return 0;
24952495
}
24962496

2497-
int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info)
2497+
int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info,
2498+
bool interruptible)
24982499
{
24992500
int running;
25002501
int ret = 0;
@@ -2505,9 +2506,14 @@ int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info)
25052506
spin_unlock(&fs_info->qgroup_lock);
25062507
mutex_unlock(&fs_info->qgroup_rescan_lock);
25072508

2508-
if (running)
2509+
if (!running)
2510+
return 0;
2511+
2512+
if (interruptible)
25092513
ret = wait_for_completion_interruptible(
25102514
&fs_info->qgroup_rescan_completion);
2515+
else
2516+
wait_for_completion(&fs_info->qgroup_rescan_completion);
25112517

25122518
return ret;
25132519
}

fs/btrfs/qgroup.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
4646
struct btrfs_fs_info *fs_info);
4747
int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
4848
void btrfs_qgroup_rescan_resume(struct btrfs_fs_info *fs_info);
49-
int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info);
49+
int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info,
50+
bool interruptible);
5051
int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
5152
struct btrfs_fs_info *fs_info, u64 src, u64 dst);
5253
int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,

0 commit comments

Comments
 (0)