[PATCH V4 5/7] loop: improve loop_process_work

Ming Lei
2021-08-06T08:04:14Z

Avoid to acquire the spinlock for handling every loop command, and hold
lock once for taking all commands.

Acked-by: Dan Schatzberg <schatzberg.dan@gmail.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
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 6e5c55d4552b..c322d6468ee7 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