mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-13 22:25:03 +00:00
rcu: Make quiescent-state reporting use ->gp_seq
This commit switches the functions reporting quiescent states from use of ->gpnum to ->gp_seq. In either case, the point is to handle races where a given grace period ends before a quiescent state can be reported. Failing to catch these races would result in too-short grace periods, hence the checking. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This commit is contained in:
parent
78c5a67f17
commit
c9a24e2d0c
1 changed files with 9 additions and 9 deletions
|
@ -2242,7 +2242,7 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags)
|
||||||
* must be represented by the same rcu_node structure (which need not be a
|
* must be represented by the same rcu_node structure (which need not be a
|
||||||
* leaf rcu_node structure, though it often will be). The gps parameter
|
* leaf rcu_node structure, though it often will be). The gps parameter
|
||||||
* is the grace-period snapshot, which means that the quiescent states
|
* is the grace-period snapshot, which means that the quiescent states
|
||||||
* are valid only if rnp->gpnum is equal to gps. That structure's lock
|
* are valid only if rnp->gp_seq is equal to gps. That structure's lock
|
||||||
* must be held upon entry, and it is released before return.
|
* must be held upon entry, and it is released before return.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
|
@ -2257,7 +2257,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
|
||||||
|
|
||||||
/* Walk up the rcu_node hierarchy. */
|
/* Walk up the rcu_node hierarchy. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!(rnp->qsmask & mask) || rnp->gpnum != gps) {
|
if (!(rnp->qsmask & mask) || rnp->gp_seq != gps) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Our bit has already been cleared, or the
|
* Our bit has already been cleared, or the
|
||||||
|
@ -2335,8 +2335,8 @@ static void rcu_report_unblock_qs_rnp(struct rcu_state *rsp,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Report up the rest of the hierarchy, tracking current ->gpnum. */
|
/* Report up the rest of the hierarchy, tracking current ->gp_seq. */
|
||||||
gps = rnp->gpnum;
|
gps = rnp->gp_seq;
|
||||||
mask = rnp->grpmask;
|
mask = rnp->grpmask;
|
||||||
raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled. */
|
raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled. */
|
||||||
raw_spin_lock_rcu_node(rnp_p); /* irqs already disabled. */
|
raw_spin_lock_rcu_node(rnp_p); /* irqs already disabled. */
|
||||||
|
@ -2357,8 +2357,8 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp)
|
||||||
|
|
||||||
rnp = rdp->mynode;
|
rnp = rdp->mynode;
|
||||||
raw_spin_lock_irqsave_rcu_node(rnp, flags);
|
raw_spin_lock_irqsave_rcu_node(rnp, flags);
|
||||||
if (rdp->cpu_no_qs.b.norm || rdp->gpnum != rnp->gpnum ||
|
if (rdp->cpu_no_qs.b.norm || rdp->gp_seq != rnp->gp_seq ||
|
||||||
rnp->completed == rnp->gpnum || rdp->gpwrap) {
|
rdp->gpwrap) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The grace period in which this quiescent state was
|
* The grace period in which this quiescent state was
|
||||||
|
@ -2383,7 +2383,7 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp)
|
||||||
*/
|
*/
|
||||||
needwake = rcu_accelerate_cbs(rsp, rnp, rdp);
|
needwake = rcu_accelerate_cbs(rsp, rnp, rdp);
|
||||||
|
|
||||||
rcu_report_qs_rnp(mask, rsp, rnp, rnp->gpnum, flags);
|
rcu_report_qs_rnp(mask, rsp, rnp, rnp->gp_seq, flags);
|
||||||
/* ^^^ Released rnp->lock */
|
/* ^^^ Released rnp->lock */
|
||||||
if (needwake)
|
if (needwake)
|
||||||
rcu_gp_kthread_wake(rsp);
|
rcu_gp_kthread_wake(rsp);
|
||||||
|
@ -2688,8 +2688,8 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *rsp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mask != 0) {
|
if (mask != 0) {
|
||||||
/* Idle/offline CPUs, report (releases rnp->lock. */
|
/* Idle/offline CPUs, report (releases rnp->lock). */
|
||||||
rcu_report_qs_rnp(mask, rsp, rnp, rnp->gpnum, flags);
|
rcu_report_qs_rnp(mask, rsp, rnp, rnp->gp_seq, flags);
|
||||||
} else {
|
} else {
|
||||||
/* Nothing to do here, so just drop the lock. */
|
/* Nothing to do here, so just drop the lock. */
|
||||||
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
|
raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
|
||||||
|
|
Loading…
Reference in a new issue