rcu/tree: Repeat the monitor if any free channel is busy
authorUladzislau Rezki (Sony) <urezki@gmail.com>
Mon, 25 May 2020 21:47:47 +0000 (23:47 +0200)
committerPaul E. McKenney <paulmck@kernel.org>
Mon, 29 Jun 2020 18:59:25 +0000 (11:59 -0700)
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>
kernel/rcu/tree.c

index e0425faf3b3b1ca5d3579f353efcea1a6062f7fe..5151fe4e142984e8514a5e81ae160870f8523d81 100644 (file)
@@ -3105,7 +3105,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);
@@ -3143,11 +3143,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,