diff mbox series

[7/7] loop: avoid holding loop_ctl_mutex over add_disk

Message ID 20210818062455.211065-8-hch@lst.de (mailing list archive)
State New, archived
Headers show
Series [1/7] loop: remove the ->ioctl method in loop_func_table | expand

Commit Message

Christoph Hellwig Aug. 18, 2021, 6:24 a.m. UTC
To avoid complex lock ordering issues loop_ctl_mutex should not
be held over add_disk.  Add a new Lo_new state for a loop device
that has just been created but which is not live yet.

Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/block/loop.c | 16 ++++++++++++----
 drivers/block/loop.h |  1 +
 2 files changed, 13 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 043673bda8b3..80f462edc39f 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -2329,7 +2329,7 @@  static int loop_add(int i)
 	lo = kzalloc(sizeof(*lo), GFP_KERNEL);
 	if (!lo)
 		goto out;
-	lo->lo_state = Lo_unbound;
+	lo->lo_state = Lo_new;
 
 	err = mutex_lock_killable(&loop_ctl_mutex);
 	if (err)
@@ -2343,8 +2343,9 @@  static int loop_add(int i)
 	} else {
 		err = idr_alloc(&loop_index_idr, lo, 0, 0, GFP_KERNEL);
 	}
+	mutex_unlock(&loop_ctl_mutex);
 	if (err < 0)
-		goto out_unlock;
+		goto out_free_dev;
 	i = err;
 
 	err = -ENOMEM;
@@ -2414,15 +2415,22 @@  static int loop_add(int i)
 	disk->event_flags	= DISK_EVENT_FLAG_UEVENT;
 	sprintf(disk->disk_name, "loop%d", i);
 	add_disk(disk);
+
+	err = mutex_lock_killable(&loop_ctl_mutex);
+	if (err)
+		goto out_del_gendisk;
+	lo->lo_state = Lo_unbound;
 	mutex_unlock(&loop_ctl_mutex);
+
 	return i;
 
+out_del_gendisk:
+	del_gendisk(lo->lo_disk);
+	blk_cleanup_disk(lo->lo_disk);
 out_cleanup_tags:
 	blk_mq_free_tag_set(&lo->tag_set);
 out_free_idr:
 	idr_remove(&loop_index_idr, i);
-out_unlock:
-	mutex_unlock(&loop_ctl_mutex);
 out_free_dev:
 	kfree(lo);
 out:
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index d14ce6bdc014..608a20c23c64 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -24,6 +24,7 @@  enum {
 	Lo_bound,
 	Lo_rundown,
 	Lo_deleting,
+	Lo_new,
 };
 
 struct loop_func_table;