Avoid to acquire the spinlock for handling every loop command, and hold lock once for taking all commands. Acked-by: Dan Schatzberg <schatzberg.dan@xxxxxxxxx> Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> --- drivers/block/loop.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6d9cfd47b7a2..c9a28483433b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -2238,21 +2238,26 @@ static void loop_process_work(struct loop_worker *worker, { int orig_flags = current->flags; struct loop_cmd *cmd; + LIST_HEAD(list); current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO; + spin_lock(&lo->lo_work_lock); - while (!list_empty(cmd_list)) { - cmd = container_of( - cmd_list->next, struct loop_cmd, list_entry); - list_del(cmd_list->next); - spin_unlock(&lo->lo_work_lock); + again: + list_splice_init(cmd_list, &list); + spin_unlock(&lo->lo_work_lock); - loop_handle_cmd(cmd); - cond_resched(); + while (!list_empty(&list)) { + cmd = list_first_entry(&list, struct loop_cmd, list_entry); + list_del_init(&cmd->list_entry); - spin_lock(&lo->lo_work_lock); + loop_handle_cmd(cmd); } + spin_lock(&lo->lo_work_lock); + if (!list_empty(cmd_list)) + goto again; + /* * We only add to the idle list if there are no pending cmds * *and* the worker will not run again which ensures that it -- 2.31.1