Linux v3.18-rc2-43-gf7e87a44ef60
- Add two RCU patches to fix a deadlock and a hang - Reenable debugging options.
This commit is contained in:
		
							parent
							
								
									995f274d71
								
							
						
					
					
						commit
						c6207348df
					
				| @ -1699,13 +1699,13 @@ CONFIG_B43_PCMCIA=y | ||||
| CONFIG_B43_SDIO=y | ||||
| CONFIG_B43_BCMA=y | ||||
| CONFIG_B43_BCMA_PIO=y | ||||
| # CONFIG_B43_DEBUG is not set | ||||
| CONFIG_B43_DEBUG=y | ||||
| CONFIG_B43_PHY_LP=y | ||||
| CONFIG_B43_PHY_N=y | ||||
| CONFIG_B43_PHY_HT=y | ||||
| CONFIG_B43_PHY_G=y | ||||
| CONFIG_B43LEGACY=m | ||||
| # CONFIG_B43LEGACY_DEBUG is not set | ||||
| CONFIG_B43LEGACY_DEBUG=y | ||||
| CONFIG_B43LEGACY_DMA=y | ||||
| CONFIG_B43LEGACY_PIO=y | ||||
| CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y | ||||
| @ -4694,7 +4694,7 @@ CONFIG_PM_DEBUG=y | ||||
| # CONFIG_DPM_WATCHDOG is not set # revisit this in debug | ||||
| CONFIG_PM_TRACE=y | ||||
| CONFIG_PM_TRACE_RTC=y | ||||
| # CONFIG_PM_TEST_SUSPEND is not set | ||||
| CONFIG_PM_TEST_SUSPEND=y | ||||
| CONFIG_PM_RUNTIME=y | ||||
| # CONFIG_PM_OPP is not set | ||||
| # CONFIG_PM_AUTOSLEEP is not set | ||||
|  | ||||
							
								
								
									
										112
									
								
								config-nodebug
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								config-nodebug
									
									
									
									
									
								
							| @ -2,115 +2,115 @@ CONFIG_SND_VERBOSE_PRINTK=y | ||||
| CONFIG_SND_DEBUG=y | ||||
| CONFIG_SND_PCM_XRUN_DEBUG=y | ||||
| 
 | ||||
| # CONFIG_DEBUG_ATOMIC_SLEEP is not set | ||||
| CONFIG_DEBUG_ATOMIC_SLEEP=y | ||||
| 
 | ||||
| # CONFIG_DEBUG_MUTEXES is not set | ||||
| # CONFIG_DEBUG_RT_MUTEXES is not set | ||||
| # CONFIG_DEBUG_LOCK_ALLOC is not set | ||||
| # CONFIG_LOCK_TORTURE_TEST is not set | ||||
| # CONFIG_PROVE_LOCKING is not set | ||||
| # CONFIG_DEBUG_SPINLOCK is not set | ||||
| # CONFIG_PROVE_RCU is not set | ||||
| CONFIG_DEBUG_MUTEXES=y | ||||
| CONFIG_DEBUG_RT_MUTEXES=y | ||||
| CONFIG_DEBUG_LOCK_ALLOC=y | ||||
| CONFIG_LOCK_TORTURE_TEST=m | ||||
| CONFIG_PROVE_LOCKING=y | ||||
| CONFIG_DEBUG_SPINLOCK=y | ||||
| CONFIG_PROVE_RCU=y | ||||
| # CONFIG_PROVE_RCU_REPEATEDLY is not set | ||||
| # CONFIG_DEBUG_PER_CPU_MAPS is not set | ||||
| CONFIG_DEBUG_PER_CPU_MAPS=y | ||||
| CONFIG_CPUMASK_OFFSTACK=y | ||||
| 
 | ||||
| # CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set | ||||
| CONFIG_CPU_NOTIFIER_ERROR_INJECT=m | ||||
| 
 | ||||
| # CONFIG_FAULT_INJECTION is not set | ||||
| # CONFIG_FAILSLAB is not set | ||||
| # CONFIG_FAIL_PAGE_ALLOC is not set | ||||
| # CONFIG_FAIL_MAKE_REQUEST is not set | ||||
| # CONFIG_FAULT_INJECTION_DEBUG_FS is not set | ||||
| # CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set | ||||
| # CONFIG_FAIL_IO_TIMEOUT is not set | ||||
| # CONFIG_FAIL_MMC_REQUEST is not set | ||||
| CONFIG_FAULT_INJECTION=y | ||||
| CONFIG_FAILSLAB=y | ||||
| CONFIG_FAIL_PAGE_ALLOC=y | ||||
| CONFIG_FAIL_MAKE_REQUEST=y | ||||
| CONFIG_FAULT_INJECTION_DEBUG_FS=y | ||||
| CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y | ||||
| CONFIG_FAIL_IO_TIMEOUT=y | ||||
| CONFIG_FAIL_MMC_REQUEST=y | ||||
| 
 | ||||
| # CONFIG_LOCK_STAT is not set | ||||
| CONFIG_LOCK_STAT=y | ||||
| 
 | ||||
| # CONFIG_DEBUG_STACK_USAGE is not set | ||||
| CONFIG_DEBUG_STACK_USAGE=y | ||||
| 
 | ||||
| # CONFIG_ACPI_DEBUG is not set | ||||
| CONFIG_ACPI_DEBUG=y | ||||
| 
 | ||||
| # CONFIG_DEBUG_SG is not set | ||||
| # CONFIG_DEBUG_PI_LIST is not set | ||||
| CONFIG_DEBUG_SG=y | ||||
| CONFIG_DEBUG_PI_LIST=y | ||||
| 
 | ||||
| # CONFIG_DEBUG_PAGEALLOC is not set | ||||
| 
 | ||||
| # CONFIG_DEBUG_OBJECTS is not set | ||||
| CONFIG_DEBUG_OBJECTS=y | ||||
| # CONFIG_DEBUG_OBJECTS_SELFTEST is not set | ||||
| # CONFIG_DEBUG_OBJECTS_FREE is not set | ||||
| # CONFIG_DEBUG_OBJECTS_TIMERS is not set | ||||
| # CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set | ||||
| CONFIG_DEBUG_OBJECTS_FREE=y | ||||
| CONFIG_DEBUG_OBJECTS_TIMERS=y | ||||
| CONFIG_DEBUG_OBJECTS_RCU_HEAD=y | ||||
| CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 | ||||
| 
 | ||||
| # CONFIG_X86_PTDUMP is not set | ||||
| # CONFIG_EFI_PGT_DUMP is not set | ||||
| CONFIG_X86_PTDUMP=y | ||||
| CONFIG_EFI_PGT_DUMP=y | ||||
| 
 | ||||
| # CONFIG_CAN_DEBUG_DEVICES is not set | ||||
| CONFIG_CAN_DEBUG_DEVICES=y | ||||
| 
 | ||||
| # CONFIG_MODULE_FORCE_UNLOAD is not set | ||||
| CONFIG_MODULE_FORCE_UNLOAD=y | ||||
| 
 | ||||
| 
 | ||||
| # CONFIG_DEBUG_NOTIFIERS is not set | ||||
| CONFIG_DEBUG_NOTIFIERS=y | ||||
| 
 | ||||
| # CONFIG_DMA_API_DEBUG is not set | ||||
| CONFIG_DMA_API_DEBUG=y | ||||
| 
 | ||||
| # CONFIG_MMIOTRACE is not set | ||||
| CONFIG_MMIOTRACE=y | ||||
| 
 | ||||
| # CONFIG_DEBUG_CREDENTIALS is not set | ||||
| CONFIG_DEBUG_CREDENTIALS=y | ||||
| 
 | ||||
| # off in both production debug and nodebug builds, | ||||
| #  on in rawhide nodebug builds | ||||
| # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set | ||||
| CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y | ||||
| 
 | ||||
| # CONFIG_EXT4_DEBUG is not set | ||||
| CONFIG_EXT4_DEBUG=y | ||||
| 
 | ||||
| # CONFIG_XFS_WARN is not set | ||||
| 
 | ||||
| # CONFIG_DEBUG_PERF_USE_VMALLOC is not set | ||||
| CONFIG_DEBUG_PERF_USE_VMALLOC=y | ||||
| 
 | ||||
| # CONFIG_JBD2_DEBUG is not set | ||||
| CONFIG_JBD2_DEBUG=y | ||||
| 
 | ||||
| # CONFIG_NFSD_FAULT_INJECTION is not set | ||||
| CONFIG_NFSD_FAULT_INJECTION=y | ||||
| 
 | ||||
| # CONFIG_DEBUG_BLK_CGROUP is not set | ||||
| CONFIG_DEBUG_BLK_CGROUP=y | ||||
| 
 | ||||
| # CONFIG_DRBD_FAULT_INJECTION is not set | ||||
| CONFIG_DRBD_FAULT_INJECTION=y | ||||
| 
 | ||||
| # CONFIG_ATH_DEBUG is not set | ||||
| # CONFIG_CARL9170_DEBUGFS is not set | ||||
| # CONFIG_IWLWIFI_DEVICE_TRACING is not set | ||||
| CONFIG_ATH_DEBUG=y | ||||
| CONFIG_CARL9170_DEBUGFS=y | ||||
| CONFIG_IWLWIFI_DEVICE_TRACING=y | ||||
| 
 | ||||
| # CONFIG_RTLWIFI_DEBUG is not set | ||||
| 
 | ||||
| # CONFIG_DEBUG_OBJECTS_WORK is not set | ||||
| CONFIG_DEBUG_OBJECTS_WORK=y | ||||
| 
 | ||||
| # CONFIG_DMADEVICES_DEBUG is not set | ||||
| # CONFIG_DMADEVICES_VDEBUG is not set | ||||
| CONFIG_DMADEVICES_DEBUG=y | ||||
| CONFIG_DMADEVICES_VDEBUG=y | ||||
| 
 | ||||
| CONFIG_PM_ADVANCED_DEBUG=y | ||||
| 
 | ||||
| # CONFIG_CEPH_LIB_PRETTYDEBUG is not set | ||||
| # CONFIG_QUOTA_DEBUG is not set | ||||
| CONFIG_CEPH_LIB_PRETTYDEBUG=y | ||||
| CONFIG_QUOTA_DEBUG=y | ||||
| 
 | ||||
| 
 | ||||
| CONFIG_KGDB_KDB=y | ||||
| CONFIG_KDB_KEYBOARD=y | ||||
| CONFIG_KDB_CONTINUE_CATASTROPHIC=0 | ||||
| 
 | ||||
| # CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set | ||||
| CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y | ||||
| # CONFIG_PERCPU_TEST is not set | ||||
| # CONFIG_TEST_LIST_SORT is not set | ||||
| CONFIG_TEST_LIST_SORT=y | ||||
| # CONFIG_TEST_STRING_HELPERS is not set | ||||
| 
 | ||||
| # CONFIG_DETECT_HUNG_TASK is not set | ||||
| CONFIG_DETECT_HUNG_TASK=y | ||||
| CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 | ||||
| # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set | ||||
| 
 | ||||
| # CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set | ||||
| CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y | ||||
| 
 | ||||
| # CONFIG_DEBUG_KMEMLEAK is not set | ||||
| CONFIG_DEBUG_KMEMLEAK=y | ||||
| CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=1024 | ||||
| # CONFIG_DEBUG_KMEMLEAK_TEST is not set | ||||
| CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y | ||||
| @ -121,7 +121,7 @@ CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y | ||||
| 
 | ||||
| # CONFIG_SPI_DEBUG is not set | ||||
| 
 | ||||
| # CONFIG_X86_DEBUG_STATIC_CPU_HAS is not set | ||||
| CONFIG_X86_DEBUG_STATIC_CPU_HAS=y | ||||
| 
 | ||||
| # CONFIG_SCHEDSTATS is not set | ||||
| # CONFIG_LATENCYTOP is not set | ||||
|  | ||||
| @ -337,7 +337,7 @@ CONFIG_SP5100_TCO=m | ||||
| 
 | ||||
| # CONFIG_MEMTEST is not set | ||||
| # CONFIG_DEBUG_TLBFLUSH is not set | ||||
| # CONFIG_MAXSMP is not set | ||||
| CONFIG_MAXSMP=y | ||||
| 
 | ||||
| 
 | ||||
| CONFIG_HP_ILO=m | ||||
|  | ||||
							
								
								
									
										15
									
								
								kernel.spec
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								kernel.spec
									
									
									
									
									
								
							| @ -69,7 +69,7 @@ Summary: The Linux kernel | ||||
| # The rc snapshot level | ||||
| %define rcrev 2 | ||||
| # The git snapshot level | ||||
| %define gitrev 0 | ||||
| %define gitrev 1 | ||||
| # Set rpm version accordingly | ||||
| %define rpmversion 3.%{upstream_sublevel}.0 | ||||
| %endif | ||||
| @ -124,7 +124,7 @@ Summary: The Linux kernel | ||||
| # Set debugbuildsenabled to 1 for production (build separate debug kernels) | ||||
| #  and 0 for rawhide (all kernels are debug kernels). | ||||
| # See also 'make debug' and 'make release'. | ||||
| %define debugbuildsenabled 1 | ||||
| %define debugbuildsenabled 0 | ||||
| 
 | ||||
| # Want to build a vanilla kernel build without any non-upstream patches? | ||||
| %define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0} | ||||
| @ -620,6 +620,9 @@ Patch26058: asus-nb-wmi-Add-wapf4-quirk-for-the-X550VB.patch | ||||
| #rhbz 1111138 | ||||
| Patch26059: i8042-Add-notimeout-quirk-for-Fujitsu-Lifebook-A544-.patch | ||||
| 
 | ||||
| Patch26060: rcu-More-on-deadlock-between-CPU-hotplug-and-expedit.patch | ||||
| Patch26061: rcu-Make-rcu_barrier-understand-about-missing-rcuo-k.patch | ||||
| 
 | ||||
| # git clone ssh://git.fedorahosted.org/git/kernel-arm64.git, git diff master...devel | ||||
| Patch30000: kernel-arm64.patch | ||||
| 
 | ||||
| @ -1349,6 +1352,9 @@ ApplyPatch asus-nb-wmi-Add-wapf4-quirk-for-the-X550VB.patch | ||||
| #rhbz 1111138 | ||||
| ApplyPatch i8042-Add-notimeout-quirk-for-Fujitsu-Lifebook-A544-.patch | ||||
| 
 | ||||
| ApplyPatch rcu-More-on-deadlock-between-CPU-hotplug-and-expedit.patch | ||||
| ApplyPatch rcu-Make-rcu_barrier-understand-about-missing-rcuo-k.patch | ||||
| 
 | ||||
| %if 0%{?aarch64patches} | ||||
| ApplyPatch kernel-arm64.patch | ||||
| %ifnarch aarch64 # this is stupid, but i want to notice before secondary koji does. | ||||
| @ -2217,6 +2223,11 @@ fi | ||||
| #                                    ||----w | | ||||
| #                                    ||     || | ||||
| %changelog | ||||
| * Tue Oct 28 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.18.0-0.rc2.git1.1 | ||||
| - Linux v3.18-rc2-43-gf7e87a44ef60 | ||||
| - Add two RCU patches to fix a deadlock and a hang | ||||
| - Reenable debugging options. | ||||
| 
 | ||||
| * Mon Oct 27 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.18.0-0.rc2.git0.1 | ||||
| - Linux v3.18-rc2 | ||||
| - Disable debugging options. | ||||
|  | ||||
							
								
								
									
										177
									
								
								rcu-Make-rcu_barrier-understand-about-missing-rcuo-k.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								rcu-Make-rcu_barrier-understand-about-missing-rcuo-k.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,177 @@ | ||||
| From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> | ||||
| Date: Mon, 27 Oct 2014 09:15:54 -0700 | ||||
| Subject: [PATCH] rcu: Make rcu_barrier() understand about missing rcuo | ||||
|  kthreads | ||||
| 
 | ||||
| Commit 35ce7f29a44a (rcu: Create rcuo kthreads only for onlined CPUs) | ||||
| avoids creating rcuo kthreads for CPUs that never come online.  This | ||||
| fixes a bug in many instances of firmware: Instead of lying about their | ||||
| age, these systems instead lie about the number of CPUs that they have. | ||||
| Before commit 35ce7f29a44a, this could result in huge numbers of useless | ||||
| rcuo kthreads being created. | ||||
| 
 | ||||
| It appears that experience indicates that I should have told the | ||||
| people suffering from this problem to fix their broken firmware, but | ||||
| I instead produced what turned out to be a partial fix.   The missing | ||||
| piece supplied by this commit makes sure that rcu_barrier() knows not to | ||||
| post callbacks for no-CBs CPUs that have not yet come online, because | ||||
| otherwise rcu_barrier() will hang on systems having firmware that lies | ||||
| about the number of CPUs. | ||||
| 
 | ||||
| It is tempting to simply have rcu_barrier() refuse to post a callback on | ||||
| any no-CBs CPU that does not have an rcuo kthread.  This unfortunately | ||||
| does not work because rcu_barrier() is required to wait for all pending | ||||
| callbacks.  It is therefore required to wait even for those callbacks | ||||
| that cannot possibly be invoked.  Even if doing so hangs the system. | ||||
| 
 | ||||
| Given that posting a callback to a no-CBs CPU that does not yet have an | ||||
| rcuo kthread can hang rcu_barrier(), It is tempting to report an error | ||||
| in this case.  Unfortunately, this will result in false positives at | ||||
| boot time, when it is perfectly legal to post callbacks to the boot CPU | ||||
| before the scheduler has started, in other words, before it is legal | ||||
| to invoke rcu_barrier(). | ||||
| 
 | ||||
| So this commit instead has rcu_barrier() avoid posting callbacks to | ||||
| CPUs having neither rcuo kthread nor pending callbacks, and has it | ||||
| complain bitterly if it finds CPUs having no rcuo kthread but some | ||||
| pending callbacks.  And when rcu_barrier() does find CPUs having no rcuo | ||||
| kthread but pending callbacks, as noted earlier, it has no choice but | ||||
| to hang indefinitely. | ||||
| 
 | ||||
| Reported-by: Yanko Kaneti <yaneti@declera.com> | ||||
| Reported-by: Jay Vosburgh <jay.vosburgh@canonical.com> | ||||
| Reported-by: Meelis Roos <mroos@linux.ee> | ||||
| Reported-by: Eric B Munson <emunson@akamai.com> | ||||
| Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||||
| Tested-by: Eric B Munson <emunson@akamai.com> | ||||
| ---
 | ||||
|  include/trace/events/rcu.h | 18 +++++++++--------- | ||||
|  kernel/rcu/tree.c          | 15 ++++++++++----- | ||||
|  kernel/rcu/tree.h          |  1 + | ||||
|  kernel/rcu/tree_plugin.h   | 33 +++++++++++++++++++++++++++++++++ | ||||
|  4 files changed, 53 insertions(+), 14 deletions(-) | ||||
| 
 | ||||
| diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
 | ||||
| index 9b56f37148cf..e335e7d8c6c2 100644
 | ||||
| --- a/include/trace/events/rcu.h
 | ||||
| +++ b/include/trace/events/rcu.h
 | ||||
| @@ -660,18 +660,18 @@ TRACE_EVENT(rcu_torture_read,
 | ||||
|  /* | ||||
|   * Tracepoint for _rcu_barrier() execution.  The string "s" describes | ||||
|   * the _rcu_barrier phase: | ||||
| - *	"Begin": rcu_barrier_callback() started.
 | ||||
| - *	"Check": rcu_barrier_callback() checking for piggybacking.
 | ||||
| - *	"EarlyExit": rcu_barrier_callback() piggybacked, thus early exit.
 | ||||
| - *	"Inc1": rcu_barrier_callback() piggyback check counter incremented.
 | ||||
| - *	"Offline": rcu_barrier_callback() found offline CPU
 | ||||
| - *	"OnlineNoCB": rcu_barrier_callback() found online no-CBs CPU.
 | ||||
| - *	"OnlineQ": rcu_barrier_callback() found online CPU with callbacks.
 | ||||
| - *	"OnlineNQ": rcu_barrier_callback() found online CPU, no callbacks.
 | ||||
| + *	"Begin": _rcu_barrier() started.
 | ||||
| + *	"Check": _rcu_barrier() checking for piggybacking.
 | ||||
| + *	"EarlyExit": _rcu_barrier() piggybacked, thus early exit.
 | ||||
| + *	"Inc1": _rcu_barrier() piggyback check counter incremented.
 | ||||
| + *	"OfflineNoCB": _rcu_barrier() found callback on never-online CPU
 | ||||
| + *	"OnlineNoCB": _rcu_barrier() found online no-CBs CPU.
 | ||||
| + *	"OnlineQ": _rcu_barrier() found online CPU with callbacks.
 | ||||
| + *	"OnlineNQ": _rcu_barrier() found online CPU, no callbacks.
 | ||||
|   *	"IRQ": An rcu_barrier_callback() callback posted on remote CPU. | ||||
|   *	"CB": An rcu_barrier_callback() invoked a callback, not the last. | ||||
|   *	"LastCB": An rcu_barrier_callback() invoked the last callback. | ||||
| - *	"Inc2": rcu_barrier_callback() piggyback check counter incremented.
 | ||||
| + *	"Inc2": _rcu_barrier() piggyback check counter incremented.
 | ||||
|   * The "cpu" argument is the CPU or -1 if meaningless, the "cnt" argument | ||||
|   * is the count of remaining callbacks, and "done" is the piggybacking count. | ||||
|   */ | ||||
| diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
 | ||||
| index 133e47223095..9815447d22e0 100644
 | ||||
| --- a/kernel/rcu/tree.c
 | ||||
| +++ b/kernel/rcu/tree.c
 | ||||
| @@ -3299,11 +3299,16 @@ static void _rcu_barrier(struct rcu_state *rsp)
 | ||||
|  			continue; | ||||
|  		rdp = per_cpu_ptr(rsp->rda, cpu); | ||||
|  		if (rcu_is_nocb_cpu(cpu)) { | ||||
| -			_rcu_barrier_trace(rsp, "OnlineNoCB", cpu,
 | ||||
| -					   rsp->n_barrier_done);
 | ||||
| -			atomic_inc(&rsp->barrier_cpu_count);
 | ||||
| -			__call_rcu(&rdp->barrier_head, rcu_barrier_callback,
 | ||||
| -				   rsp, cpu, 0);
 | ||||
| +			if (!rcu_nocb_cpu_needs_barrier(rsp, cpu)) {
 | ||||
| +				_rcu_barrier_trace(rsp, "OfflineNoCB", cpu,
 | ||||
| +						   rsp->n_barrier_done);
 | ||||
| +			} else {
 | ||||
| +				_rcu_barrier_trace(rsp, "OnlineNoCB", cpu,
 | ||||
| +						   rsp->n_barrier_done);
 | ||||
| +				atomic_inc(&rsp->barrier_cpu_count);
 | ||||
| +				__call_rcu(&rdp->barrier_head,
 | ||||
| +					   rcu_barrier_callback, rsp, cpu, 0);
 | ||||
| +			}
 | ||||
|  		} else if (ACCESS_ONCE(rdp->qlen)) { | ||||
|  			_rcu_barrier_trace(rsp, "OnlineQ", cpu, | ||||
|  					   rsp->n_barrier_done); | ||||
| diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
 | ||||
| index d03764652d91..bbdc45d8d74f 100644
 | ||||
| --- a/kernel/rcu/tree.h
 | ||||
| +++ b/kernel/rcu/tree.h
 | ||||
| @@ -587,6 +587,7 @@ static void print_cpu_stall_info(struct rcu_state *rsp, int cpu);
 | ||||
|  static void print_cpu_stall_info_end(void); | ||||
|  static void zero_cpu_stall_ticks(struct rcu_data *rdp); | ||||
|  static void increment_cpu_stall_ticks(void); | ||||
| +static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu);
 | ||||
|  static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq); | ||||
|  static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp); | ||||
|  static void rcu_init_one_nocb(struct rcu_node *rnp); | ||||
| diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
 | ||||
| index 387dd4599344..c1d7f27bd38f 100644
 | ||||
| --- a/kernel/rcu/tree_plugin.h
 | ||||
| +++ b/kernel/rcu/tree_plugin.h
 | ||||
| @@ -2050,6 +2050,33 @@ static void wake_nocb_leader(struct rcu_data *rdp, bool force)
 | ||||
|  } | ||||
|   | ||||
|  /* | ||||
| + * Does the specified CPU need an RCU callback for the specified flavor
 | ||||
| + * of rcu_barrier()?
 | ||||
| + */
 | ||||
| +static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu)
 | ||||
| +{
 | ||||
| +	struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
 | ||||
| +	struct rcu_head *rhp;
 | ||||
| +
 | ||||
| +	/* No-CBs CPUs might have callbacks on any of three lists. */
 | ||||
| +	rhp = ACCESS_ONCE(rdp->nocb_head);
 | ||||
| +	if (!rhp)
 | ||||
| +		rhp = ACCESS_ONCE(rdp->nocb_gp_head);
 | ||||
| +	if (!rhp)
 | ||||
| +		rhp = ACCESS_ONCE(rdp->nocb_follower_head);
 | ||||
| +
 | ||||
| +	/* Having no rcuo kthread but CBs after scheduler starts is bad! */
 | ||||
| +	if (!ACCESS_ONCE(rdp->nocb_kthread) && rhp) {
 | ||||
| +		/* RCU callback enqueued before CPU first came online??? */
 | ||||
| +		pr_err("RCU: Never-onlined no-CBs CPU %d has CB %p\n",
 | ||||
| +		       cpu, rhp->func);
 | ||||
| +		WARN_ON_ONCE(1);
 | ||||
| +	}
 | ||||
| +
 | ||||
| +	return !!rhp;
 | ||||
| +}
 | ||||
| +
 | ||||
| +/*
 | ||||
|   * Enqueue the specified string of rcu_head structures onto the specified | ||||
|   * CPU's no-CBs lists.  The CPU is specified by rdp, the head of the | ||||
|   * string by rhp, and the tail of the string by rhtp.  The non-lazy/lazy | ||||
| @@ -2642,6 +2669,12 @@ static bool init_nocb_callback_list(struct rcu_data *rdp)
 | ||||
|   | ||||
|  #else /* #ifdef CONFIG_RCU_NOCB_CPU */ | ||||
|   | ||||
| +static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu)
 | ||||
| +{
 | ||||
| +	WARN_ON_ONCE(1); /* Should be dead code. */
 | ||||
| +	return false;
 | ||||
| +}
 | ||||
| +
 | ||||
|  static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) | ||||
|  { | ||||
|  } | ||||
| -- 
 | ||||
| 1.9.3 | ||||
| 
 | ||||
							
								
								
									
										67
									
								
								rcu-More-on-deadlock-between-CPU-hotplug-and-expedit.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								rcu-More-on-deadlock-between-CPU-hotplug-and-expedit.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> | ||||
| Date: Wed, 22 Oct 2014 10:00:05 -0700 | ||||
| Subject: [PATCH] rcu: More on deadlock between CPU hotplug and expedited grace | ||||
|  periods | ||||
| 
 | ||||
| Commit dd56af42bd82 (rcu: Eliminate deadlock between CPU hotplug and | ||||
| expedited grace periods) was incomplete.  Although it did eliminate | ||||
| deadlocks involving synchronize_sched_expedited()'s acquisition of | ||||
| cpu_hotplug.lock via get_online_cpus(), it did nothing about the similar | ||||
| deadlock involving acquisition of this same lock via put_online_cpus(). | ||||
| This deadlock became apparent with testing involving hibernation. | ||||
| 
 | ||||
| This commit therefore changes put_online_cpus() acquisition of this lock | ||||
| to be conditional, and increments a new cpu_hotplug.puts_pending field | ||||
| in case of acquisition failure.  Then cpu_hotplug_begin() checks for this | ||||
| new field being non-zero, and applies any changes to cpu_hotplug.refcount. | ||||
| 
 | ||||
| Reported-by: Jiri Kosina <jkosina@suse.cz> | ||||
| Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> | ||||
| Tested-by: Jiri Kosina <jkosina@suse.cz> | ||||
| Tested-by: Borislav Petkov <bp@suse.de> | ||||
| ---
 | ||||
|  kernel/cpu.c | 14 +++++++++++++- | ||||
|  1 file changed, 13 insertions(+), 1 deletion(-) | ||||
| 
 | ||||
| diff --git a/kernel/cpu.c b/kernel/cpu.c
 | ||||
| index 356450f09c1f..90a3d017b90c 100644
 | ||||
| --- a/kernel/cpu.c
 | ||||
| +++ b/kernel/cpu.c
 | ||||
| @@ -64,6 +64,8 @@ static struct {
 | ||||
|  	 * an ongoing cpu hotplug operation. | ||||
|  	 */ | ||||
|  	int refcount; | ||||
| +	/* And allows lockless put_online_cpus(). */
 | ||||
| +	atomic_t puts_pending;
 | ||||
|   | ||||
|  #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||||
|  	struct lockdep_map dep_map; | ||||
| @@ -113,7 +115,11 @@ void put_online_cpus(void)
 | ||||
|  { | ||||
|  	if (cpu_hotplug.active_writer == current) | ||||
|  		return; | ||||
| -	mutex_lock(&cpu_hotplug.lock);
 | ||||
| +	if (!mutex_trylock(&cpu_hotplug.lock)) {
 | ||||
| +		atomic_inc(&cpu_hotplug.puts_pending);
 | ||||
| +		cpuhp_lock_release();
 | ||||
| +		return;
 | ||||
| +	}
 | ||||
|   | ||||
|  	if (WARN_ON(!cpu_hotplug.refcount)) | ||||
|  		cpu_hotplug.refcount++; /* try to fix things up */ | ||||
| @@ -155,6 +161,12 @@ void cpu_hotplug_begin(void)
 | ||||
|  	cpuhp_lock_acquire(); | ||||
|  	for (;;) { | ||||
|  		mutex_lock(&cpu_hotplug.lock); | ||||
| +		if (atomic_read(&cpu_hotplug.puts_pending)) {
 | ||||
| +			int delta;
 | ||||
| +
 | ||||
| +			delta = atomic_xchg(&cpu_hotplug.puts_pending, 0);
 | ||||
| +			cpu_hotplug.refcount -= delta;
 | ||||
| +		}
 | ||||
|  		if (likely(!cpu_hotplug.refcount)) | ||||
|  			break; | ||||
|  		__set_current_state(TASK_UNINTERRUPTIBLE); | ||||
| -- 
 | ||||
| 1.9.3 | ||||
| 
 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user