diff options
| author | Brice Goglin <Brice.Goglin@inria.fr> | 2008-10-18 23:27:17 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-20 11:52:33 -0400 |
| commit | 5e9a0f023bee02bfb94e08590d998660c01f5a49 (patch) | |
| tree | 3cd2131f12a09cc9c84c31f99375256148e400fd /mm | |
| parent | 2f007e74bb85b9fc4eab28524052161703300f1a (diff) | |
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>
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/migrate.c | 152 |
1 files changed, 86 insertions, 66 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index a4c29081ebce..11c6c56ec017 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
| @@ -826,9 +826,11 @@ static struct page *new_page_node(struct page *p, unsigned long private, | |||
| 826 | * Move a set of pages as indicated in the pm array. The addr | 826 | * Move a set of pages as indicated in the pm array. The addr |
| 827 | * field must be set to the virtual address of the page to be moved | 827 | * field must be set to the virtual address of the page to be moved |
| 828 | * and the node number must contain a valid target node. | 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 | static int do_move_page_to_node_array(struct mm_struct *mm, |
| 831 | int migrate_all) | 832 | struct page_to_node *pm, |
| 833 | int migrate_all) | ||
| 832 | { | 834 | { |
| 833 | int err; | 835 | int err; |
| 834 | struct page_to_node *pp; | 836 | struct page_to_node *pp; |
| @@ -906,6 +908,81 @@ set_status: | |||
| 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 | * Determine the nodes of an array of pages and store it in an array of status. | 986 | * Determine the nodes of an array of pages and store it in an array of status. |
| 910 | */ | 987 | */ |
| 911 | static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages, | 988 | static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages, |
| @@ -963,12 +1040,9 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, | |||
| 963 | const int __user *nodes, | 1040 | const int __user *nodes, |
| 964 | int __user *status, int flags) | 1041 | int __user *status, int flags) |
| 965 | { | 1042 | { |
| 966 | int err = 0; | ||
| 967 | int i; | ||
| 968 | struct task_struct *task; | 1043 | struct task_struct *task; |
| 969 | nodemask_t task_nodes; | ||
| 970 | struct mm_struct *mm; | 1044 | struct mm_struct *mm; |
| 971 | struct page_to_node *pm = NULL; | 1045 | int err; |
| 972 | 1046 | ||
| 973 | /* Check flags */ | 1047 | /* Check flags */ |
| 974 | if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL)) | 1048 | if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL)) |
| @@ -1000,75 +1074,21 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, | |||
| 1000 | (current->uid != task->suid) && (current->uid != task->uid) && | 1074 | (current->uid != task->suid) && (current->uid != task->uid) && |
| 1001 | !capable(CAP_SYS_NICE)) { | 1075 | !capable(CAP_SYS_NICE)) { |
| 1002 | err = -EPERM; | 1076 | err = -EPERM; |
| 1003 | goto out2; | 1077 | goto out; |
| 1004 | } | 1078 | } |
| 1005 | 1079 | ||
| 1006 | err = security_task_movememory(task); | 1080 | err = security_task_movememory(task); |
| 1007 | if (err) | 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 | err = do_pages_stat(mm, nr_pages, pages, status); | 1088 | err = do_pages_stat(mm, nr_pages, pages, status); |
| 1012 | goto out2; | ||
| 1013 | } | ||
| 1014 | |||
| 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 | } | 1089 | } |
| 1022 | 1090 | ||
| 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 | out: | 1091 | out: |
| 1070 | vfree(pm); | ||
| 1071 | out2: | ||
| 1072 | mmput(mm); | 1092 | mmput(mm); |
| 1073 | return err; | 1093 | return err; |
| 1074 | } | 1094 | } |
