diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cpuset.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 19f87565be17..cf8203a5fa71 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -639,25 +639,14 @@ void cpuset_update_task_memory_state() | |||
639 | task_unlock(tsk); | 639 | task_unlock(tsk); |
640 | 640 | ||
641 | if (my_cpusets_mem_gen != tsk->cpuset_mems_generation) { | 641 | if (my_cpusets_mem_gen != tsk->cpuset_mems_generation) { |
642 | nodemask_t oldmem = tsk->mems_allowed; | ||
643 | int migrate; | ||
644 | |||
645 | down(&callback_sem); | 642 | down(&callback_sem); |
646 | task_lock(tsk); | 643 | task_lock(tsk); |
647 | cs = tsk->cpuset; /* Maybe changed when task not locked */ | 644 | cs = tsk->cpuset; /* Maybe changed when task not locked */ |
648 | migrate = is_memory_migrate(cs); | ||
649 | guarantee_online_mems(cs, &tsk->mems_allowed); | 645 | guarantee_online_mems(cs, &tsk->mems_allowed); |
650 | tsk->cpuset_mems_generation = cs->mems_generation; | 646 | tsk->cpuset_mems_generation = cs->mems_generation; |
651 | task_unlock(tsk); | 647 | task_unlock(tsk); |
652 | up(&callback_sem); | 648 | up(&callback_sem); |
653 | mpol_rebind_task(tsk, &tsk->mems_allowed); | 649 | mpol_rebind_task(tsk, &tsk->mems_allowed); |
654 | if (!nodes_equal(oldmem, tsk->mems_allowed)) { | ||
655 | if (migrate) { | ||
656 | do_migrate_pages(tsk->mm, &oldmem, | ||
657 | &tsk->mems_allowed, | ||
658 | MPOL_MF_MOVE_ALL); | ||
659 | } | ||
660 | } | ||
661 | } | 650 | } |
662 | } | 651 | } |
663 | 652 | ||
@@ -815,7 +804,9 @@ static int update_cpumask(struct cpuset *cs, char *buf) | |||
815 | * Handle user request to change the 'mems' memory placement | 804 | * Handle user request to change the 'mems' memory placement |
816 | * of a cpuset. Needs to validate the request, update the | 805 | * of a cpuset. Needs to validate the request, update the |
817 | * cpusets mems_allowed and mems_generation, and for each | 806 | * cpusets mems_allowed and mems_generation, and for each |
818 | * task in the cpuset, rebind any vma mempolicies. | 807 | * task in the cpuset, rebind any vma mempolicies and if |
808 | * the cpuset is marked 'memory_migrate', migrate the tasks | ||
809 | * pages to the new memory. | ||
819 | * | 810 | * |
820 | * Call with manage_sem held. May take callback_sem during call. | 811 | * Call with manage_sem held. May take callback_sem during call. |
821 | * Will take tasklist_lock, scan tasklist for tasks in cpuset cs, | 812 | * Will take tasklist_lock, scan tasklist for tasks in cpuset cs, |
@@ -826,9 +817,11 @@ static int update_cpumask(struct cpuset *cs, char *buf) | |||
826 | static int update_nodemask(struct cpuset *cs, char *buf) | 817 | static int update_nodemask(struct cpuset *cs, char *buf) |
827 | { | 818 | { |
828 | struct cpuset trialcs; | 819 | struct cpuset trialcs; |
820 | nodemask_t oldmem; | ||
829 | struct task_struct *g, *p; | 821 | struct task_struct *g, *p; |
830 | struct mm_struct **mmarray; | 822 | struct mm_struct **mmarray; |
831 | int i, n, ntasks; | 823 | int i, n, ntasks; |
824 | int migrate; | ||
832 | int fudge; | 825 | int fudge; |
833 | int retval; | 826 | int retval; |
834 | 827 | ||
@@ -837,6 +830,11 @@ static int update_nodemask(struct cpuset *cs, char *buf) | |||
837 | if (retval < 0) | 830 | if (retval < 0) |
838 | goto done; | 831 | goto done; |
839 | nodes_and(trialcs.mems_allowed, trialcs.mems_allowed, node_online_map); | 832 | nodes_and(trialcs.mems_allowed, trialcs.mems_allowed, node_online_map); |
833 | oldmem = cs->mems_allowed; | ||
834 | if (nodes_equal(oldmem, trialcs.mems_allowed)) { | ||
835 | retval = 0; /* Too easy - nothing to do */ | ||
836 | goto done; | ||
837 | } | ||
840 | if (nodes_empty(trialcs.mems_allowed)) { | 838 | if (nodes_empty(trialcs.mems_allowed)) { |
841 | retval = -ENOSPC; | 839 | retval = -ENOSPC; |
842 | goto done; | 840 | goto done; |
@@ -908,12 +906,17 @@ static int update_nodemask(struct cpuset *cs, char *buf) | |||
908 | * cpuset manage_sem, we know that no other rebind effort will | 906 | * cpuset manage_sem, we know that no other rebind effort will |
909 | * be contending for the global variable cpuset_being_rebound. | 907 | * be contending for the global variable cpuset_being_rebound. |
910 | * It's ok if we rebind the same mm twice; mpol_rebind_mm() | 908 | * It's ok if we rebind the same mm twice; mpol_rebind_mm() |
911 | * is idempotent. | 909 | * is idempotent. Also migrate pages in each mm to new nodes. |
912 | */ | 910 | */ |
911 | migrate = is_memory_migrate(cs); | ||
913 | for (i = 0; i < n; i++) { | 912 | for (i = 0; i < n; i++) { |
914 | struct mm_struct *mm = mmarray[i]; | 913 | struct mm_struct *mm = mmarray[i]; |
915 | 914 | ||
916 | mpol_rebind_mm(mm, &cs->mems_allowed); | 915 | mpol_rebind_mm(mm, &cs->mems_allowed); |
916 | if (migrate) { | ||
917 | do_migrate_pages(mm, &oldmem, &cs->mems_allowed, | ||
918 | MPOL_MF_MOVE_ALL); | ||
919 | } | ||
917 | mmput(mm); | 920 | mmput(mm); |
918 | } | 921 | } |
919 | 922 | ||