mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
io-wq: write next_work before dropping acct_lock
[ Upstream commit 068c27e32e51e94e4a9eb30ae85f4097a3602980 ] Commit361aee450c
("io-wq: add intermediate work step between pending list and active work") closed a race between a cancellation and the work being removed from the wq for execution. To ensure the request is always reachable by the cancellation, we need to move it within the wq lock, which also synchronizes the cancellation. But commit42abc95f05
("io-wq: decouple work_list protection from the big wqe->lock") replaced the wq lock here and accidentally reintroduced the race by releasing the acct_lock too early. In other words: worker | cancellation work = io_get_next_work() | raw_spin_unlock(&acct->lock); | | | io_acct_cancel_pending_work | io_wq_worker_cancel() worker->next_work = work Using acct_lock is still enough since we synchronize on it on io_acct_cancel_pending_work. Fixes:42abc95f05
("io-wq: decouple work_list protection from the big wqe->lock") Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de> Link: https://lore.kernel.org/r/20240416021054.3940-2-krisman@suse.de Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
af82d8d217
commit
f32f810dcc
1 changed files with 8 additions and 5 deletions
|
@ -564,10 +564,7 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
|
|||
* clear the stalled flag.
|
||||
*/
|
||||
work = io_get_next_work(acct, worker);
|
||||
raw_spin_unlock(&acct->lock);
|
||||
if (work) {
|
||||
__io_worker_busy(wq, worker);
|
||||
|
||||
/*
|
||||
* Make sure cancelation can find this, even before
|
||||
* it becomes the active work. That avoids a window
|
||||
|
@ -578,9 +575,15 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
|
|||
raw_spin_lock(&worker->lock);
|
||||
worker->next_work = work;
|
||||
raw_spin_unlock(&worker->lock);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
raw_spin_unlock(&acct->lock);
|
||||
|
||||
if (!work)
|
||||
break;
|
||||
|
||||
__io_worker_busy(wq, worker);
|
||||
|
||||
io_assign_current_work(worker, work);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue