aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mempolicy.h6
-rw-r--r--kernel/cpuset.c4
-rw-r--r--mm/mempolicy.c64
3 files changed, 74 insertions, 0 deletions
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 7af8cb836e78..8b67cf837ca9 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -154,6 +154,7 @@ struct mempolicy *get_vma_policy(struct task_struct *task,
154 154
155extern void numa_default_policy(void); 155extern void numa_default_policy(void);
156extern void numa_policy_init(void); 156extern void numa_policy_init(void);
157extern void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new);
157extern struct mempolicy default_policy; 158extern struct mempolicy default_policy;
158 159
159#else 160#else
@@ -226,6 +227,11 @@ static inline void numa_default_policy(void)
226{ 227{
227} 228}
228 229
230static inline void numa_policy_rebind(const nodemask_t *old,
231 const nodemask_t *new)
232{
233}
234
229#endif /* CONFIG_NUMA */ 235#endif /* CONFIG_NUMA */
230#endif /* __KERNEL__ */ 236#endif /* __KERNEL__ */
231 237
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 6633f3fb6417..5a737ed9dac7 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -32,6 +32,7 @@
32#include <linux/kernel.h> 32#include <linux/kernel.h>
33#include <linux/kmod.h> 33#include <linux/kmod.h>
34#include <linux/list.h> 34#include <linux/list.h>
35#include <linux/mempolicy.h>
35#include <linux/mm.h> 36#include <linux/mm.h>
36#include <linux/module.h> 37#include <linux/module.h>
37#include <linux/mount.h> 38#include <linux/mount.h>
@@ -600,6 +601,7 @@ static void refresh_mems(void)
600 601
601 if (current->cpuset_mems_generation != my_cpusets_mem_gen) { 602 if (current->cpuset_mems_generation != my_cpusets_mem_gen) {
602 struct cpuset *cs; 603 struct cpuset *cs;
604 nodemask_t oldmem = current->mems_allowed;
603 605
604 down(&callback_sem); 606 down(&callback_sem);
605 task_lock(current); 607 task_lock(current);
@@ -608,6 +610,8 @@ static void refresh_mems(void)
608 current->cpuset_mems_generation = cs->mems_generation; 610 current->cpuset_mems_generation = cs->mems_generation;
609 task_unlock(current); 611 task_unlock(current);
610 up(&callback_sem); 612 up(&callback_sem);
613 if (!nodes_equal(oldmem, current->mems_allowed))
614 numa_policy_rebind(&oldmem, &current->mems_allowed);
611 } 615 }
612} 616}
613 617
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 */
1212static 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 */
1269void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new)
1270{
1271 rebind_policy(current->mempolicy, old, new);
1272}