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

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.jp


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent c4110804
Loading
Loading
Loading
Loading
+22 −22
Original line number Diff line number Diff line
@@ -373,10 +373,22 @@ static int brd_alloc(int i)
	struct gendisk *disk;
	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);
	if (!brd)
	if (!brd) {
		mutex_unlock(&brd_devices_mutex);
		return -ENOMEM;
	}
	brd->brd_number		= i;
	list_add_tail(&brd->brd_list, &brd_devices);
	mutex_unlock(&brd_devices_mutex);

	spin_lock_init(&brd->brd_lock);
	INIT_RADIX_TREE(&brd->brd_pages, GFP_ATOMIC);

@@ -411,37 +423,30 @@ static int brd_alloc(int i)
	blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
	blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue);
	add_disk(disk);
	list_add_tail(&brd->brd_list, &brd_devices);

	return 0;

out_free_dev:
	mutex_lock(&brd_devices_mutex);
	list_del(&brd->brd_list);
	mutex_unlock(&brd_devices_mutex);
	kfree(brd);
	return -ENOMEM;
}

static void brd_probe(dev_t dev)
{
	int i = 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);
	brd_alloc(MINOR(dev) / max_part);
}

static void brd_del_one(struct brd_device *brd)
{
	list_del(&brd->brd_list);
	del_gendisk(brd->brd_disk);
	blk_cleanup_disk(brd->brd_disk);
	brd_free_pages(brd);
	mutex_lock(&brd_devices_mutex);
	list_del(&brd->brd_list);
	mutex_unlock(&brd_devices_mutex);
	kfree(brd);
}

@@ -491,25 +496,21 @@ static int __init brd_init(void)

	brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL);

	mutex_lock(&brd_devices_mutex);
	for (i = 0; i < rd_nr; i++) {
		err = brd_alloc(i);
		if (err)
			goto out_free;
	}

	mutex_unlock(&brd_devices_mutex);

	pr_info("brd: module loaded\n");
	return 0;

out_free:
	unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
	debugfs_remove_recursive(brd_debugfs_dir);

	list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
		brd_del_one(brd);
	mutex_unlock(&brd_devices_mutex);
	unregister_blkdev(RAMDISK_MAJOR, "ramdisk");

	pr_info("brd: module NOT loaded !!!\n");
	return err;
@@ -519,13 +520,12 @@ static void __exit brd_exit(void)
{
	struct brd_device *brd, *next;

	unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
	debugfs_remove_recursive(brd_debugfs_dir);

	list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
		brd_del_one(brd);

	unregister_blkdev(RAMDISK_MAJOR, "ramdisk");

	pr_info("brd: module unloaded\n");
}