]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.14.97/s390-smp-fix-cpu-hotplug-deadlock-with-cpu-rescan.patch
Linux 4.14.97
[thirdparty/kernel/stable-queue.git] / releases / 4.14.97 / s390-smp-fix-cpu-hotplug-deadlock-with-cpu-rescan.patch
CommitLineData
8b80b9d4
GKH
1From b7cb707c373094ce4008d4a6ac9b6b366ec52da5 Mon Sep 17 00:00:00 2001
2From: Gerald Schaefer <gerald.schaefer@de.ibm.com>
3Date: Wed, 9 Jan 2019 13:00:03 +0100
4Subject: s390/smp: fix CPU hotplug deadlock with CPU rescan
5
6From: Gerald Schaefer <gerald.schaefer@de.ibm.com>
7
8commit b7cb707c373094ce4008d4a6ac9b6b366ec52da5 upstream.
9
10smp_rescan_cpus() is called without the device_hotplug_lock, which can lead
11to a dedlock when a new CPU is found and immediately set online by a udev
12rule.
13
14This was observed on an older kernel version, where the cpu_hotplug_begin()
15loop was still present, and it resulted in hanging chcpu and systemd-udev
16processes. This specific deadlock will not show on current kernels. However,
17there may be other possible deadlocks, and since smp_rescan_cpus() can still
18trigger a CPU hotplug operation, the device_hotplug_lock should be held.
19
20For reference, this was the deadlock with the old cpu_hotplug_begin() loop:
21
22 chcpu (rescan) systemd-udevd
23
24 echo 1 > /sys/../rescan
25 -> smp_rescan_cpus()
26 -> (*) get_online_cpus()
27 (increases refcount)
28 -> smp_add_present_cpu()
29 (new CPU found)
30 -> register_cpu()
31 -> device_add()
32 -> udev "add" event triggered -----------> udev rule sets CPU online
33 -> echo 1 > /sys/.../online
34 -> lock_device_hotplug_sysfs()
35 (this is missing in rescan path)
36 -> device_online()
37 -> (**) device_lock(new CPU dev)
38 -> cpu_up()
39 -> cpu_hotplug_begin()
40 (loops until refcount == 0)
41 -> deadlock with (*)
42 -> bus_probe_device()
43 -> device_attach()
44 -> device_lock(new CPU dev)
45 -> deadlock with (**)
46
47Fix this by taking the device_hotplug_lock in the CPU rescan path.
48
49Cc: <stable@vger.kernel.org>
50Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
51Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
52Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
53
54---
55 arch/s390/kernel/smp.c | 4 ++++
56 drivers/s390/char/sclp_config.c | 2 ++
57 2 files changed, 6 insertions(+)
58
59--- a/arch/s390/kernel/smp.c
60+++ b/arch/s390/kernel/smp.c
61@@ -1168,7 +1168,11 @@ static ssize_t __ref rescan_store(struct
62 {
63 int rc;
64
65+ rc = lock_device_hotplug_sysfs();
66+ if (rc)
67+ return rc;
68 rc = smp_rescan_cpus();
69+ unlock_device_hotplug();
70 return rc ? rc : count;
71 }
72 static DEVICE_ATTR(rescan, 0200, NULL, rescan_store);
73--- a/drivers/s390/char/sclp_config.c
74+++ b/drivers/s390/char/sclp_config.c
75@@ -60,7 +60,9 @@ static void sclp_cpu_capability_notify(s
76
77 static void __ref sclp_cpu_change_notify(struct work_struct *work)
78 {
79+ lock_device_hotplug();
80 smp_rescan_cpus();
81+ unlock_device_hotplug();
82 }
83
84 static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)