diff options
| -rw-r--r-- | kernel/padata.c | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/kernel/padata.c b/kernel/padata.c index 9e18dfa372a9..57ec4eb5f2e3 100644 --- a/kernel/padata.c +++ b/kernel/padata.c | |||
| @@ -516,12 +516,27 @@ static void padata_replace(struct padata_instance *pinst, | |||
| 516 | 516 | ||
| 517 | synchronize_rcu(); | 517 | synchronize_rcu(); |
| 518 | 518 | ||
| 519 | padata_flush_queues(pd_old); | 519 | if (pd_old) { |
| 520 | padata_free_pd(pd_old); | 520 | padata_flush_queues(pd_old); |
| 521 | padata_free_pd(pd_old); | ||
| 522 | } | ||
| 521 | 523 | ||
| 522 | pinst->flags &= ~PADATA_RESET; | 524 | pinst->flags &= ~PADATA_RESET; |
| 523 | } | 525 | } |
| 524 | 526 | ||
| 527 | /* If cpumask contains no active cpu, we mark the instance as invalid. */ | ||
| 528 | static bool padata_validate_cpumask(struct padata_instance *pinst, | ||
| 529 | const struct cpumask *cpumask) | ||
| 530 | { | ||
| 531 | if (!cpumask_intersects(cpumask, cpu_active_mask)) { | ||
| 532 | pinst->flags |= PADATA_INVALID; | ||
| 533 | return false; | ||
| 534 | } | ||
| 535 | |||
| 536 | pinst->flags &= ~PADATA_INVALID; | ||
| 537 | return true; | ||
| 538 | } | ||
| 539 | |||
| 525 | /** | 540 | /** |
| 526 | * padata_set_cpumask - set the cpumask that padata should use | 541 | * padata_set_cpumask - set the cpumask that padata should use |
| 527 | * | 542 | * |
| @@ -531,11 +546,18 @@ static void padata_replace(struct padata_instance *pinst, | |||
| 531 | int padata_set_cpumask(struct padata_instance *pinst, | 546 | int padata_set_cpumask(struct padata_instance *pinst, |
| 532 | cpumask_var_t cpumask) | 547 | cpumask_var_t cpumask) |
| 533 | { | 548 | { |
| 534 | struct parallel_data *pd; | 549 | int valid; |
| 535 | int err = 0; | 550 | int err = 0; |
| 551 | struct parallel_data *pd = NULL; | ||
| 536 | 552 | ||
| 537 | mutex_lock(&pinst->lock); | 553 | mutex_lock(&pinst->lock); |
| 538 | 554 | ||
| 555 | valid = padata_validate_cpumask(pinst, cpumask); | ||
| 556 | if (!valid) { | ||
| 557 | __padata_stop(pinst); | ||
| 558 | goto out_replace; | ||
| 559 | } | ||
| 560 | |||
| 539 | get_online_cpus(); | 561 | get_online_cpus(); |
| 540 | 562 | ||
| 541 | pd = padata_alloc_pd(pinst, cpumask); | 563 | pd = padata_alloc_pd(pinst, cpumask); |
| @@ -544,10 +566,14 @@ int padata_set_cpumask(struct padata_instance *pinst, | |||
| 544 | goto out; | 566 | goto out; |
| 545 | } | 567 | } |
| 546 | 568 | ||
| 569 | out_replace: | ||
| 547 | cpumask_copy(pinst->cpumask, cpumask); | 570 | cpumask_copy(pinst->cpumask, cpumask); |
| 548 | 571 | ||
| 549 | padata_replace(pinst, pd); | 572 | padata_replace(pinst, pd); |
| 550 | 573 | ||
| 574 | if (valid) | ||
| 575 | __padata_start(pinst); | ||
| 576 | |||
| 551 | out: | 577 | out: |
| 552 | put_online_cpus(); | 578 | put_online_cpus(); |
| 553 | 579 | ||
| @@ -567,6 +593,9 @@ static int __padata_add_cpu(struct padata_instance *pinst, int cpu) | |||
| 567 | return -ENOMEM; | 593 | return -ENOMEM; |
| 568 | 594 | ||
| 569 | padata_replace(pinst, pd); | 595 | padata_replace(pinst, pd); |
| 596 | |||
| 597 | if (padata_validate_cpumask(pinst, pinst->cpumask)) | ||
| 598 | __padata_start(pinst); | ||
| 570 | } | 599 | } |
| 571 | 600 | ||
| 572 | return 0; | 601 | return 0; |
| @@ -597,9 +626,16 @@ EXPORT_SYMBOL(padata_add_cpu); | |||
| 597 | 626 | ||
| 598 | static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) | 627 | static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) |
| 599 | { | 628 | { |
| 600 | struct parallel_data *pd; | 629 | struct parallel_data *pd = NULL; |
| 601 | 630 | ||
| 602 | if (cpumask_test_cpu(cpu, cpu_online_mask)) { | 631 | if (cpumask_test_cpu(cpu, cpu_online_mask)) { |
| 632 | |||
| 633 | if (!padata_validate_cpumask(pinst, pinst->cpumask)) { | ||
| 634 | __padata_stop(pinst); | ||
| 635 | padata_replace(pinst, pd); | ||
| 636 | goto out; | ||
| 637 | } | ||
| 638 | |||
| 603 | pd = padata_alloc_pd(pinst, pinst->cpumask); | 639 | pd = padata_alloc_pd(pinst, pinst->cpumask); |
| 604 | if (!pd) | 640 | if (!pd) |
| 605 | return -ENOMEM; | 641 | return -ENOMEM; |
| @@ -607,6 +643,7 @@ static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) | |||
| 607 | padata_replace(pinst, pd); | 643 | padata_replace(pinst, pd); |
| 608 | } | 644 | } |
| 609 | 645 | ||
| 646 | out: | ||
| 610 | return 0; | 647 | return 0; |
| 611 | } | 648 | } |
| 612 | 649 | ||
| @@ -732,7 +769,7 @@ struct padata_instance *padata_alloc(const struct cpumask *cpumask, | |||
| 732 | struct workqueue_struct *wq) | 769 | struct workqueue_struct *wq) |
| 733 | { | 770 | { |
| 734 | struct padata_instance *pinst; | 771 | struct padata_instance *pinst; |
| 735 | struct parallel_data *pd; | 772 | struct parallel_data *pd = NULL; |
| 736 | 773 | ||
| 737 | pinst = kzalloc(sizeof(struct padata_instance), GFP_KERNEL); | 774 | pinst = kzalloc(sizeof(struct padata_instance), GFP_KERNEL); |
| 738 | if (!pinst) | 775 | if (!pinst) |
| @@ -740,12 +777,14 @@ struct padata_instance *padata_alloc(const struct cpumask *cpumask, | |||
| 740 | 777 | ||
| 741 | get_online_cpus(); | 778 | get_online_cpus(); |
| 742 | 779 | ||
| 743 | pd = padata_alloc_pd(pinst, cpumask); | 780 | if (!alloc_cpumask_var(&pinst->cpumask, GFP_KERNEL)) |
| 744 | if (!pd) | ||
| 745 | goto err_free_inst; | 781 | goto err_free_inst; |
| 746 | 782 | ||
| 747 | if (!alloc_cpumask_var(&pinst->cpumask, GFP_KERNEL)) | 783 | if (padata_validate_cpumask(pinst, cpumask)) { |
| 748 | goto err_free_pd; | 784 | pd = padata_alloc_pd(pinst, cpumask); |
| 785 | if (!pd) | ||
| 786 | goto err_free_mask; | ||
| 787 | } | ||
| 749 | 788 | ||
| 750 | rcu_assign_pointer(pinst->pd, pd); | 789 | rcu_assign_pointer(pinst->pd, pd); |
| 751 | 790 | ||
| @@ -767,8 +806,8 @@ struct padata_instance *padata_alloc(const struct cpumask *cpumask, | |||
| 767 | 806 | ||
| 768 | return pinst; | 807 | return pinst; |
| 769 | 808 | ||
| 770 | err_free_pd: | 809 | err_free_mask: |
| 771 | padata_free_pd(pd); | 810 | free_cpumask_var(pinst->cpumask); |
| 772 | err_free_inst: | 811 | err_free_inst: |
| 773 | kfree(pinst); | 812 | kfree(pinst); |
| 774 | put_online_cpus(); | 813 | put_online_cpus(); |
