RCU: Question rcu_preempt_blocked_readers_cgp in rcu_gp_fqs_loop func

From: Zhang, Qiang
Date: Wed Sep 09 2020 - 03:04:06 EST



When config preempt RCU, and then there are multiple levels node, the current task is preempted in rcu read critical region.
the current task be add to "rnp->blkd_tasks" link list, and the "rnp->gp_tasks" may be assigned a value . these rnp is leaf node in RCU tree.

But in "rcu_gp_fqs_loop" func, we check blocked readers in root node.

static void rcu_gp_fqs_loop(void)
{
.....
struct rcu_node *rnp = rcu_get_root();
.....
if (!READ_ONCE(rnp->qsmask) &&
!rcu_preempt_blocked_readers_cgp(rnp)) ------> rnp is root node
break;
....
}

the root node's blkd_tasks never add task, the "rnp->gp_tasks" is never be assigned value, this check is invailed.
Should we check leaf nodes like this

--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1846,6 +1846,25 @@ static bool rcu_gp_init(void)
return true;
}

+static bool rcu_preempt_blocked_readers(void)
+{
+ struct rcu_node *rnp;
+ unsigned long flags;
+ bool ret = false;
+
+ rcu_for_each_leaf_node(rnp) {
+ raw_spin_lock_irqsave_rcu_node(rnp, flags);
+ if (rcu_preempt_blocked_readers_cgp(rnp)) {
+ ret = true;
+ raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+ break;
+ }
+ raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+ }
+
+ return ret;
+}
+
/*
* Helper function for swait_event_idle_exclusive() wakeup at force-quiescent-state
* time.
@@ -1864,7 +1883,7 @@ static bool rcu_gp_fqs_check_wake(int *gfp)
return true;

// The current grace period has completed.
- if (!READ_ONCE(rnp->qsmask) && !rcu_preempt_blocked_readers_cgp(rnp))
+ if (!READ_ONCE(rnp->qsmask) && !rcu_preempt_blocked_readers())
return true;

return false;
@@ -1927,7 +1946,7 @@ static void rcu_gp_fqs_loop(void)
/* Locking provides needed memory barriers. */
/* If grace period done, leave loop. */
if (!READ_ONCE(rnp->qsmask) &&
- !rcu_preempt_blocked_readers_cgp(rnp))
+ !rcu_preempt_blocked_readers())
break;
/* If time for quiescent-state forcing, do it. */
if (!time_after(rcu_state.jiffies_force_qs, jiffies) ||
--


thanks
Qiang