io-wq: close cancel gap for hashed linked work
authorPavel Begunkov <asml.silence@gmail.com>
Sun, 22 Mar 2020 16:14:26 +0000 (19:14 +0300)
committerJens Axboe <axboe@kernel.dk>
Sun, 22 Mar 2020 17:33:58 +0000 (11:33 -0600)
After io_assign_current_work() of a linked work, it can be decided to
offloaded to another thread so doing io_wqe_enqueue(). However, until
next io_assign_current_work() it can be cancelled, that isn't handled.

Don't assign it, if it's not going to be executed.

Fixes: 60cf46ae6054 ("io-wq: hash dependent work")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io-wq.c

index 9541df2..b3fb61e 100644 (file)
@@ -485,7 +485,7 @@ static void io_worker_handle_work(struct io_worker *worker)
        struct io_wq *wq = wqe->wq;
 
        do {
-               struct io_wq_work *work;
+               struct io_wq_work *work, *assign_work;
                unsigned int hash;
 get_next:
                /*
@@ -522,10 +522,14 @@ get_next:
                        hash = io_get_work_hash(work);
                        work->func(&work);
                        work = (old_work == work) ? NULL : work;
-                       io_assign_current_work(worker, work);
+
+                       assign_work = work;
+                       if (work && io_wq_is_hashed(work))
+                               assign_work = NULL;
+                       io_assign_current_work(worker, assign_work);
                        wq->free_work(old_work);
 
-                       if (work && io_wq_is_hashed(work)) {
+                       if (work && !assign_work) {
                                io_wqe_enqueue(wqe, work);
                                work = NULL;
                        }