Add the helper, so we can remove the duplicated code for freeing all workers in clearing FD. Cc: Michal Koutný <mkoutny@xxxxxxxx> Cc: Dan Schatzberg <schatzberg.dan@xxxxxxxxx> Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> --- drivers/block/loop.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 7fa0c70a3ea6..b71c8659f140 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1138,16 +1138,14 @@ static void loop_set_timer(struct loop_device *lo) schedule_delayed_work(&lo->idle_work, LOOP_IDLE_WORKER_TIMEOUT); } -static void loop_free_idle_workers(struct work_struct *work) +static void __loop_free_idle_workers(struct loop_device *lo, bool force) { - struct loop_device *lo = container_of(work, struct loop_device, - idle_work.work); struct loop_worker *pos, *worker; spin_lock(&lo->lo_work_lock); list_for_each_entry_safe(worker, pos, &lo->idle_worker_list, idle_list) { - if (time_is_after_jiffies(worker->last_ran_at + + if (!force && time_is_after_jiffies(worker->last_ran_at + LOOP_IDLE_WORKER_TIMEOUT)) break; list_del(&worker->idle_list); @@ -1160,6 +1158,13 @@ static void loop_free_idle_workers(struct work_struct *work) spin_unlock(&lo->lo_work_lock); } +static void loop_free_idle_workers(struct work_struct *work) +{ + struct loop_device *lo = container_of(work, struct loop_device, + idle_work.work); + + __loop_free_idle_workers(lo, false); +} static int loop_configure(struct loop_device *lo, fmode_t mode, struct block_device *bdev, @@ -1309,7 +1314,6 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) int err = 0; bool partscan = false; int lo_number; - struct loop_worker *pos, *worker; mutex_lock(&lo->lo_mutex); if (WARN_ON_ONCE(lo->lo_state != Lo_rundown)) { @@ -1330,15 +1334,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) blk_mq_freeze_queue(lo->lo_queue); destroy_workqueue(lo->workqueue); - spin_lock(&lo->lo_work_lock); - list_for_each_entry_safe(worker, pos, &lo->idle_worker_list, - idle_list) { - list_del(&worker->idle_list); - rb_erase(&worker->rb_node, &lo->worker_tree); - css_put(worker->blkcg_css); - kfree(worker); - } - spin_unlock(&lo->lo_work_lock); + __loop_free_idle_workers(lo, true); cancel_delayed_work_sync(&lo->idle_work); spin_lock_irq(&lo->lo_lock); -- 2.31.1