aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/padata.c
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2010-07-07 09:31:26 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2010-07-14 08:29:29 -0400
commit33e54450683c5e970ac007489d7921ba792d093c (patch)
tree1e3d0a7fcc007bfa97c88c68d411b8e1691bb7e5 /kernel/padata.c
parentee836555120140f770005b8ce6673c913d1b9a98 (diff)
padata: Handle empty padata cpumasks
This patch fixes a bug when the padata cpumask does not intersect with the active cpumask. In this case we get a division by zero in padata_alloc_pd and we end up with a useless padata instance. Padata can end up with an empty cpumask for two reasons: 1. A user removed the last cpu that belongs to the padata cpumask and the active cpumask. 2. The last cpu that belongs to the padata cpumask and the active cpumask goes offline. We introduce a function padata_validate_cpumask to check if the padata cpumask does intersect with the active cpumask. If the cpumasks do not intersect we mark the instance as invalid, so it can't be used. We do not allocate the cpumask dependend recources in this case. This fixes the division by zero and keeps the padate instance in a consistent state. It's not possible to trigger this bug by now because the only padata user, pcrypt uses always the possible cpumask. Reported-by: Dan Kruchinin <dkruchinin@acm.org> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'kernel/padata.c')
-rw-r--r--kernel/padata.c61
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. */
528static 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,
531int padata_set_cpumask(struct padata_instance *pinst, 546int 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
569out_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
551out: 577out:
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
598static int __padata_remove_cpu(struct padata_instance *pinst, int cpu) 627static 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
646out:
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
770err_free_pd: 809err_free_mask:
771 padata_free_pd(pd); 810 free_cpumask_var(pinst->cpumask);
772err_free_inst: 811err_free_inst:
773 kfree(pinst); 812 kfree(pinst);
774 put_online_cpus(); 813 put_online_cpus();