From 4c69d8874f8717b1e7e6c3c04f1541a345a7e9f0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 18 Aug 2021 07:37:56 +0200 Subject: [PATCH] loop: move loop device deletion out of loop_ctl_mutex To avoid complex lock ordering issues always delete loop devices outside of loop_ctl_mutex. In loop_control_remove the Lo_deleting state can be used to prevent further lookups, and given that module unload is synchronized vs new opens of the control device and thus ioctls there is no need for locks there at all. Based on patches from Hillf Danton and Tetsuo Handa . Reported-by: Tetsuo Handa Signed-off-by: Christoph Hellwig --- drivers/block/loop.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index cb01f22a2f4b..fe249662fa1b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -2479,7 +2479,11 @@ static int loop_control_remove(int idx) mutex_unlock(&lo->lo_mutex); idr_remove(&loop_index_idr, lo->lo_number); + mutex_unlock(&loop_ctl_mutex); + loop_remove(lo); + return 0; + out_unlock_ctrl: mutex_unlock(&loop_ctl_mutex); return ret; @@ -2610,11 +2614,12 @@ static void __exit loop_exit(void) unregister_blkdev(LOOP_MAJOR, "loop"); misc_deregister(&loop_misc); - mutex_lock(&loop_ctl_mutex); + /* + * No need for loop_ctl_mutex given that no new ioctls and thus + * additions and removals can happen in parallel to module unloading. + */ idr_for_each_entry(&loop_index_idr, lo, id) loop_remove(lo); - mutex_unlock(&loop_ctl_mutex); - idr_destroy(&loop_index_idr); } -- 2.50.1