FAILED: patch "[PATCH] io-wq: fix wakeup race when adding new work" failed to apply to 5.10-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 87df7fb922d18e96992aa5e824aa34b2065fef59 Mon Sep 17 00:00:00 2001
From: Jens Axboe <[email protected]>
Date: Mon, 30 Aug 2021 07:45:47 -0600
Subject: [PATCH] io-wq: fix wakeup race when adding new work
When new work is added, io_wqe_enqueue() checks if we need to wake or create a new worker. But that check is done outside the lock that otherwise synchronizes us with a worker going to sleep, so we can end up in the following situation:
CPU0 CPU1
lock
insert work
unlockatomic_read(nr_running) != 0
lock atomic_dec(nr_running)
no wakeup needed
Hold the wqe lock around the "need to wakeup" check. Then we can also get rid of the temporary work_flags variable, as we know the work will remain valid as long as we hold the lock.
fs/io-wq.c +4 -4
@@ -794,7 +794,7 @@ static void io_wqe_insert_work(struct io_wqe *wqe, struct io_wq_work *work)static void io_wqe_enqueue (struct io_wqe *wqe,struct io_wq_work *work) {struct io_wqe_acct *acct =io_work_get_acct (wqe, work); -int work_flags; +bool do_wake;/* * If io-wq is exiting for this task, or if the request has explicitly
@@ -806,14 +806,14 @@ static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work)return ; } - work_flags = work->flags;raw_spin_lock (&wqe->lock);io_wqe_insert_work (wqe, work); wqe->flags &= ~IO_WQE_FLAG_STALLED ; + do_wake = (work->flags &IO_WQ_WORK_CONCURRENT ) || + !atomic_read (&acct->nr_running);raw_spin_unlock (&wqe->lock); -if ((work_flags &IO_WQ_WORK_CONCURRENT ) || - !atomic_read (&acct->nr_running)) +if (do_wake)io_wqe_wake_worker (wqe, acct); }