Skip to content

Commit 3140a22

Browse files
bgoglintorvalds
authored andcommitted
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: Brice Goglin <[email protected]> Signed-off-by: Nathalie Furmento <[email protected]> Acked-by: Christoph Lameter <[email protected]> Cc: Nick Piggin <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 390722b commit 3140a22

File tree

1 file changed

+44
-35
lines changed

1 file changed

+44
-35
lines changed

mm/migrate.c

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -919,41 +919,43 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
919919
const int __user *nodes,
920920
int __user *status, int flags)
921921
{
922-
struct page_to_node *pm = NULL;
922+
struct page_to_node *pm;
923923
nodemask_t task_nodes;
924-
int err = 0;
925-
int i;
924+
unsigned long chunk_nr_pages;
925+
unsigned long chunk_start;
926+
int err;
926927

927928
task_nodes = cpuset_mems_allowed(task);
928929

929-
/* Limit nr_pages so that the multiplication may not overflow */
930-
if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) {
931-
err = -E2BIG;
932-
goto out;
933-
}
934-
935-
pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node));
936-
if (!pm) {
937-
err = -ENOMEM;
930+
err = -ENOMEM;
931+
pm = (struct page_to_node *)__get_free_page(GFP_KERNEL);
932+
if (!pm)
938933
goto out;
939-
}
940-
941934
/*
942-
* Get parameters from user space and initialize the pm
943-
* array. Return various errors if the user did something wrong.
935+
* Store a chunk of page_to_node array in a page,
936+
* but keep the last one as a marker
944937
*/
945-
for (i = 0; i < nr_pages; i++) {
946-
const void __user *p;
938+
chunk_nr_pages = (PAGE_SIZE / sizeof(struct page_to_node)) - 1;
947939

948-
err = -EFAULT;
949-
if (get_user(p, pages + i))
950-
goto out_pm;
940+
for (chunk_start = 0;
941+
chunk_start < nr_pages;
942+
chunk_start += chunk_nr_pages) {
943+
int j;
951944

952-
pm[i].addr = (unsigned long)p;
953-
if (nodes) {
945+
if (chunk_start + chunk_nr_pages > nr_pages)
946+
chunk_nr_pages = nr_pages - chunk_start;
947+
948+
/* fill the chunk pm with addrs and nodes from user-space */
949+
for (j = 0; j < chunk_nr_pages; j++) {
950+
const void __user *p;
954951
int node;
955952

956-
if (get_user(node, nodes + i))
953+
err = -EFAULT;
954+
if (get_user(p, pages + j + chunk_start))
955+
goto out_pm;
956+
pm[j].addr = (unsigned long) p;
957+
958+
if (get_user(node, nodes + j + chunk_start))
957959
goto out_pm;
958960

959961
err = -ENODEV;
@@ -964,22 +966,29 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
964966
if (!node_isset(node, task_nodes))
965967
goto out_pm;
966968

967-
pm[i].node = node;
968-
} else
969-
pm[i].node = 0; /* anything to not match MAX_NUMNODES */
970-
}
971-
/* End marker */
972-
pm[nr_pages].node = MAX_NUMNODES;
969+
pm[j].node = node;
970+
}
971+
972+
/* End marker for this chunk */
973+
pm[chunk_nr_pages].node = MAX_NUMNODES;
974+
975+
/* Migrate this chunk */
976+
err = do_move_page_to_node_array(mm, pm,
977+
flags & MPOL_MF_MOVE_ALL);
978+
if (err < 0)
979+
goto out_pm;
973980

974-
err = do_move_page_to_node_array(mm, pm, flags & MPOL_MF_MOVE_ALL);
975-
if (err >= 0)
976981
/* Return status information */
977-
for (i = 0; i < nr_pages; i++)
978-
if (put_user(pm[i].status, status + i))
982+
for (j = 0; j < chunk_nr_pages; j++)
983+
if (put_user(pm[j].status, status + j + chunk_start)) {
979984
err = -EFAULT;
985+
goto out_pm;
986+
}
987+
}
988+
err = 0;
980989

981990
out_pm:
982-
vfree(pm);
991+
free_page((unsigned long)pm);
983992
out:
984993
return err;
985994
}

0 commit comments

Comments
 (0)