]>
Commit | Line | Data |
---|---|---|
6a930a95 BS |
1 | From: Gerald Schaefer <geraldsc@de.ibm.com> |
2 | Subject: iucv: failing cpu hot remove for inactive iucv | |
3 | References: bnc#466462,LTC#51104 | |
4 | ||
5 | Symptom: cpu hot remove rejected with NOTIFY_BAD | |
6 | Problem: If the iucv module is compiled in / loaded but no user | |
7 | is registered, cpu hot remove doesn't work. The iucv | |
8 | cpu hotplug notifier on CPU_DOWN_PREPARE checks, if | |
9 | the iucv_buffer_cpumask would be empty after the | |
10 | corresponding bit would be cleared. However the bit | |
11 | was never set since iucv wasn't enabled. That causes | |
12 | all cpu hot unplug operations to fail in this scenario. | |
13 | Solution: Use iucv_path_table as an indicator whether iucv is | |
14 | enabled or not. | |
15 | ||
16 | Acked-by: John Jolly <jjolly@suse.de> | |
17 | --- | |
18 | ||
19 | net/iucv/iucv.c | 18 +++++++++++------- | |
20 | 1 file changed, 11 insertions(+), 7 deletions(-) | |
21 | ||
22 | Index: linux-sles11/net/iucv/iucv.c | |
23 | =================================================================== | |
24 | --- linux-sles11.orig/net/iucv/iucv.c | |
25 | +++ linux-sles11/net/iucv/iucv.c | |
26 | @@ -516,6 +516,7 @@ static int iucv_enable(void) | |
27 | size_t alloc_size; | |
28 | int cpu, rc; | |
29 | ||
30 | + get_online_cpus(); | |
31 | rc = -ENOMEM; | |
32 | alloc_size = iucv_max_pathid * sizeof(struct iucv_path); | |
33 | iucv_path_table = kzalloc(alloc_size, GFP_KERNEL); | |
34 | @@ -523,19 +524,17 @@ static int iucv_enable(void) | |
35 | goto out; | |
36 | /* Declare per cpu buffers. */ | |
37 | rc = -EIO; | |
38 | - get_online_cpus(); | |
39 | for_each_online_cpu(cpu) | |
40 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); | |
41 | if (cpus_empty(iucv_buffer_cpumask)) | |
42 | /* No cpu could declare an iucv buffer. */ | |
43 | - goto out_path; | |
44 | + goto out; | |
45 | put_online_cpus(); | |
46 | return 0; | |
47 | - | |
48 | -out_path: | |
49 | - put_online_cpus(); | |
50 | - kfree(iucv_path_table); | |
51 | out: | |
52 | + kfree(iucv_path_table); | |
53 | + iucv_path_table = NULL; | |
54 | + put_online_cpus(); | |
55 | return rc; | |
56 | } | |
57 | ||
58 | @@ -550,8 +549,9 @@ static void iucv_disable(void) | |
59 | { | |
60 | get_online_cpus(); | |
61 | on_each_cpu(iucv_retrieve_cpu, NULL, 1); | |
62 | - put_online_cpus(); | |
63 | kfree(iucv_path_table); | |
64 | + iucv_path_table = NULL; | |
65 | + put_online_cpus(); | |
66 | } | |
67 | ||
68 | static int __cpuinit iucv_cpu_notify(struct notifier_block *self, | |
69 | @@ -588,10 +588,14 @@ static int __cpuinit iucv_cpu_notify(str | |
70 | case CPU_ONLINE_FROZEN: | |
71 | case CPU_DOWN_FAILED: | |
72 | case CPU_DOWN_FAILED_FROZEN: | |
73 | + if (!iucv_path_table) | |
74 | + break; | |
75 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); | |
76 | break; | |
77 | case CPU_DOWN_PREPARE: | |
78 | case CPU_DOWN_PREPARE_FROZEN: | |
79 | + if (!iucv_path_table) | |
80 | + break; | |
81 | cpumask = iucv_buffer_cpumask; | |
82 | cpu_clear(cpu, cpumask); | |
83 | if (cpus_empty(cpumask)) |