Commit f1d3e4dca3f8d4f55656477e83d0afe0ea7cbaed
Committed by
David S. Miller
1 parent
65dbd7c277
Exists in
master
and in
4 other branches
iucv: fix cpu hotplug
If the iucv module is compiled in/loaded but no user is registered cpu hot remove doesn't work. Reason for that is that the iucv cpu hotplug notifier on CPU_DOWN_PREPARE checks if the iucv_buffer_cpumask would be empty after the corresponding bit would be cleared. However the bit was never set since iucv wasn't enable. That causes all cpu hot unplug operations to fail in this scenario. To fix this use iucv_path_table as an indicator wether iucv is enabled or not. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 11 additions and 7 deletions Side-by-side Diff
net/iucv/iucv.c
... | ... | @@ -517,6 +517,7 @@ |
517 | 517 | size_t alloc_size; |
518 | 518 | int cpu, rc; |
519 | 519 | |
520 | + get_online_cpus(); | |
520 | 521 | rc = -ENOMEM; |
521 | 522 | alloc_size = iucv_max_pathid * sizeof(struct iucv_path); |
522 | 523 | iucv_path_table = kzalloc(alloc_size, GFP_KERNEL); |
523 | 524 | |
524 | 525 | |
525 | 526 | |
... | ... | @@ -524,19 +525,17 @@ |
524 | 525 | goto out; |
525 | 526 | /* Declare per cpu buffers. */ |
526 | 527 | rc = -EIO; |
527 | - get_online_cpus(); | |
528 | 528 | for_each_online_cpu(cpu) |
529 | 529 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); |
530 | 530 | if (cpus_empty(iucv_buffer_cpumask)) |
531 | 531 | /* No cpu could declare an iucv buffer. */ |
532 | - goto out_path; | |
532 | + goto out; | |
533 | 533 | put_online_cpus(); |
534 | 534 | return 0; |
535 | - | |
536 | -out_path: | |
537 | - put_online_cpus(); | |
538 | - kfree(iucv_path_table); | |
539 | 535 | out: |
536 | + kfree(iucv_path_table); | |
537 | + iucv_path_table = NULL; | |
538 | + put_online_cpus(); | |
540 | 539 | return rc; |
541 | 540 | } |
542 | 541 | |
543 | 542 | |
... | ... | @@ -551,8 +550,9 @@ |
551 | 550 | { |
552 | 551 | get_online_cpus(); |
553 | 552 | on_each_cpu(iucv_retrieve_cpu, NULL, 1); |
554 | - put_online_cpus(); | |
555 | 553 | kfree(iucv_path_table); |
554 | + iucv_path_table = NULL; | |
555 | + put_online_cpus(); | |
556 | 556 | } |
557 | 557 | |
558 | 558 | static int __cpuinit iucv_cpu_notify(struct notifier_block *self, |
559 | 559 | |
... | ... | @@ -589,10 +589,14 @@ |
589 | 589 | case CPU_ONLINE_FROZEN: |
590 | 590 | case CPU_DOWN_FAILED: |
591 | 591 | case CPU_DOWN_FAILED_FROZEN: |
592 | + if (!iucv_path_table) | |
593 | + break; | |
592 | 594 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); |
593 | 595 | break; |
594 | 596 | case CPU_DOWN_PREPARE: |
595 | 597 | case CPU_DOWN_PREPARE_FROZEN: |
598 | + if (!iucv_path_table) | |
599 | + break; | |
596 | 600 | cpumask = iucv_buffer_cpumask; |
597 | 601 | cpu_clear(cpu, cpumask); |
598 | 602 | if (cpus_empty(cpumask)) |