Skip to content

Commit 03f1212

Browse files
Li Nanaxboe
Li Nan
authored andcommitted
block: fix deadlock between bd_link_disk_holder and partition scan
'open_mutex' of gendisk is used to protect open/close block devices. But in bd_link_disk_holder(), it is used to protect the creation of symlink between holding disk and slave bdev, which introduces some issues. When bd_link_disk_holder() is called, the driver is usually in the process of initialization/modification and may suspend submitting io. At this time, any io hold 'open_mutex', such as scanning partitions, can cause deadlocks. For example, in raid: T1 T2 bdev_open_by_dev lock open_mutex [1] ... efi_partition ... md_submit_bio md_ioctl mddev_syspend -> suspend all io md_add_new_disk bind_rdev_to_array bd_link_disk_holder try lock open_mutex [2] md_handle_request -> wait mddev_resume T1 scan partition, T2 add a new device to raid. T1 waits for T2 to resume mddev, but T2 waits for open_mutex held by T1. Deadlock occurs. Fix it by introducing a local mutex 'blk_holder_mutex' to replace 'open_mutex'. Fixes: 1b0a2d9 ("md: use new apis to suspend array for ioctls involed array reconfiguration") Reported-by: [email protected] Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218459 Signed-off-by: Li Nan <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Yu Kuai <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 522d735 commit 03f1212

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

block/holder.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ struct bd_holder_disk {
88
int refcnt;
99
};
1010

11+
static DEFINE_MUTEX(blk_holder_mutex);
12+
1113
static struct bd_holder_disk *bd_find_holder_disk(struct block_device *bdev,
1214
struct gendisk *disk)
1315
{
@@ -80,7 +82,7 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
8082
kobject_get(bdev->bd_holder_dir);
8183
mutex_unlock(&bdev->bd_disk->open_mutex);
8284

83-
mutex_lock(&disk->open_mutex);
85+
mutex_lock(&blk_holder_mutex);
8486
WARN_ON_ONCE(!bdev->bd_holder);
8587

8688
holder = bd_find_holder_disk(bdev, disk);
@@ -108,15 +110,15 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
108110
goto out_del_symlink;
109111
list_add(&holder->list, &disk->slave_bdevs);
110112

111-
mutex_unlock(&disk->open_mutex);
113+
mutex_unlock(&blk_holder_mutex);
112114
return 0;
113115

114116
out_del_symlink:
115117
del_symlink(disk->slave_dir, bdev_kobj(bdev));
116118
out_free_holder:
117119
kfree(holder);
118120
out_unlock:
119-
mutex_unlock(&disk->open_mutex);
121+
mutex_unlock(&blk_holder_mutex);
120122
if (ret)
121123
kobject_put(bdev->bd_holder_dir);
122124
return ret;
@@ -140,7 +142,7 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
140142
if (WARN_ON_ONCE(!disk->slave_dir))
141143
return;
142144

143-
mutex_lock(&disk->open_mutex);
145+
mutex_lock(&blk_holder_mutex);
144146
holder = bd_find_holder_disk(bdev, disk);
145147
if (!WARN_ON_ONCE(holder == NULL) && !--holder->refcnt) {
146148
del_symlink(disk->slave_dir, bdev_kobj(bdev));
@@ -149,6 +151,6 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
149151
list_del_init(&holder->list);
150152
kfree(holder);
151153
}
152-
mutex_unlock(&disk->open_mutex);
154+
mutex_unlock(&blk_holder_mutex);
153155
}
154156
EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);

0 commit comments

Comments
 (0)