Re: [PATCH v3] block: genhd: don't call probe function with major_names_lock held
From: Christoph Hellwig <hch@lst.de>
Date: 2021-08-16 07:33:18
Subsystem:
block layer, the rest · Maintainers:
Jens Axboe, Linus Torvalds
This is the wrong way to approach it. Instead of making things ever more complex try to make it simpler. In this case, ensure that the destroy_workqueue is not held with pointless locks. Given that the loop device already is known to not have a reference and marked as in the rundown state there shouldn't be anything that is required to be protected by lo_mutex. So something like this untested patch should probably do the work:
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index fa1c298a8cfb..c734dc768316 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c@@ -1347,16 +1347,15 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) * became visible. */ - mutex_lock(&lo->lo_mutex); if (WARN_ON_ONCE(lo->lo_state != Lo_rundown)) { err = -ENXIO; - goto out_unlock; + goto out; } filp = lo->lo_backing_file; if (filp == NULL) { err = -EINVAL; - goto out_unlock; + goto out; } if (test_bit(QUEUE_FLAG_WC, &lo->lo_queue->queue_flags))
@@ -1366,6 +1365,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) blk_mq_freeze_queue(lo->lo_queue); destroy_workqueue(lo->workqueue); + + mutex_lock(&lo->lo_mutex); spin_lock_irq(&lo->lo_work_lock); list_for_each_entry_safe(worker, pos, &lo->idle_worker_list, idle_list) {
@@ -1413,8 +1414,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) partscan = lo->lo_flags & LO_FLAGS_PARTSCAN && bdev; lo_number = lo->lo_number; disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE); -out_unlock: mutex_unlock(&lo->lo_mutex); + if (partscan) { /* * open_mutex has been held already in release path, so don't
@@ -1435,7 +1436,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) /* Device is gone, no point in returning error */ err = 0; } - +out: /* * lo->lo_state is set to Lo_unbound here after above partscan has * finished.