Commit 5e9a0f023bee02bfb94e08590d998660c01f5a49
Committed by
Linus Torvalds
1 parent
2f007e74bb
Exists in
master
and in
7 other branches
mm: extract do_pages_move() out of sys_move_pages()
To prepare the chunking, move the sys_move_pages() code that is used when nodes!=NULL into do_pages_move(). And rename do_move_pages() into do_move_page_to_node_array(). 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>
Showing 1 changed file with 86 additions and 66 deletions Side-by-side Diff
mm/migrate.c
... | ... | @@ -826,9 +826,11 @@ |
826 | 826 | * Move a set of pages as indicated in the pm array. The addr |
827 | 827 | * field must be set to the virtual address of the page to be moved |
828 | 828 | * and the node number must contain a valid target node. |
829 | + * The pm array ends with node = MAX_NUMNODES. | |
829 | 830 | */ |
830 | -static int do_move_pages(struct mm_struct *mm, struct page_to_node *pm, | |
831 | - int migrate_all) | |
831 | +static int do_move_page_to_node_array(struct mm_struct *mm, | |
832 | + struct page_to_node *pm, | |
833 | + int migrate_all) | |
832 | 834 | { |
833 | 835 | int err; |
834 | 836 | struct page_to_node *pp; |
... | ... | @@ -906,6 +908,81 @@ |
906 | 908 | } |
907 | 909 | |
908 | 910 | /* |
911 | + * Migrate an array of page address onto an array of nodes and fill | |
912 | + * the corresponding array of status. | |
913 | + */ | |
914 | +static int do_pages_move(struct mm_struct *mm, struct task_struct *task, | |
915 | + unsigned long nr_pages, | |
916 | + const void __user * __user *pages, | |
917 | + const int __user *nodes, | |
918 | + int __user *status, int flags) | |
919 | +{ | |
920 | + struct page_to_node *pm = NULL; | |
921 | + nodemask_t task_nodes; | |
922 | + int err = 0; | |
923 | + int i; | |
924 | + | |
925 | + task_nodes = cpuset_mems_allowed(task); | |
926 | + | |
927 | + /* Limit nr_pages so that the multiplication may not overflow */ | |
928 | + if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) { | |
929 | + err = -E2BIG; | |
930 | + goto out; | |
931 | + } | |
932 | + | |
933 | + pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node)); | |
934 | + if (!pm) { | |
935 | + err = -ENOMEM; | |
936 | + goto out; | |
937 | + } | |
938 | + | |
939 | + /* | |
940 | + * Get parameters from user space and initialize the pm | |
941 | + * array. Return various errors if the user did something wrong. | |
942 | + */ | |
943 | + for (i = 0; i < nr_pages; i++) { | |
944 | + const void __user *p; | |
945 | + | |
946 | + err = -EFAULT; | |
947 | + if (get_user(p, pages + i)) | |
948 | + goto out_pm; | |
949 | + | |
950 | + pm[i].addr = (unsigned long)p; | |
951 | + if (nodes) { | |
952 | + int node; | |
953 | + | |
954 | + if (get_user(node, nodes + i)) | |
955 | + goto out_pm; | |
956 | + | |
957 | + err = -ENODEV; | |
958 | + if (!node_state(node, N_HIGH_MEMORY)) | |
959 | + goto out_pm; | |
960 | + | |
961 | + err = -EACCES; | |
962 | + if (!node_isset(node, task_nodes)) | |
963 | + goto out_pm; | |
964 | + | |
965 | + pm[i].node = node; | |
966 | + } else | |
967 | + pm[i].node = 0; /* anything to not match MAX_NUMNODES */ | |
968 | + } | |
969 | + /* End marker */ | |
970 | + pm[nr_pages].node = MAX_NUMNODES; | |
971 | + | |
972 | + err = do_move_page_to_node_array(mm, pm, flags & MPOL_MF_MOVE_ALL); | |
973 | + if (err >= 0) | |
974 | + /* Return status information */ | |
975 | + for (i = 0; i < nr_pages; i++) | |
976 | + if (put_user(pm[i].status, status + i)) | |
977 | + err = -EFAULT; | |
978 | + | |
979 | +out_pm: | |
980 | + vfree(pm); | |
981 | +out: | |
982 | + return err; | |
983 | +} | |
984 | + | |
985 | +/* | |
909 | 986 | * Determine the nodes of an array of pages and store it in an array of status. |
910 | 987 | */ |
911 | 988 | static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages, |
912 | 989 | |
913 | 990 | |
... | ... | @@ -963,12 +1040,9 @@ |
963 | 1040 | const int __user *nodes, |
964 | 1041 | int __user *status, int flags) |
965 | 1042 | { |
966 | - int err = 0; | |
967 | - int i; | |
968 | 1043 | struct task_struct *task; |
969 | - nodemask_t task_nodes; | |
970 | 1044 | struct mm_struct *mm; |
971 | - struct page_to_node *pm = NULL; | |
1045 | + int err; | |
972 | 1046 | |
973 | 1047 | /* Check flags */ |
974 | 1048 | if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL)) |
975 | 1049 | |
976 | 1050 | |
977 | 1051 | |
978 | 1052 | |
979 | 1053 | |
... | ... | @@ -1000,75 +1074,21 @@ |
1000 | 1074 | (current->uid != task->suid) && (current->uid != task->uid) && |
1001 | 1075 | !capable(CAP_SYS_NICE)) { |
1002 | 1076 | err = -EPERM; |
1003 | - goto out2; | |
1077 | + goto out; | |
1004 | 1078 | } |
1005 | 1079 | |
1006 | 1080 | err = security_task_movememory(task); |
1007 | 1081 | if (err) |
1008 | - goto out2; | |
1082 | + goto out; | |
1009 | 1083 | |
1010 | - if (!nodes) { | |
1084 | + if (nodes) { | |
1085 | + err = do_pages_move(mm, task, nr_pages, pages, nodes, status, | |
1086 | + flags); | |
1087 | + } else { | |
1011 | 1088 | err = do_pages_stat(mm, nr_pages, pages, status); |
1012 | - goto out2; | |
1013 | 1089 | } |
1014 | 1090 | |
1015 | - task_nodes = cpuset_mems_allowed(task); | |
1016 | - | |
1017 | - /* Limit nr_pages so that the multiplication may not overflow */ | |
1018 | - if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) { | |
1019 | - err = -E2BIG; | |
1020 | - goto out2; | |
1021 | - } | |
1022 | - | |
1023 | - pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node)); | |
1024 | - if (!pm) { | |
1025 | - err = -ENOMEM; | |
1026 | - goto out2; | |
1027 | - } | |
1028 | - | |
1029 | - /* | |
1030 | - * Get parameters from user space and initialize the pm | |
1031 | - * array. Return various errors if the user did something wrong. | |
1032 | - */ | |
1033 | - for (i = 0; i < nr_pages; i++) { | |
1034 | - const void __user *p; | |
1035 | - | |
1036 | - err = -EFAULT; | |
1037 | - if (get_user(p, pages + i)) | |
1038 | - goto out; | |
1039 | - | |
1040 | - pm[i].addr = (unsigned long)p; | |
1041 | - if (nodes) { | |
1042 | - int node; | |
1043 | - | |
1044 | - if (get_user(node, nodes + i)) | |
1045 | - goto out; | |
1046 | - | |
1047 | - err = -ENODEV; | |
1048 | - if (!node_state(node, N_HIGH_MEMORY)) | |
1049 | - goto out; | |
1050 | - | |
1051 | - err = -EACCES; | |
1052 | - if (!node_isset(node, task_nodes)) | |
1053 | - goto out; | |
1054 | - | |
1055 | - pm[i].node = node; | |
1056 | - } else | |
1057 | - pm[i].node = 0; /* anything to not match MAX_NUMNODES */ | |
1058 | - } | |
1059 | - /* End marker */ | |
1060 | - pm[nr_pages].node = MAX_NUMNODES; | |
1061 | - | |
1062 | - err = do_move_pages(mm, pm, flags & MPOL_MF_MOVE_ALL); | |
1063 | - if (err >= 0) | |
1064 | - /* Return status information */ | |
1065 | - for (i = 0; i < nr_pages; i++) | |
1066 | - if (put_user(pm[i].status, status + i)) | |
1067 | - err = -EFAULT; | |
1068 | - | |
1069 | 1091 | out: |
1070 | - vfree(pm); | |
1071 | -out2: | |
1072 | 1092 | mmput(mm); |
1073 | 1093 | return err; |
1074 | 1094 | } |