diff options
Diffstat (limited to 'mm/migrate.c')
-rw-r--r-- | mm/migrate.c | 40 |
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 | */ |
913 | static int do_pages_stat(struct mm_struct *mm, struct page_to_node *pm) | 911 | static 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); |
939 | set_status: | 947 | set_status: |
940 | pm->status = err; | 948 | put_user(err, status+i); |
941 | } | 949 | } |
950 | err = 0; | ||
942 | 951 | ||
952 | out: | ||
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++) |