diff options
author | Filipe Manana <fdmanana@suse.com> | 2015-11-05 11:06:23 +0100 |
---|---|---|
committer | Filipe Manana <fdmanana@suse.com> | 2015-11-05 11:32:21 +0100 |
commit | 190631f1c8cb7e4d5c27ff87e22ed53817e78759 (patch) | |
tree | a0b01561f6504793d66fe12351a784303fa2327d /drivers/scsi/ipr.h | |
parent | btrfs: qgroup: exit the rescan worker during umount (diff) | |
download | linux-190631f1c8cb7e4d5c27ff87e22ed53817e78759.tar.xz linux-190631f1c8cb7e4d5c27ff87e22ed53817e78759.zip |
Btrfs: fix race waiting for qgroup rescan worker
We were initializing the completion (fs_info->qgroup_rescan_completion)
object after releasing the qgroup rescan lock, which gives a small time
window for a rescan waiter to not actually wait for the rescan worker
to finish. Example:
CPU 1 CPU 2
fs_info->qgroup_rescan_completion->done is 0
btrfs_qgroup_rescan_worker()
complete_all(&fs_info->qgroup_rescan_completion)
sets fs_info->qgroup_rescan_completion->done
to UINT_MAX / 2
... do some other stuff ....
qgroup_rescan_init()
mutex_lock(&fs_info->qgroup_rescan_lock)
set flag BTRFS_QGROUP_STATUS_FLAG_RESCAN
in fs_info->qgroup_flags
mutex_unlock(&fs_info->qgroup_rescan_lock)
btrfs_qgroup_wait_for_completion()
mutex_lock(&fs_info->qgroup_rescan_lock)
sees flag BTRFS_QGROUP_STATUS_FLAG_RESCAN
in fs_info->qgroup_flags
mutex_unlock(&fs_info->qgroup_rescan_lock)
wait_for_completion_interruptible(
&fs_info->qgroup_rescan_completion)
fs_info->qgroup_rescan_completion->done
is > 0 so it returns immediately
init_completion(&fs_info->qgroup_rescan_completion)
sets fs_info->qgroup_rescan_completion->done to 0
So fix this by initializing the completion object while holding the mutex
fs_info->qgroup_rescan_lock.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Diffstat (limited to 'drivers/scsi/ipr.h')
0 files changed, 0 insertions, 0 deletions