On Tue, Jul 06, 2021 at 07:52:27AM +0200, Christoph Hellwig wrote: > On Mon, Jul 05, 2021 at 06:26:03PM +0800, Ming Lei wrote: > > +static void loop_free_idle_workers(struct work_struct *work) > > +{ > > + 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 + > > + LOOP_IDLE_WORKER_TIMEOUT)) > > + break; > > + list_del(&worker->idle_list); > > + rb_erase(&worker->rb_node, &lo->worker_tree); > > + css_put(worker->blkcg_css); > > + kfree(worker); > > + } > > + if (!list_empty(&lo->idle_worker_list)) > > + loop_set_timer(lo); > > + spin_unlock(&lo->lo_work_lock); > > +} > > + > > + > > Double empty line. But that whole fact that the loop driver badly > reimplements work queues is just fucked up. We need to revert this > shit. Can you explain why work queues are bad for fixing this blkcg/memcg issue? Thanks, Ming