linux_dsm_epyc7002/kernel/rcu
Paul E. McKenney 87446b4874 rcu: Make rcu_read_unlock_special() checks match raise_softirq_irqoff()
Threaded interrupts provide additional interesting interactions between
RCU and raise_softirq() that can result in self-deadlocks in v5.0-2 of
the Linux kernel.  These self-deadlocks can be provoked in susceptible
kernels within a few minutes using the following rcutorture command on
an 8-CPU system:

tools/testing/selftests/rcutorture/bin/kvm.sh --duration 5 --configs "TREE03" --bootargs "threadirqs"

Although post-v5.2 RCU commits have at least greatly reduced the
probability of these self-deadlocks, this was entirely by accident.
Although this sort of accident should be rowdily celebrated on those
rare occasions when it does occur, such celebrations should be quickly
followed by a principled patch, which is what this patch purports to be.

The key point behind this patch is that when in_interrupt() returns
true, __raise_softirq_irqoff() will never attempt a wakeup.  Therefore,
if in_interrupt(), calls to raise_softirq*() are both safe and
extremely cheap.

This commit therefore replaces the in_irq() calls in the "if" statement
in rcu_read_unlock_special() with in_interrupt() and simplifies the
"if" condition to the following:

	if (irqs_were_disabled && use_softirq &&
	    (in_interrupt() ||
	     (exp && !t->rcu_read_unlock_special.b.deferred_qs))) {
		raise_softirq_irqoff(RCU_SOFTIRQ);
	} else {
		/* Appeal to the scheduler. */
	}

The rationale behind the "if" condition is as follows:

1.	irqs_were_disabled:  If interrupts are enabled, we should
	instead appeal to the scheduler so as to let the upcoming
	irq_enable()/local_bh_enable() do the rescheduling for us.
2.	use_softirq: If this kernel isn't using softirq, then
	raise_softirq_irqoff() will be unhelpful.
3.	a.	in_interrupt(): If this returns true, the subsequent
		call to raise_softirq_irqoff() is guaranteed not to
		do a wakeup, so that call will be both very cheap and
		quite safe.
	b.	Otherwise, if !in_interrupt() the raise_softirq_irqoff()
		might do a wakeup, which is expensive and, in some
		contexts, unsafe.
		i.	The "exp" (an expedited RCU grace period is being
			blocked) says that the wakeup is worthwhile, and:
		ii.	The !.deferred_qs says that scheduler locks
			cannot be held, so the wakeup will be safe.

Backporting this requires considerable care, so no auto-backport, please!

Fixes: 05f415715c ("rcu: Speed up expedited GPs when interrupting RCU reader")
Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
2019-08-01 14:04:20 -07:00
..
Kconfig treewide: Add SPDX license identifier - Makefile/Kconfig 2019-05-21 10:50:46 +02:00
Kconfig.debug treewide: Add SPDX license identifier - Makefile/Kconfig 2019-05-21 10:50:46 +02:00
Makefile License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
rcu_segcblist.c rcu/rcu_segcblist: Convert to SPDX license identifier 2019-02-09 08:43:40 -08:00
rcu_segcblist.h rcu/rcu_segcblist: Convert to SPDX license identifier 2019-02-09 08:43:40 -08:00
rcu.h rcutorture: Add trivial RCU implementation 2019-05-28 09:06:09 -07:00
rcuperf.c rcuperf: Fix cleanup path for invalid perf_type strings 2019-03-26 14:42:53 -07:00
rcutorture.c rcutorture: Upper case solves the case of the vanishing NULL pointer 2019-05-28 09:06:09 -07:00
srcutiny.c srcu: Remove cleanup_srcu_struct_quiesced() 2019-03-26 14:39:24 -07:00
srcutree.c rcu: Make __call_srcu static 2019-05-28 09:03:35 -07:00
sync.c rcu/sync: Simplify the state machine 2019-05-28 09:05:23 -07:00
tiny.c rcu: rcu_qs -- Use raise_softirq_irqoff to not save irqs twice 2019-03-26 14:37:49 -07:00
tree_exp.h Merge branches 'consolidate.2019.05.28a', 'doc.2019.05.28a', 'fixes.2019.06.13a', 'srcu.2019.05.28a', 'sync.2019.05.28a' and 'torture.2019.05.28a' into HEAD 2019-06-19 09:21:46 -07:00
tree_plugin.h rcu: Make rcu_read_unlock_special() checks match raise_softirq_irqoff() 2019-08-01 14:04:20 -07:00
tree_stall.h rcu: Correctly unlock root node in rcu_check_gp_start_stall() 2019-05-28 09:02:57 -07:00
tree.c Merge branches 'consolidate.2019.05.28a', 'doc.2019.05.28a', 'fixes.2019.06.13a', 'srcu.2019.05.28a', 'sync.2019.05.28a' and 'torture.2019.05.28a' into HEAD 2019-06-19 09:21:46 -07:00
tree.h rcu: Rename rcu_data's ->deferred_qs to ->exp_deferred_qs 2019-05-28 08:48:19 -07:00
update.c rcutorture: Add trivial RCU implementation 2019-05-28 09:06:09 -07:00