]>
Commit | Line | Data |
---|---|---|
25aba572 FE |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Jens Axboe <axboe@kernel.dk> | |
3 | Date: Tue, 31 Aug 2021 13:53:00 -0600 | |
4 | Subject: [PATCH] io-wq: fix queue stalling race | |
5 | ||
6 | We need to set the stalled bit early, before we drop the lock for adding | |
7 | us to the stall hash queue. If not, then we can race with new work being | |
8 | queued between adding us to the stall hash and io_worker_handle_work() | |
9 | marking us stalled. | |
10 | ||
11 | Signed-off-by: Jens Axboe <axboe@kernel.dk> | |
12 | [backport] | |
13 | Signed-off-by: Fabian Ebner <f.ebner@proxmox.com> | |
14 | --- | |
15 | fs/io-wq.c | 15 +++++++-------- | |
16 | 1 file changed, 7 insertions(+), 8 deletions(-) | |
17 | ||
18 | diff --git a/fs/io-wq.c b/fs/io-wq.c | |
19 | index 6612d0aa497e..33678185f3bc 100644 | |
20 | --- a/fs/io-wq.c | |
21 | +++ b/fs/io-wq.c | |
22 | @@ -437,8 +437,7 @@ static bool io_worker_can_run_work(struct io_worker *worker, | |
23 | } | |
24 | ||
25 | static struct io_wq_work *io_get_next_work(struct io_wqe *wqe, | |
26 | - struct io_worker *worker, | |
27 | - bool *stalled) | |
28 | + struct io_worker *worker) | |
29 | __must_hold(wqe->lock) | |
30 | { | |
31 | struct io_wq_work_node *node, *prev; | |
32 | @@ -476,10 +475,14 @@ static struct io_wq_work *io_get_next_work(struct io_wqe *wqe, | |
33 | } | |
34 | ||
35 | if (stall_hash != -1U) { | |
36 | + /* | |
37 | + * Set this before dropping the lock to avoid racing with new | |
38 | + * work being added and clearing the stalled bit. | |
39 | + */ | |
40 | + wqe->flags |= IO_WQE_FLAG_STALLED; | |
41 | raw_spin_unlock(&wqe->lock); | |
42 | io_wait_on_hash(wqe, stall_hash); | |
43 | raw_spin_lock(&wqe->lock); | |
44 | - *stalled = true; | |
45 | } | |
46 | ||
47 | return NULL; | |
48 | @@ -519,7 +522,6 @@ static void io_worker_handle_work(struct io_worker *worker) | |
49 | ||
50 | do { | |
51 | struct io_wq_work *work; | |
52 | - bool stalled; | |
53 | get_next: | |
54 | /* | |
55 | * If we got some work, mark us as busy. If we didn't, but | |
56 | @@ -528,12 +530,9 @@ static void io_worker_handle_work(struct io_worker *worker) | |
57 | * can't make progress, any work completion or insertion will | |
58 | * clear the stalled flag. | |
59 | */ | |
60 | - stalled = false; | |
61 | - work = io_get_next_work(wqe, worker, &stalled); | |
62 | + work = io_get_next_work(wqe, worker); | |
63 | if (work) | |
64 | __io_worker_busy(wqe, worker, work); | |
65 | - else if (stalled) | |
66 | - wqe->flags |= IO_WQE_FLAG_STALLED; | |
67 | ||
68 | raw_spin_unlock_irq(&wqe->lock); | |
69 | if (!work) | |
70 | -- | |
71 | 2.30.2 | |
72 |