aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mempolicy.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r--mm/mempolicy.c83
1 files changed, 48 insertions, 35 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index b19569137529..1d771e4200d2 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -390,7 +390,7 @@ static void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask,
390{ 390{
391 if (!pol) 391 if (!pol)
392 return; 392 return;
393 if (!mpol_store_user_nodemask(pol) && step == 0 && 393 if (!mpol_store_user_nodemask(pol) && step == MPOL_REBIND_ONCE &&
394 nodes_equal(pol->w.cpuset_mems_allowed, *newmask)) 394 nodes_equal(pol->w.cpuset_mems_allowed, *newmask))
395 return; 395 return;
396 396
@@ -607,27 +607,6 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
607 return first; 607 return first;
608} 608}
609 609
610/* Apply policy to a single VMA */
611static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new)
612{
613 int err = 0;
614 struct mempolicy *old = vma->vm_policy;
615
616 pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
617 vma->vm_start, vma->vm_end, vma->vm_pgoff,
618 vma->vm_ops, vma->vm_file,
619 vma->vm_ops ? vma->vm_ops->set_policy : NULL);
620
621 if (vma->vm_ops && vma->vm_ops->set_policy)
622 err = vma->vm_ops->set_policy(vma, new);
623 if (!err) {
624 mpol_get(new);
625 vma->vm_policy = new;
626 mpol_put(old);
627 }
628 return err;
629}
630
631/* Step 2: apply policy to a range and do splits. */ 610/* Step 2: apply policy to a range and do splits. */
632static int mbind_range(struct mm_struct *mm, unsigned long start, 611static int mbind_range(struct mm_struct *mm, unsigned long start,
633 unsigned long end, struct mempolicy *new_pol) 612 unsigned long end, struct mempolicy *new_pol)
@@ -676,9 +655,23 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
676 if (err) 655 if (err)
677 goto out; 656 goto out;
678 } 657 }
679 err = policy_vma(vma, new_pol); 658
680 if (err) 659 /*
681 goto out; 660 * Apply policy to a single VMA. The reference counting of
661 * policy for vma_policy linkages has already been handled by
662 * vma_merge and split_vma as necessary. If this is a shared
663 * policy then ->set_policy will increment the reference count
664 * for an sp node.
665 */
666 pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
667 vma->vm_start, vma->vm_end, vma->vm_pgoff,
668 vma->vm_ops, vma->vm_file,
669 vma->vm_ops ? vma->vm_ops->set_policy : NULL);
670 if (vma->vm_ops && vma->vm_ops->set_policy) {
671 err = vma->vm_ops->set_policy(vma, new_pol);
672 if (err)
673 goto out;
674 }
682 } 675 }
683 676
684 out: 677 out:
@@ -957,8 +950,8 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest,
957 * 950 *
958 * Returns the number of page that could not be moved. 951 * Returns the number of page that could not be moved.
959 */ 952 */
960int do_migrate_pages(struct mm_struct *mm, 953int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
961 const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags) 954 const nodemask_t *to, int flags)
962{ 955{
963 int busy = 0; 956 int busy = 0;
964 int err; 957 int err;
@@ -970,7 +963,7 @@ int do_migrate_pages(struct mm_struct *mm,
970 963
971 down_read(&mm->mmap_sem); 964 down_read(&mm->mmap_sem);
972 965
973 err = migrate_vmas(mm, from_nodes, to_nodes, flags); 966 err = migrate_vmas(mm, from, to, flags);
974 if (err) 967 if (err)
975 goto out; 968 goto out;
976 969
@@ -1005,14 +998,34 @@ int do_migrate_pages(struct mm_struct *mm,
1005 * moved to an empty node, then there is nothing left worth migrating. 998 * moved to an empty node, then there is nothing left worth migrating.
1006 */ 999 */
1007 1000
1008 tmp = *from_nodes; 1001 tmp = *from;
1009 while (!nodes_empty(tmp)) { 1002 while (!nodes_empty(tmp)) {
1010 int s,d; 1003 int s,d;
1011 int source = -1; 1004 int source = -1;
1012 int dest = 0; 1005 int dest = 0;
1013 1006
1014 for_each_node_mask(s, tmp) { 1007 for_each_node_mask(s, tmp) {
1015 d = node_remap(s, *from_nodes, *to_nodes); 1008
1009 /*
1010 * do_migrate_pages() tries to maintain the relative
1011 * node relationship of the pages established between
1012 * threads and memory areas.
1013 *
1014 * However if the number of source nodes is not equal to
1015 * the number of destination nodes we can not preserve
1016 * this node relative relationship. In that case, skip
1017 * copying memory from a node that is in the destination
1018 * mask.
1019 *
1020 * Example: [2,3,4] -> [3,4,5] moves everything.
1021 * [0-7] - > [3,4,5] moves only 0,1,2,6,7.
1022 */
1023
1024 if ((nodes_weight(*from) != nodes_weight(*to)) &&
1025 (node_isset(s, *to)))
1026 continue;
1027
1028 d = node_remap(s, *from, *to);
1016 if (s == d) 1029 if (s == d)
1017 continue; 1030 continue;
1018 1031
@@ -1072,8 +1085,8 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
1072{ 1085{
1073} 1086}
1074 1087
1075int do_migrate_pages(struct mm_struct *mm, 1088int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from,
1076 const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags) 1089 const nodemask_t *to, int flags)
1077{ 1090{
1078 return -ENOSYS; 1091 return -ENOSYS;
1079} 1092}
@@ -1164,7 +1177,7 @@ static long do_mbind(unsigned long start, unsigned long len,
1164 if (!list_empty(&pagelist)) { 1177 if (!list_empty(&pagelist)) {
1165 nr_failed = migrate_pages(&pagelist, new_vma_page, 1178 nr_failed = migrate_pages(&pagelist, new_vma_page,
1166 (unsigned long)vma, 1179 (unsigned long)vma,
1167 false, true); 1180 false, MIGRATE_SYNC);
1168 if (nr_failed) 1181 if (nr_failed)
1169 putback_lru_pages(&pagelist); 1182 putback_lru_pages(&pagelist);
1170 } 1183 }
@@ -1334,8 +1347,8 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode,
1334 * userid as the target process. 1347 * userid as the target process.
1335 */ 1348 */
1336 tcred = __task_cred(task); 1349 tcred = __task_cred(task);
1337 if (cred->euid != tcred->suid && cred->euid != tcred->uid && 1350 if (!uid_eq(cred->euid, tcred->suid) && !uid_eq(cred->euid, tcred->uid) &&
1338 cred->uid != tcred->suid && cred->uid != tcred->uid && 1351 !uid_eq(cred->uid, tcred->suid) && !uid_eq(cred->uid, tcred->uid) &&
1339 !capable(CAP_SYS_NICE)) { 1352 !capable(CAP_SYS_NICE)) {
1340 rcu_read_unlock(); 1353 rcu_read_unlock();
1341 err = -EPERM; 1354 err = -EPERM;