diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/mempolicy.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 2076b1542b8a..5abc57c2b8bd 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -457,6 +457,7 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask, | |||
457 | struct vm_area_struct *vma = NULL; | 457 | struct vm_area_struct *vma = NULL; |
458 | struct mempolicy *pol = current->mempolicy; | 458 | struct mempolicy *pol = current->mempolicy; |
459 | 459 | ||
460 | cpuset_update_current_mems_allowed(); | ||
460 | if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR)) | 461 | if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR)) |
461 | return -EINVAL; | 462 | return -EINVAL; |
462 | if (flags & MPOL_F_ADDR) { | 463 | if (flags & MPOL_F_ADDR) { |
@@ -1206,3 +1207,66 @@ void numa_default_policy(void) | |||
1206 | { | 1207 | { |
1207 | do_set_mempolicy(MPOL_DEFAULT, NULL); | 1208 | do_set_mempolicy(MPOL_DEFAULT, NULL); |
1208 | } | 1209 | } |
1210 | |||
1211 | /* Migrate a policy to a different set of nodes */ | ||
1212 | static void rebind_policy(struct mempolicy *pol, const nodemask_t *old, | ||
1213 | const nodemask_t *new) | ||
1214 | { | ||
1215 | nodemask_t tmp; | ||
1216 | |||
1217 | if (!pol) | ||
1218 | return; | ||
1219 | |||
1220 | switch (pol->policy) { | ||
1221 | case MPOL_DEFAULT: | ||
1222 | break; | ||
1223 | case MPOL_INTERLEAVE: | ||
1224 | nodes_remap(tmp, pol->v.nodes, *old, *new); | ||
1225 | pol->v.nodes = tmp; | ||
1226 | current->il_next = node_remap(current->il_next, *old, *new); | ||
1227 | break; | ||
1228 | case MPOL_PREFERRED: | ||
1229 | pol->v.preferred_node = node_remap(pol->v.preferred_node, | ||
1230 | *old, *new); | ||
1231 | break; | ||
1232 | case MPOL_BIND: { | ||
1233 | nodemask_t nodes; | ||
1234 | struct zone **z; | ||
1235 | struct zonelist *zonelist; | ||
1236 | |||
1237 | nodes_clear(nodes); | ||
1238 | for (z = pol->v.zonelist->zones; *z; z++) | ||
1239 | node_set((*z)->zone_pgdat->node_id, nodes); | ||
1240 | nodes_remap(tmp, nodes, *old, *new); | ||
1241 | nodes = tmp; | ||
1242 | |||
1243 | zonelist = bind_zonelist(&nodes); | ||
1244 | |||
1245 | /* If no mem, then zonelist is NULL and we keep old zonelist. | ||
1246 | * If that old zonelist has no remaining mems_allowed nodes, | ||
1247 | * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT. | ||
1248 | */ | ||
1249 | |||
1250 | if (zonelist) { | ||
1251 | /* Good - got mem - substitute new zonelist */ | ||
1252 | kfree(pol->v.zonelist); | ||
1253 | pol->v.zonelist = zonelist; | ||
1254 | } | ||
1255 | break; | ||
1256 | } | ||
1257 | default: | ||
1258 | BUG(); | ||
1259 | break; | ||
1260 | } | ||
1261 | } | ||
1262 | |||
1263 | /* | ||
1264 | * Someone moved this task to different nodes. Fixup mempolicies. | ||
1265 | * | ||
1266 | * TODO - fixup current->mm->vma and shmfs/tmpfs/hugetlbfs policies as well, | ||
1267 | * once we have a cpuset mechanism to mark which cpuset subtree is migrating. | ||
1268 | */ | ||
1269 | void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new) | ||
1270 | { | ||
1271 | rebind_policy(current->mempolicy, old, new); | ||
1272 | } | ||