mm: don't vmalloc a huge page_to_node array for do_pages_stat()
do_pages_stat() does not need any page_to_node entry for real. Just pass the pointers to the user-space page address array and to the user-space status array, and have do_pages_stat() traverse the former and fill the latter directly. Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr> Acked-by: Christoph Lameter <cl@linux-foundation.org> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
e78bbfa826
commit
2f007e74bb
40
mm/migrate.c
40
mm/migrate.c
@ -906,25 +906,33 @@ static int do_move_pages(struct mm_struct *mm, struct page_to_node *pm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the nodes of a list of pages. The addr in the pm array
|
* Determine the nodes of an array of pages and store it in an array of status.
|
||||||
* must have been set to the virtual address of which we want to determine
|
|
||||||
* the node number.
|
|
||||||
*/
|
*/
|
||||||
static int do_pages_stat(struct mm_struct *mm, struct page_to_node *pm)
|
static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
|
||||||
|
const void __user * __user *pages,
|
||||||
|
int __user *status)
|
||||||
{
|
{
|
||||||
|
unsigned long i;
|
||||||
|
int err;
|
||||||
|
|
||||||
down_read(&mm->mmap_sem);
|
down_read(&mm->mmap_sem);
|
||||||
|
|
||||||
for ( ; pm->node != MAX_NUMNODES; pm++) {
|
for (i = 0; i < nr_pages; i++) {
|
||||||
|
const void __user *p;
|
||||||
|
unsigned long addr;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
int err;
|
|
||||||
|
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
vma = find_vma(mm, pm->addr);
|
if (get_user(p, pages+i))
|
||||||
|
goto out;
|
||||||
|
addr = (unsigned long) p;
|
||||||
|
|
||||||
|
vma = find_vma(mm, addr);
|
||||||
if (!vma)
|
if (!vma)
|
||||||
goto set_status;
|
goto set_status;
|
||||||
|
|
||||||
page = follow_page(vma, pm->addr, 0);
|
page = follow_page(vma, addr, 0);
|
||||||
|
|
||||||
err = PTR_ERR(page);
|
err = PTR_ERR(page);
|
||||||
if (IS_ERR(page))
|
if (IS_ERR(page))
|
||||||
@ -937,11 +945,13 @@ static int do_pages_stat(struct mm_struct *mm, struct page_to_node *pm)
|
|||||||
|
|
||||||
err = page_to_nid(page);
|
err = page_to_nid(page);
|
||||||
set_status:
|
set_status:
|
||||||
pm->status = err;
|
put_user(err, status+i);
|
||||||
}
|
}
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
up_read(&mm->mmap_sem);
|
up_read(&mm->mmap_sem);
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -997,6 +1007,10 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
|
|||||||
if (err)
|
if (err)
|
||||||
goto out2;
|
goto out2;
|
||||||
|
|
||||||
|
if (!nodes) {
|
||||||
|
err = do_pages_stat(mm, nr_pages, pages, status);
|
||||||
|
goto out2;
|
||||||
|
}
|
||||||
|
|
||||||
task_nodes = cpuset_mems_allowed(task);
|
task_nodes = cpuset_mems_allowed(task);
|
||||||
|
|
||||||
@ -1045,11 +1059,7 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
|
|||||||
/* End marker */
|
/* End marker */
|
||||||
pm[nr_pages].node = MAX_NUMNODES;
|
pm[nr_pages].node = MAX_NUMNODES;
|
||||||
|
|
||||||
if (nodes)
|
err = do_move_pages(mm, pm, flags & MPOL_MF_MOVE_ALL);
|
||||||
err = do_move_pages(mm, pm, flags & MPOL_MF_MOVE_ALL);
|
|
||||||
else
|
|
||||||
err = do_pages_stat(mm, pm);
|
|
||||||
|
|
||||||
if (err >= 0)
|
if (err >= 0)
|
||||||
/* Return status information */
|
/* Return status information */
|
||||||
for (i = 0; i < nr_pages; i++)
|
for (i = 0; i < nr_pages; i++)
|
||||||
|
Loading…
Reference in New Issue
Block a user