aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mempolicy.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r--mm/mempolicy.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 3bd7fb7e4b75..67af4cea1e23 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -132,19 +132,29 @@ static int mpol_check_policy(int mode, nodemask_t *nodes)
132 } 132 }
133 return nodes_subset(*nodes, node_online_map) ? 0 : -EINVAL; 133 return nodes_subset(*nodes, node_online_map) ? 0 : -EINVAL;
134} 134}
135
135/* Generate a custom zonelist for the BIND policy. */ 136/* Generate a custom zonelist for the BIND policy. */
136static struct zonelist *bind_zonelist(nodemask_t *nodes) 137static struct zonelist *bind_zonelist(nodemask_t *nodes)
137{ 138{
138 struct zonelist *zl; 139 struct zonelist *zl;
139 int num, max, nd; 140 int num, max, nd, k;
140 141
141 max = 1 + MAX_NR_ZONES * nodes_weight(*nodes); 142 max = 1 + MAX_NR_ZONES * nodes_weight(*nodes);
142 zl = kmalloc(sizeof(void *) * max, GFP_KERNEL); 143 zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL);
143 if (!zl) 144 if (!zl)
144 return NULL; 145 return NULL;
145 num = 0; 146 num = 0;
146 for_each_node_mask(nd, *nodes) 147 /* First put in the highest zones from all nodes, then all the next
147 zl->zones[num++] = &NODE_DATA(nd)->node_zones[policy_zone]; 148 lower zones etc. Avoid empty zones because the memory allocator
149 doesn't like them. If you implement node hot removal you
150 have to fix that. */
151 for (k = policy_zone; k >= 0; k--) {
152 for_each_node_mask(nd, *nodes) {
153 struct zone *z = &NODE_DATA(nd)->node_zones[k];
154 if (z->present_pages > 0)
155 zl->zones[num++] = z;
156 }
157 }
148 zl->zones[num] = NULL; 158 zl->zones[num] = NULL;
149 return zl; 159 return zl;
150} 160}
@@ -542,7 +552,7 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
542 */ 552 */
543 if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) { 553 if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) {
544 if (isolate_lru_page(page)) 554 if (isolate_lru_page(page))
545 list_add(&page->lru, pagelist); 555 list_add_tail(&page->lru, pagelist);
546 } 556 }
547} 557}
548 558
@@ -559,6 +569,7 @@ static int migrate_pages_to(struct list_head *pagelist,
559 LIST_HEAD(moved); 569 LIST_HEAD(moved);
560 LIST_HEAD(failed); 570 LIST_HEAD(failed);
561 int err = 0; 571 int err = 0;
572 unsigned long offset = 0;
562 int nr_pages; 573 int nr_pages;
563 struct page *page; 574 struct page *page;
564 struct list_head *p; 575 struct list_head *p;
@@ -566,8 +577,21 @@ static int migrate_pages_to(struct list_head *pagelist,
566redo: 577redo:
567 nr_pages = 0; 578 nr_pages = 0;
568 list_for_each(p, pagelist) { 579 list_for_each(p, pagelist) {
569 if (vma) 580 if (vma) {
570 page = alloc_page_vma(GFP_HIGHUSER, vma, vma->vm_start); 581 /*
582 * The address passed to alloc_page_vma is used to
583 * generate the proper interleave behavior. We fake
584 * the address here by an increasing offset in order
585 * to get the proper distribution of pages.
586 *
587 * No decision has been made as to which page
588 * a certain old page is moved to so we cannot
589 * specify the correct address.
590 */
591 page = alloc_page_vma(GFP_HIGHUSER, vma,
592 offset + vma->vm_start);
593 offset += PAGE_SIZE;
594 }
571 else 595 else
572 page = alloc_pages_node(dest, GFP_HIGHUSER, 0); 596 page = alloc_pages_node(dest, GFP_HIGHUSER, 0);
573 597
@@ -575,9 +599,9 @@ redo:
575 err = -ENOMEM; 599 err = -ENOMEM;
576 goto out; 600 goto out;
577 } 601 }
578 list_add(&page->lru, &newlist); 602 list_add_tail(&page->lru, &newlist);
579 nr_pages++; 603 nr_pages++;
580 if (nr_pages > MIGRATE_CHUNK_SIZE); 604 if (nr_pages > MIGRATE_CHUNK_SIZE)
581 break; 605 break;
582 } 606 }
583 err = migrate_pages(pagelist, &newlist, &moved, &failed); 607 err = migrate_pages(pagelist, &newlist, &moved, &failed);
@@ -798,6 +822,8 @@ static int get_nodes(nodemask_t *nodes, const unsigned long __user *nmask,
798 nodes_clear(*nodes); 822 nodes_clear(*nodes);
799 if (maxnode == 0 || !nmask) 823 if (maxnode == 0 || !nmask)
800 return 0; 824 return 0;
825 if (maxnode > PAGE_SIZE*BITS_PER_BYTE)
826 return -EINVAL;
801 827
802 nlongs = BITS_TO_LONGS(maxnode); 828 nlongs = BITS_TO_LONGS(maxnode);
803 if ((maxnode % BITS_PER_LONG) == 0) 829 if ((maxnode % BITS_PER_LONG) == 0)