io-wq: fix wakeup race when adding new work
authorJens Axboe <axboe@kernel.dk>
Mon, 13 Sep 2021 15:20:44 +0000 (09:20 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 18 Sep 2021 11:40:06 +0000 (13:40 +0200)
commit9ac218642dfc1309682baa708e81935e5cec5ff3
treebc4fae2e41efcec28acab9c2dfaff4df4d1a356a
parent548ee201fb4a3c372a332284df3ecc21749918e1
io-wq: fix wakeup race when adding new work

commit 87df7fb922d18e96992aa5e824aa34b2065fef59 upstream.

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
unlock
atomic_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.

Cc: stable@vger.kernel.org
Reported-by: Andres Freund <andres@anarazel.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/io-wq.c