Commit 61cc5315 authored by Zhang, Jun's avatar Zhang, Jun Committed by Greg Kroah-Hartman

rcu: Do RCU GP kthread self-wakeup from softirq and interrupt

commit 1d1f898d upstream.

The rcu_gp_kthread_wake() function is invoked when it might be necessary
to wake the RCU grace-period kthread.  Because self-wakeups are normally
a useless waste of CPU cycles, if rcu_gp_kthread_wake() is invoked from
this kthread, it naturally refuses to do the wakeup.

Unfortunately, natural though it might be, this heuristic fails when
rcu_gp_kthread_wake() is invoked from an interrupt or softirq handler
that interrupted the grace-period kthread just after the final check of
the wait-event condition but just before the schedule() call.  In this
case, a wakeup is required, even though the call to rcu_gp_kthread_wake()
is within the RCU grace-period kthread's context.  Failing to provide
this wakeup can result in grace periods failing to start, which in turn
results in out-of-memory conditions.

This race window is quite narrow, but it actually did happen during real
testing.  It would of course need to be fixed even if it was strictly
theoretical in nature.

This patch does not Cc stable because it does not apply cleanly to
earlier kernel versions.

Fixes: 48a7639c ("rcu: Make callers awaken grace-period kthread")
Reported-by: default avatar"He, Bo" <bo.he@intel.com>
Co-developed-by: default avatar"Zhang, Jun" <jun.zhang@intel.com>
Co-developed-by: default avatar"He, Bo" <bo.he@intel.com>
Co-developed-by: default avatar"xiao, jin" <jin.xiao@intel.com>
Co-developed-by: default avatarBai, Jie A <jie.a.bai@intel.com>
Signed-off: "Zhang, Jun" <jun.zhang@intel.com>
Signed-off: "He, Bo" <bo.he@intel.com>
Signed-off: "xiao, jin" <jin.xiao@intel.com>
Signed-off: Bai, Jie A <jie.a.bai@intel.com>
Signed-off-by: default avatar"Zhang, Jun" <jun.zhang@intel.com>
[ paulmck: Switch from !in_softirq() to "!in_interrupt() &&
  !in_serving_softirq() to avoid redundant wakeups and to also handle the
  interrupt-handler scenario as well as the softirq-handler scenario that
  actually occurred in testing. ]
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.ibm.com>
Link: https://lkml.kernel.org/r/CD6925E8781EFD4D8E11882D20FC406D52A11F61@SHSMSX104.ccr.corp.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b61c06e3
...@@ -1789,15 +1789,23 @@ static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) ...@@ -1789,15 +1789,23 @@ static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp)
} }
/* /*
* Awaken the grace-period kthread for the specified flavor of RCU. * Awaken the grace-period kthread. Don't do a self-awaken (unless in
* Don't do a self-awaken, and don't bother awakening when there is * an interrupt or softirq handler), and don't bother awakening when there
* nothing for the grace-period kthread to do (as in several CPUs * is nothing for the grace-period kthread to do (as in several CPUs raced
* raced to awaken, and we lost), and finally don't try to awaken * to awaken, and we lost), and finally don't try to awaken a kthread that
* a kthread that has not yet been created. * has not yet been created. If all those checks are passed, track some
* debug information and awaken.
*
* So why do the self-wakeup when in an interrupt or softirq handler
* in the grace-period kthread's context? Because the kthread might have
* been interrupted just as it was going to sleep, and just after the final
* pre-sleep check of the awaken condition. In this case, a wakeup really
* is required, and is therefore supplied.
*/ */
static void rcu_gp_kthread_wake(struct rcu_state *rsp) static void rcu_gp_kthread_wake(struct rcu_state *rsp)
{ {
if (current == rsp->gp_kthread || if ((current == rsp->gp_kthread &&
!in_interrupt() && !in_serving_softirq()) ||
!READ_ONCE(rsp->gp_flags) || !READ_ONCE(rsp->gp_flags) ||
!rsp->gp_kthread) !rsp->gp_kthread)
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment