]> www.infradead.org Git - users/hch/block.git/commitdiff
loop: move loop device deletion out of loop_ctl_mutex
authorChristoph Hellwig <hch@lst.de>
Wed, 18 Aug 2021 05:37:56 +0000 (07:37 +0200)
committerChristoph Hellwig <hch@lst.de>
Thu, 26 Aug 2021 09:43:36 +0000 (11:43 +0200)
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 <hdanton@sina.com> and
Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>.

Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/block/loop.c

index cb01f22a2f4b47e5516e9c4d599c2a95f9f0579d..fe249662fa1bebe9df0280e75bdeffce21aebff7 100644 (file)
@@ -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);
 }