Commit 3140a227 authored by Brice Goglin's avatar Brice Goglin Committed by Linus Torvalds

mm: rework do_pages_move() to work on page_sized chunks

Rework do_pages_move() to work by page-sized chunks of struct page_to_node
that are passed to do_move_page_to_node_array().  We now only have to
allocate a single page instead a possibly very large vmalloc area to store
all page_to_node entries.

As a result, new_page_node() will now have a very small lookup, hidding
much of the overall sys_move_pages() overhead.
Signed-off-by: default avatarBrice Goglin <Brice.Goglin@inria.fr>
Signed-off-by: default avatarNathalie Furmento <Nathalie.Furmento@labri.fr>
Acked-by: default avatarChristoph Lameter <cl@linux-foundation.org>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 390722ba
...@@ -919,41 +919,43 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task, ...@@ -919,41 +919,43 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
const int __user *nodes, const int __user *nodes,
int __user *status, int flags) int __user *status, int flags)
{ {
struct page_to_node *pm = NULL; struct page_to_node *pm;
nodemask_t task_nodes; nodemask_t task_nodes;
int err = 0; unsigned long chunk_nr_pages;
int i; unsigned long chunk_start;
int err;
task_nodes = cpuset_mems_allowed(task); task_nodes = cpuset_mems_allowed(task);
/* Limit nr_pages so that the multiplication may not overflow */ err = -ENOMEM;
if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) { pm = (struct page_to_node *)__get_free_page(GFP_KERNEL);
err = -E2BIG; if (!pm)
goto out;
}
pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node));
if (!pm) {
err = -ENOMEM;
goto out; goto out;
}
/* /*
* Get parameters from user space and initialize the pm * Store a chunk of page_to_node array in a page,
* array. Return various errors if the user did something wrong. * but keep the last one as a marker
*/ */
for (i = 0; i < nr_pages; i++) { chunk_nr_pages = (PAGE_SIZE / sizeof(struct page_to_node)) - 1;
const void __user *p;
err = -EFAULT; for (chunk_start = 0;
if (get_user(p, pages + i)) chunk_start < nr_pages;
goto out_pm; chunk_start += chunk_nr_pages) {
int j;
pm[i].addr = (unsigned long)p; if (chunk_start + chunk_nr_pages > nr_pages)
if (nodes) { chunk_nr_pages = nr_pages - chunk_start;
/* fill the chunk pm with addrs and nodes from user-space */
for (j = 0; j < chunk_nr_pages; j++) {
const void __user *p;
int node; int node;
if (get_user(node, nodes + i)) err = -EFAULT;
if (get_user(p, pages + j + chunk_start))
goto out_pm;
pm[j].addr = (unsigned long) p;
if (get_user(node, nodes + j + chunk_start))
goto out_pm; goto out_pm;
err = -ENODEV; err = -ENODEV;
...@@ -964,22 +966,29 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task, ...@@ -964,22 +966,29 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
if (!node_isset(node, task_nodes)) if (!node_isset(node, task_nodes))
goto out_pm; goto out_pm;
pm[i].node = node; pm[j].node = node;
} else }
pm[i].node = 0; /* anything to not match MAX_NUMNODES */
} /* End marker for this chunk */
/* End marker */ pm[chunk_nr_pages].node = MAX_NUMNODES;
pm[nr_pages].node = MAX_NUMNODES;
/* Migrate this chunk */
err = do_move_page_to_node_array(mm, pm,
flags & MPOL_MF_MOVE_ALL);
if (err < 0)
goto out_pm;
err = do_move_page_to_node_array(mm, pm, flags & MPOL_MF_MOVE_ALL);
if (err >= 0)
/* Return status information */ /* Return status information */
for (i = 0; i < nr_pages; i++) for (j = 0; j < chunk_nr_pages; j++)
if (put_user(pm[i].status, status + i)) if (put_user(pm[j].status, status + j + chunk_start)) {
err = -EFAULT; err = -EFAULT;
goto out_pm;
}
}
err = 0;
out_pm: out_pm:
vfree(pm); free_page((unsigned long)pm);
out: out:
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment