Skip to content

Commit 0bb7883

Browse files
fdmananakdave
authored andcommitted
btrfs: fix sleep while in non-sleep context during qgroup removal
While removing a qgroup's sysfs entry we end up taking the kernfs_mutex, through kobject_del(), while holding the fs_info->qgroup_lock spinlock, producing the following trace: [821.843637] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:281 [821.843641] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 28214, name: podman [821.843644] CPU: 3 PID: 28214 Comm: podman Tainted: G W 5.11.6 #15 [821.843646] Hardware name: Dell Inc. PowerEdge R330/084XW4, BIOS 2.11.0 12/08/2020 [821.843647] Call Trace: [821.843650] dump_stack+0xa1/0xfb [821.843656] ___might_sleep+0x144/0x160 [821.843659] mutex_lock+0x17/0x40 [821.843662] kernfs_remove_by_name_ns+0x1f/0x80 [821.843666] sysfs_remove_group+0x7d/0xe0 [821.843668] sysfs_remove_groups+0x28/0x40 [821.843670] kobject_del+0x2a/0x80 [821.843672] btrfs_sysfs_del_one_qgroup+0x2b/0x40 [btrfs] [821.843685] __del_qgroup_rb+0x12/0x150 [btrfs] [821.843696] btrfs_remove_qgroup+0x288/0x2a0 [btrfs] [821.843707] btrfs_ioctl+0x3129/0x36a0 [btrfs] [821.843717] ? __mod_lruvec_page_state+0x5e/0xb0 [821.843719] ? page_add_new_anon_rmap+0xbc/0x150 [821.843723] ? kfree+0x1b4/0x300 [821.843725] ? mntput_no_expire+0x55/0x330 [821.843728] __x64_sys_ioctl+0x5a/0xa0 [821.843731] do_syscall_64+0x33/0x70 [821.843733] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [821.843736] RIP: 0033:0x4cd3fb [821.843741] RSP: 002b:000000c000906b20 EFLAGS: 00000206 ORIG_RAX: 0000000000000010 [821.843744] RAX: ffffffffffffffda RBX: 000000c000050000 RCX: 00000000004cd3fb [821.843745] RDX: 000000c000906b98 RSI: 000000004010942a RDI: 000000000000000f [821.843747] RBP: 000000c000907cd0 R08: 000000c000622901 R09: 0000000000000000 [821.843748] R10: 000000c000d992c0 R11: 0000000000000206 R12: 000000000000012d [821.843749] R13: 000000000000012c R14: 0000000000000200 R15: 0000000000000049 Fix this by removing the qgroup sysfs entry while not holding the spinlock, since the spinlock is only meant for protection of the qgroup rbtree. Reported-by: Stuart Shelton <[email protected]> Link: https://lore.kernel.org/linux-btrfs/[email protected]/ Fixes: 49e5fb4 ("btrfs: qgroup: export qgroups in sysfs") CC: [email protected] # 5.10+ Reviewed-by: Qu Wenruo <[email protected]> Signed-off-by: Filipe Manana <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 8d488a8 commit 0bb7883

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

fs/btrfs/qgroup.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ static void __del_qgroup_rb(struct btrfs_fs_info *fs_info,
226226
{
227227
struct btrfs_qgroup_list *list;
228228

229-
btrfs_sysfs_del_one_qgroup(fs_info, qgroup);
230229
list_del(&qgroup->dirty);
231230
while (!list_empty(&qgroup->groups)) {
232231
list = list_first_entry(&qgroup->groups,
@@ -243,7 +242,6 @@ static void __del_qgroup_rb(struct btrfs_fs_info *fs_info,
243242
list_del(&list->next_member);
244243
kfree(list);
245244
}
246-
kfree(qgroup);
247245
}
248246

249247
/* must be called with qgroup_lock held */
@@ -569,6 +567,8 @@ void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info)
569567
qgroup = rb_entry(n, struct btrfs_qgroup, node);
570568
rb_erase(n, &fs_info->qgroup_tree);
571569
__del_qgroup_rb(fs_info, qgroup);
570+
btrfs_sysfs_del_one_qgroup(fs_info, qgroup);
571+
kfree(qgroup);
572572
}
573573
/*
574574
* We call btrfs_free_qgroup_config() when unmounting
@@ -1578,6 +1578,14 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
15781578
spin_lock(&fs_info->qgroup_lock);
15791579
del_qgroup_rb(fs_info, qgroupid);
15801580
spin_unlock(&fs_info->qgroup_lock);
1581+
1582+
/*
1583+
* Remove the qgroup from sysfs now without holding the qgroup_lock
1584+
* spinlock, since the sysfs_remove_group() function needs to take
1585+
* the mutex kernfs_mutex through kernfs_remove_by_name_ns().
1586+
*/
1587+
btrfs_sysfs_del_one_qgroup(fs_info, qgroup);
1588+
kfree(qgroup);
15811589
out:
15821590
mutex_unlock(&fs_info->qgroup_ioctl_lock);
15831591
return ret;

0 commit comments

Comments
 (0)