Skip to content

Commit 85e0a0f

Browse files
committed
Btrfs: remove unnecessary locking of cleaner_mutex to avoid deadlock
After commmit e44163e ("btrfs: explictly delete unused block groups in close_ctree and ro-remount"), added in the 4.3 merge window, we have calls to btrfs_delete_unused_bgs() while holding the cleaner_mutex. This can cause a deadlock with a concurrent block group relocation (when a filesystem balance or shrink operation is in progress for example) because btrfs_delete_unused_bgs() locks delete_unused_bgs_mutex and the relocation path locks first delete_unused_bgs_mutex and then it locks cleaner_mutex, resulting in a classic ABBA deadlock: CPU 0 CPU 1 lock fs_info->cleaner_mutex __btrfs_balance() || btrfs_shrink_device() lock fs_info->delete_unused_bgs_mutex btrfs_relocate_chunk() btrfs_relocate_block_group() lock fs_info->cleaner_mutex btrfs_delete_unused_bgs() lock fs_info->delete_unused_bgs_mutex Fix this by not taking the cleaner_mutex before calling btrfs_delete_unused_bgs() because it's no longer needed after commit 67c5e7d ("Btrfs: fix race between balance and unused block group deletion"). The mutex fs_info->delete_unused_bgs_mutex, the spinlock fs_info->unused_bgs_lock and a block group's spinlock are enough to get correct serialization between tasks running relocation and unused block group deletion (as well as between multiple tasks concurrently calling btrfs_delete_unused_bgs()). This issue was discussed (in the mailing list) during the review of the patch titled "btrfs: explictly delete unused block groups in close_ctree and ro-remount" and it was agreed that acquiring the cleaner mutex had to be dropped after the patch titled "Btrfs: fix race between balance and unused block group deletion" got merged (both patches were submitted at about the same time, but one landed in kernel 4.2 and the other in the 4.3 merge window). Signed-off-by: Filipe Manana <fdmanana@suse.com>
1 parent 6af3e3a commit 85e0a0f

File tree

2 files changed

+0
-4
lines changed

2 files changed

+0
-4
lines changed

fs/btrfs/disk-io.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3762,9 +3762,7 @@ void close_ctree(struct btrfs_root *root)
37623762
* block groups queued for removal, the deletion will be
37633763
* skipped when we quit the cleaner thread.
37643764
*/
3765-
mutex_lock(&root->fs_info->cleaner_mutex);
37663765
btrfs_delete_unused_bgs(root->fs_info);
3767-
mutex_unlock(&root->fs_info->cleaner_mutex);
37683766

37693767
ret = btrfs_commit_super(root);
37703768
if (ret)

fs/btrfs/super.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,9 +1658,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
16581658
* groups on disk until we're mounted read-write again
16591659
* unless we clean them up here.
16601660
*/
1661-
mutex_lock(&root->fs_info->cleaner_mutex);
16621661
btrfs_delete_unused_bgs(fs_info);
1663-
mutex_unlock(&root->fs_info->cleaner_mutex);
16641662

16651663
btrfs_dev_replace_suspend_for_unmount(fs_info);
16661664
btrfs_scrub_cancel(fs_info);

0 commit comments

Comments
 (0)