summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorUladzislau Rezki (Sony) <urezki@gmail.com>2020-05-25 23:47:47 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-08-19 08:23:27 +0200
commitb6d439dae45ed4f021a8ea4ec33c8dacc8f55d2c (patch)
treeddd189fd247427b184a24164e628fd185d4c8359 /kernel
parentfe8de1c5e8309ca4f8eb9a92e495acf546f0ed7e (diff)
rcu/tree: Repeat the monitor if any free channel is busy
[ 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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcu/tree.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index d9a49cd6065a..a3aa129cc8f5 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,