| From 6077cc70cec213d3fba0c30227480b0c74679ada Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 25 May 2020 23:47:47 +0200 |
| Subject: rcu/tree: Repeat the monitor if any free channel is busy |
| |
| From: Uladzislau Rezki (Sony) <urezki@gmail.com> |
| |
| [ Upstream commit 594aa5975b9b5cfe9edaec06170e43b8c0607377 ] |
| |
| It is possible that one of the channels cannot be detached |
| because its free channel is busy and previously queued data |
| has not been processed yet. On the other hand, another |
| channel can be successfully detached causing the monitor |
| work to stop. |
| |
| Prevent that by rescheduling the monitor work if there are |
| any channels in the pending state after a detach attempt. |
| |
| Fixes: 34c881745549e ("rcu: Support kfree_bulk() interface in kfree_rcu()") |
| Acked-by: Joel Fernandes (Google) <joel@joelfernandes.org> |
| Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com> |
| Signed-off-by: Paul E. McKenney <paulmck@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| kernel/rcu/tree.c | 9 ++++++--- |
| 1 file changed, 6 insertions(+), 3 deletions(-) |
| |
| diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c |
| index d9a49cd6065a2..a3aa129cc8f5f 100644 |
| --- a/kernel/rcu/tree.c |
| +++ b/kernel/rcu/tree.c |
| @@ -2895,7 +2895,7 @@ static void kfree_rcu_work(struct work_struct *work) |
| static inline bool queue_kfree_rcu_work(struct kfree_rcu_cpu *krcp) |
| { |
| struct kfree_rcu_cpu_work *krwp; |
| - bool queued = false; |
| + bool repeat = false; |
| int i; |
| |
| lockdep_assert_held(&krcp->lock); |
| @@ -2931,11 +2931,14 @@ static inline bool queue_kfree_rcu_work(struct kfree_rcu_cpu *krcp) |
| * been detached following each other, one by one. |
| */ |
| queue_rcu_work(system_wq, &krwp->rcu_work); |
| - queued = true; |
| } |
| + |
| + /* Repeat if any "free" corresponding channel is still busy. */ |
| + if (krcp->bhead || krcp->head) |
| + repeat = true; |
| } |
| |
| - return queued; |
| + return !repeat; |
| } |
| |
| static inline void kfree_rcu_drain_unlock(struct kfree_rcu_cpu *krcp, |
| -- |
| 2.25.1 |
| |