Commit f7bf3586 authored by Tetsuo Handa's avatar Tetsuo Handa Committed by Jens Axboe

brd: reduce the brd_devices_mutex scope

As with commit 8b52d8be ("loop: reorder loop_exit"),
unregister_blkdev() needs to be called first in order to avoid calling
brd_alloc() from brd_probe() after brd_del_one() from brd_exit(). Then,
we can avoid holding global mutex during add_disk()/del_gendisk() as with
commit 1c500ad7 ("loop: reduce the loop_ctl_mutex scope").
Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/e205f13d-18ff-a49c-0988-7de6ea5ff823@i-love.sakura.ne.jpSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent c4110804
...@@ -373,10 +373,22 @@ static int brd_alloc(int i) ...@@ -373,10 +373,22 @@ static int brd_alloc(int i)
struct gendisk *disk; struct gendisk *disk;
char buf[DISK_NAME_LEN]; char buf[DISK_NAME_LEN];
mutex_lock(&brd_devices_mutex);
list_for_each_entry(brd, &brd_devices, brd_list) {
if (brd->brd_number == i) {
mutex_unlock(&brd_devices_mutex);
return -EEXIST;
}
}
brd = kzalloc(sizeof(*brd), GFP_KERNEL); brd = kzalloc(sizeof(*brd), GFP_KERNEL);
if (!brd) if (!brd) {
mutex_unlock(&brd_devices_mutex);
return -ENOMEM; return -ENOMEM;
}
brd->brd_number = i; brd->brd_number = i;
list_add_tail(&brd->brd_list, &brd_devices);
mutex_unlock(&brd_devices_mutex);
spin_lock_init(&brd->brd_lock); spin_lock_init(&brd->brd_lock);
INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC); INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC);
...@@ -411,37 +423,30 @@ static int brd_alloc(int i) ...@@ -411,37 +423,30 @@ static int brd_alloc(int i)
blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue); blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue);
add_disk(disk); add_disk(disk);
list_add_tail(&brd->brd_list, &brd_devices);
return 0; return 0;
out_free_dev: out_free_dev:
mutex_lock(&brd_devices_mutex);
list_del(&brd->brd_list);
mutex_unlock(&brd_devices_mutex);
kfree(brd); kfree(brd);
return -ENOMEM; return -ENOMEM;
} }
static void brd_probe(dev_t dev) static void brd_probe(dev_t dev)
{ {
int i = MINOR(dev) / max_part; brd_alloc(MINOR(dev) / max_part);
struct brd_device *brd;
mutex_lock(&brd_devices_mutex);
list_for_each_entry(brd, &brd_devices, brd_list) {
if (brd->brd_number == i)
goto out_unlock;
}
brd_alloc(i);
out_unlock:
mutex_unlock(&brd_devices_mutex);
} }
static void brd_del_one(struct brd_device *brd) static void brd_del_one(struct brd_device *brd)
{ {
list_del(&brd->brd_list);
del_gendisk(brd->brd_disk); del_gendisk(brd->brd_disk);
blk_cleanup_disk(brd->brd_disk); blk_cleanup_disk(brd->brd_disk);
brd_free_pages(brd); brd_free_pages(brd);
mutex_lock(&brd_devices_mutex);
list_del(&brd->brd_list);
mutex_unlock(&brd_devices_mutex);
kfree(brd); kfree(brd);
} }
...@@ -491,25 +496,21 @@ static int __init brd_init(void) ...@@ -491,25 +496,21 @@ static int __init brd_init(void)
brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL); brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL);
mutex_lock(&brd_devices_mutex);
for (i = 0; i < rd_nr; i++) { for (i = 0; i < rd_nr; i++) {
err = brd_alloc(i); err = brd_alloc(i);
if (err) if (err)
goto out_free; goto out_free;
} }
mutex_unlock(&brd_devices_mutex);
pr_info("brd: module loaded\n"); pr_info("brd: module loaded\n");
return 0; return 0;
out_free: out_free:
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
debugfs_remove_recursive(brd_debugfs_dir); debugfs_remove_recursive(brd_debugfs_dir);
list_for_each_entry_safe(brd, next, &brd_devices, brd_list) list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
brd_del_one(brd); brd_del_one(brd);
mutex_unlock(&brd_devices_mutex);
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
pr_info("brd: module NOT loaded !!!\n"); pr_info("brd: module NOT loaded !!!\n");
return err; return err;
...@@ -519,13 +520,12 @@ static void __exit brd_exit(void) ...@@ -519,13 +520,12 @@ static void __exit brd_exit(void)
{ {
struct brd_device *brd, *next; struct brd_device *brd, *next;
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
debugfs_remove_recursive(brd_debugfs_dir); debugfs_remove_recursive(brd_debugfs_dir);
list_for_each_entry_safe(brd, next, &brd_devices, brd_list) list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
brd_del_one(brd); brd_del_one(brd);
unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
pr_info("brd: module unloaded\n"); pr_info("brd: module unloaded\n");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment