From: Greg Kroah-Hartman Date: Fri, 5 May 2017 18:42:26 +0000 (-0700) Subject: 4.9-stable patches X-Git-Tag: v3.18.52~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=81bf61bbbb88a3e026e6bfdc8e38306359118781;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: cpu-hotplug-serialize-callback-invocations-proper.patch --- diff --git a/queue-4.9/cpu-hotplug-serialize-callback-invocations-proper.patch b/queue-4.9/cpu-hotplug-serialize-callback-invocations-proper.patch new file mode 100644 index 00000000000..134ab5c5c91 --- /dev/null +++ b/queue-4.9/cpu-hotplug-serialize-callback-invocations-proper.patch @@ -0,0 +1,146 @@ +From dc434e056fe1dada20df7ba07f32739d3a701adf Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior +Date: Tue, 14 Mar 2017 16:06:45 +0100 +Subject: cpu/hotplug: Serialize callback invocations proper + +From: Sebastian Andrzej Siewior + +commit dc434e056fe1dada20df7ba07f32739d3a701adf upstream. + +The setup/remove_state/instance() functions in the hotplug core code are +serialized against concurrent CPU hotplug, but unfortunately not serialized +against themself. + +As a consequence a concurrent invocation of these function results in +corruption of the callback machinery because two instances try to invoke +callbacks on remote cpus at the same time. This results in missing callback +invocations and initiator threads waiting forever on the completion. + +The obvious solution to replace get_cpu_online() with cpu_hotplug_begin() +is not possible because at least one callsite calls into these functions +from a get_online_cpu() locked region. + +Extend the protection scope of the cpuhp_state_mutex from solely protecting +the state arrays to cover the callback invocation machinery as well. + +Fixes: 5b7aa87e0482 ("cpu/hotplug: Implement setup/removal interface") +Reported-and-tested-by: Bart Van Assche +Signed-off-by: Sebastian Andrzej Siewior +Cc: hpa@zytor.com +Cc: mingo@kernel.org +Cc: akpm@linux-foundation.org +Cc: torvalds@linux-foundation.org +Link: http://lkml.kernel.org/r/20170314150645.g4tdyoszlcbajmna@linutronix.de +Signed-off-by: Thomas Gleixner +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/cpu.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -1441,14 +1441,12 @@ static void cpuhp_store_callbacks(enum c + /* (Un)Install the callbacks for further cpu hotplug operations */ + struct cpuhp_step *sp; + +- mutex_lock(&cpuhp_state_mutex); + sp = cpuhp_get_step(state); + sp->startup.single = startup; + sp->teardown.single = teardown; + sp->name = name; + sp->multi_instance = multi_instance; + INIT_HLIST_HEAD(&sp->list); +- mutex_unlock(&cpuhp_state_mutex); + } + + static void *cpuhp_get_teardown_cb(enum cpuhp_state state) +@@ -1518,16 +1516,13 @@ static int cpuhp_reserve_state(enum cpuh + { + enum cpuhp_state i; + +- mutex_lock(&cpuhp_state_mutex); + for (i = CPUHP_AP_ONLINE_DYN; i <= CPUHP_AP_ONLINE_DYN_END; i++) { + if (cpuhp_ap_states[i].name) + continue; + + cpuhp_ap_states[i].name = "Reserved"; +- mutex_unlock(&cpuhp_state_mutex); + return i; + } +- mutex_unlock(&cpuhp_state_mutex); + WARN(1, "No more dynamic states available for CPU hotplug\n"); + return -ENOSPC; + } +@@ -1544,6 +1539,7 @@ int __cpuhp_state_add_instance(enum cpuh + return -EINVAL; + + get_online_cpus(); ++ mutex_lock(&cpuhp_state_mutex); + + if (!invoke || !sp->startup.multi) + goto add_node; +@@ -1568,11 +1564,10 @@ int __cpuhp_state_add_instance(enum cpuh + } + add_node: + ret = 0; +- mutex_lock(&cpuhp_state_mutex); + hlist_add_head(node, &sp->list); +- mutex_unlock(&cpuhp_state_mutex); + + err: ++ mutex_unlock(&cpuhp_state_mutex); + put_online_cpus(); + return ret; + } +@@ -1601,6 +1596,7 @@ int __cpuhp_setup_state(enum cpuhp_state + return -EINVAL; + + get_online_cpus(); ++ mutex_lock(&cpuhp_state_mutex); + + /* currently assignments for the ONLINE state are possible */ + if (state == CPUHP_AP_ONLINE_DYN) { +@@ -1636,6 +1632,8 @@ int __cpuhp_setup_state(enum cpuhp_state + } + } + out: ++ mutex_unlock(&cpuhp_state_mutex); ++ + put_online_cpus(); + if (!ret && dyn_state) + return state; +@@ -1655,6 +1653,8 @@ int __cpuhp_state_remove_instance(enum c + return -EINVAL; + + get_online_cpus(); ++ mutex_lock(&cpuhp_state_mutex); ++ + if (!invoke || !cpuhp_get_teardown_cb(state)) + goto remove; + /* +@@ -1671,7 +1671,6 @@ int __cpuhp_state_remove_instance(enum c + } + + remove: +- mutex_lock(&cpuhp_state_mutex); + hlist_del(node); + mutex_unlock(&cpuhp_state_mutex); + put_online_cpus(); +@@ -1696,6 +1695,7 @@ void __cpuhp_remove_state(enum cpuhp_sta + BUG_ON(cpuhp_cb_check(state)); + + get_online_cpus(); ++ mutex_lock(&cpuhp_state_mutex); + + if (sp->multi_instance) { + WARN(!hlist_empty(&sp->list), +@@ -1721,6 +1721,7 @@ void __cpuhp_remove_state(enum cpuhp_sta + } + remove: + cpuhp_store_callbacks(state, NULL, NULL, NULL, false); ++ mutex_unlock(&cpuhp_state_mutex); + put_online_cpus(); + } + EXPORT_SYMBOL(__cpuhp_remove_state); diff --git a/queue-4.9/series b/queue-4.9/series index 93143cd3b79..af721a62522 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -5,3 +5,4 @@ scsi-storvsc-workaround-for-virtual-dvd-scsi-version.patch hwmon-it87-avoid-registering-the-same-chip-on-both-sio-addresses.patch 8250_pci-fix-potential-use-after-free-in-error-path.patch ceph-try-getting-buffer-capability-for-readahead-fadvise.patch +cpu-hotplug-serialize-callback-invocations-proper.patch