aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrice Goglin <Brice.Goglin@inria.fr>2008-10-18 23:27:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-20 11:52:33 -0400
commit2f007e74bb85b9fc4eab28524052161703300f1a (patch)
tree8fa77e687aa5fd807767484bdafcce86e46a56af
parente78bbfa8262424417a29349a8064a535053912b9 (diff)
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>
-rw-r--r--mm/migrate.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/mm/migrate.c b/mm/migrate.c
index f233519f0453..a4c29081ebce 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -906,25 +906,33 @@ set_status:
906} 906}
907 907
908/* 908/*
909 * Determine the nodes of a list of pages. The addr in the pm array 909 * Determine the nodes of an array of pages and store it in an array of status.
910 * must have been set to the virtual address of which we want to determine
911 * the node number.
912 */ 910 */
913static int do_pages_stat(struct mm_struct *mm, struct page_to_node *pm) 911static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
912 const void __user * __user *pages,
913 int __user *status)
914{ 914{
915 unsigned long i;
916 int err;
917
915 down_read(&mm->mmap_sem); 918 down_read(&mm->mmap_sem);
916 919
917 for ( ; pm->node != MAX_NUMNODES; pm++) { 920 for (i = 0; i < nr_pages; i++) {
921 const void __user *p;
922 unsigned long addr;
918 struct vm_area_struct *vma; 923 struct vm_area_struct *vma;
919 struct page *page; 924 struct page *page;
920 int err;
921 925
922 err = -EFAULT; 926 err = -EFAULT;
923 vma = find_vma(mm, pm->addr); 927 if (get_user(p, pages+i))
928 goto out;
929 addr = (unsigned long) p;
930
931 vma = find_vma(mm, addr);
924 if (!vma) 932 if (!vma)
925 goto set_status; 933 goto set_status;
926 934
927 page = follow_page(vma, pm->addr, 0); 935 page = follow_page(vma, addr, 0);
928 936
929 err = PTR_ERR(page); 937 err = PTR_ERR(page);
930 if (IS_ERR(page)) 938 if (IS_ERR(page))
@@ -937,11 +945,13 @@ static int do_pages_stat(struct mm_struct *mm, struct page_to_node *pm)
937 945
938 err = page_to_nid(page); 946 err = page_to_nid(page);
939set_status: 947set_status:
940 pm->status = err; 948 put_user(err, status+i);
941 } 949 }
950 err = 0;
942 951
952out:
943 up_read(&mm->mmap_sem); 953 up_read(&mm->mmap_sem);
944 return 0; 954 return err;
945} 955}
946 956
947/* 957/*
@@ -997,6 +1007,10 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
997 if (err) 1007 if (err)
998 goto out2; 1008 goto out2;
999 1009
1010 if (!nodes) {
1011 err = do_pages_stat(mm, nr_pages, pages, status);
1012 goto out2;
1013 }
1000 1014
1001 task_nodes = cpuset_mems_allowed(task); 1015 task_nodes = cpuset_mems_allowed(task);
1002 1016
@@ -1045,11 +1059,7 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
1045 /* End marker */ 1059 /* End marker */
1046 pm[nr_pages].node = MAX_NUMNODES; 1060 pm[nr_pages].node = MAX_NUMNODES;
1047 1061
1048 if (nodes) 1062 err = do_move_pages(mm, pm, flags & MPOL_MF_MOVE_ALL);
1049 err = do_move_pages(mm, pm, flags & MPOL_MF_MOVE_ALL);
1050 else
1051 err = do_pages_stat(mm, pm);
1052
1053 if (err >= 0) 1063 if (err >= 0)
1054 /* Return status information */ 1064 /* Return status information */
1055 for (i = 0; i < nr_pages; i++) 1065 for (i = 0; i < nr_pages; i++)