Commit d292dc80 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

loop: don't destroy lo->workqueue in __loop_clr_fd

There is no need to destroy the workqueue when clearing unbinding
a loop device from a backing file.  Not doing so on the other hand
avoid creating a complex lock dependency chain involving the global
system_transition_mutex.

Based on a patch from Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>.

Reported-by: syzbot+6479585dfd4dedd3f7e1@syzkaller.appspotmail.com
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Tested-by: syzbot+6479585dfd4dedd3f7e1@syzkaller.appspotmail.com
Link: https://lore.kernel.org/r/20220330052917.2566582-16-hch@lst.deSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent a0e286b6
...@@ -812,7 +812,6 @@ struct loop_worker { ...@@ -812,7 +812,6 @@ struct loop_worker {
}; };
static void loop_workfn(struct work_struct *work); static void loop_workfn(struct work_struct *work);
static void loop_rootcg_workfn(struct work_struct *work);
#ifdef CONFIG_BLK_CGROUP #ifdef CONFIG_BLK_CGROUP
static inline int queue_on_root_worker(struct cgroup_subsys_state *css) static inline int queue_on_root_worker(struct cgroup_subsys_state *css)
...@@ -1050,20 +1049,19 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, ...@@ -1050,20 +1049,19 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
!file->f_op->write_iter) !file->f_op->write_iter)
lo->lo_flags |= LO_FLAGS_READ_ONLY; lo->lo_flags |= LO_FLAGS_READ_ONLY;
if (!lo->workqueue) {
lo->workqueue = alloc_workqueue("loop%d", lo->workqueue = alloc_workqueue("loop%d",
WQ_UNBOUND | WQ_FREEZABLE, WQ_UNBOUND | WQ_FREEZABLE,
0, 0, lo->lo_number);
lo->lo_number);
if (!lo->workqueue) { if (!lo->workqueue) {
error = -ENOMEM; error = -ENOMEM;
goto out_unlock; goto out_unlock;
} }
}
disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE); disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE);
set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0); set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0);
INIT_WORK(&lo->rootcg_work, loop_rootcg_workfn);
INIT_LIST_HEAD(&lo->rootcg_cmd_list);
lo->use_dio = lo->lo_flags & LO_FLAGS_DIRECT_IO; lo->use_dio = lo->lo_flags & LO_FLAGS_DIRECT_IO;
lo->lo_device = bdev; lo->lo_device = bdev;
lo->lo_backing_file = file; lo->lo_backing_file = file;
...@@ -1143,10 +1141,6 @@ static void __loop_clr_fd(struct loop_device *lo, bool release) ...@@ -1143,10 +1141,6 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
if (!release) if (!release)
blk_mq_freeze_queue(lo->lo_queue); blk_mq_freeze_queue(lo->lo_queue);
destroy_workqueue(lo->workqueue);
loop_free_idle_workers(lo, true);
del_timer_sync(&lo->timer);
spin_lock_irq(&lo->lo_lock); spin_lock_irq(&lo->lo_lock);
filp = lo->lo_backing_file; filp = lo->lo_backing_file;
lo->lo_backing_file = NULL; lo->lo_backing_file = NULL;
...@@ -1750,6 +1744,10 @@ static void lo_free_disk(struct gendisk *disk) ...@@ -1750,6 +1744,10 @@ static void lo_free_disk(struct gendisk *disk)
{ {
struct loop_device *lo = disk->private_data; struct loop_device *lo = disk->private_data;
if (lo->workqueue)
destroy_workqueue(lo->workqueue);
loop_free_idle_workers(lo, true);
del_timer_sync(&lo->timer);
mutex_destroy(&lo->lo_mutex); mutex_destroy(&lo->lo_mutex);
kfree(lo); kfree(lo);
} }
...@@ -2013,6 +2011,8 @@ static int loop_add(int i) ...@@ -2013,6 +2011,8 @@ static int loop_add(int i)
lo->lo_number = i; lo->lo_number = i;
spin_lock_init(&lo->lo_lock); spin_lock_init(&lo->lo_lock);
spin_lock_init(&lo->lo_work_lock); spin_lock_init(&lo->lo_work_lock);
INIT_WORK(&lo->rootcg_work, loop_rootcg_workfn);
INIT_LIST_HEAD(&lo->rootcg_cmd_list);
disk->major = LOOP_MAJOR; disk->major = LOOP_MAJOR;
disk->first_minor = i << part_shift; disk->first_minor = i << part_shift;
disk->minors = 1 << part_shift; disk->minors = 1 << part_shift;
......
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