diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 927692734bcf..8e7e135d0817 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -485,6 +485,20 @@ static void mm_init_aio(struct mm_struct *mm) | |||
485 | #endif | 485 | #endif |
486 | } | 486 | } |
487 | 487 | ||
488 | int mm_init_cpumask(struct mm_struct *mm, struct mm_struct *oldmm) | ||
489 | { | ||
490 | #ifdef CONFIG_CPUMASK_OFFSTACK | ||
491 | if (!alloc_cpumask_var(&mm->cpu_vm_mask_var, GFP_KERNEL)) | ||
492 | return -ENOMEM; | ||
493 | |||
494 | if (oldmm) | ||
495 | cpumask_copy(mm_cpumask(mm), mm_cpumask(oldmm)); | ||
496 | else | ||
497 | memset(mm_cpumask(mm), 0, cpumask_size()); | ||
498 | #endif | ||
499 | return 0; | ||
500 | } | ||
501 | |||
488 | static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) | 502 | static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) |
489 | { | 503 | { |
490 | atomic_set(&mm->mm_users, 1); | 504 | atomic_set(&mm->mm_users, 1); |
@@ -521,10 +535,20 @@ struct mm_struct * mm_alloc(void) | |||
521 | struct mm_struct * mm; | 535 | struct mm_struct * mm; |
522 | 536 | ||
523 | mm = allocate_mm(); | 537 | mm = allocate_mm(); |
524 | if (mm) { | 538 | if (!mm) |
525 | memset(mm, 0, sizeof(*mm)); | 539 | return NULL; |
526 | mm = mm_init(mm, current); | 540 | |
541 | memset(mm, 0, sizeof(*mm)); | ||
542 | mm = mm_init(mm, current); | ||
543 | if (!mm) | ||
544 | return NULL; | ||
545 | |||
546 | if (mm_init_cpumask(mm, NULL)) { | ||
547 | mm_free_pgd(mm); | ||
548 | free_mm(mm); | ||
549 | return NULL; | ||
527 | } | 550 | } |
551 | |||
528 | return mm; | 552 | return mm; |
529 | } | 553 | } |
530 | 554 | ||
@@ -536,6 +560,7 @@ struct mm_struct * mm_alloc(void) | |||
536 | void __mmdrop(struct mm_struct *mm) | 560 | void __mmdrop(struct mm_struct *mm) |
537 | { | 561 | { |
538 | BUG_ON(mm == &init_mm); | 562 | BUG_ON(mm == &init_mm); |
563 | free_cpumask_var(mm->cpu_vm_mask_var); | ||
539 | mm_free_pgd(mm); | 564 | mm_free_pgd(mm); |
540 | destroy_context(mm); | 565 | destroy_context(mm); |
541 | mmu_notifier_mm_destroy(mm); | 566 | mmu_notifier_mm_destroy(mm); |
@@ -690,6 +715,9 @@ struct mm_struct *dup_mm(struct task_struct *tsk) | |||
690 | if (!mm_init(mm, tsk)) | 715 | if (!mm_init(mm, tsk)) |
691 | goto fail_nomem; | 716 | goto fail_nomem; |
692 | 717 | ||
718 | if (mm_init_cpumask(mm, oldmm)) | ||
719 | goto fail_nocpumask; | ||
720 | |||
693 | if (init_new_context(tsk, mm)) | 721 | if (init_new_context(tsk, mm)) |
694 | goto fail_nocontext; | 722 | goto fail_nocontext; |
695 | 723 | ||
@@ -716,6 +744,9 @@ fail_nomem: | |||
716 | return NULL; | 744 | return NULL; |
717 | 745 | ||
718 | fail_nocontext: | 746 | fail_nocontext: |
747 | free_cpumask_var(mm->cpu_vm_mask_var); | ||
748 | |||
749 | fail_nocpumask: | ||
719 | /* | 750 | /* |
720 | * If init_new_context() failed, we cannot use mmput() to free the mm | 751 | * If init_new_context() failed, we cannot use mmput() to free the mm |
721 | * because it calls destroy_context() | 752 | * because it calls destroy_context() |