|
@@ -110,9 +110,6 @@ struct mempolicy default_policy = {
|
|
|
.policy = MPOL_DEFAULT,
|
|
|
};
|
|
|
|
|
|
-static void mpol_rebind_policy(struct mempolicy *pol,
|
|
|
- const nodemask_t *newmask);
|
|
|
-
|
|
|
/* Check that the nodemask contains at least one populated zone */
|
|
|
static int is_valid_nodemask(nodemask_t *nodemask)
|
|
|
{
|
|
@@ -203,6 +200,97 @@ free:
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
}
|
|
|
|
|
|
+/* Migrate a policy to a different set of nodes */
|
|
|
+static void mpol_rebind_policy(struct mempolicy *pol,
|
|
|
+ const nodemask_t *newmask)
|
|
|
+{
|
|
|
+ nodemask_t tmp;
|
|
|
+ int static_nodes;
|
|
|
+ int relative_nodes;
|
|
|
+
|
|
|
+ if (!pol)
|
|
|
+ return;
|
|
|
+ static_nodes = pol->flags & MPOL_F_STATIC_NODES;
|
|
|
+ relative_nodes = pol->flags & MPOL_F_RELATIVE_NODES;
|
|
|
+ if (!mpol_store_user_nodemask(pol) &&
|
|
|
+ nodes_equal(pol->w.cpuset_mems_allowed, *newmask))
|
|
|
+ return;
|
|
|
+
|
|
|
+ switch (pol->policy) {
|
|
|
+ case MPOL_DEFAULT:
|
|
|
+ break;
|
|
|
+ case MPOL_BIND:
|
|
|
+ /* Fall through */
|
|
|
+ case MPOL_INTERLEAVE:
|
|
|
+ if (static_nodes)
|
|
|
+ nodes_and(tmp, pol->w.user_nodemask, *newmask);
|
|
|
+ else if (relative_nodes)
|
|
|
+ mpol_relative_nodemask(&tmp, &pol->w.user_nodemask,
|
|
|
+ newmask);
|
|
|
+ else {
|
|
|
+ nodes_remap(tmp, pol->v.nodes,
|
|
|
+ pol->w.cpuset_mems_allowed, *newmask);
|
|
|
+ pol->w.cpuset_mems_allowed = *newmask;
|
|
|
+ }
|
|
|
+ pol->v.nodes = tmp;
|
|
|
+ if (!node_isset(current->il_next, tmp)) {
|
|
|
+ current->il_next = next_node(current->il_next, tmp);
|
|
|
+ if (current->il_next >= MAX_NUMNODES)
|
|
|
+ current->il_next = first_node(tmp);
|
|
|
+ if (current->il_next >= MAX_NUMNODES)
|
|
|
+ current->il_next = numa_node_id();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MPOL_PREFERRED:
|
|
|
+ if (static_nodes) {
|
|
|
+ int node = first_node(pol->w.user_nodemask);
|
|
|
+
|
|
|
+ if (node_isset(node, *newmask))
|
|
|
+ pol->v.preferred_node = node;
|
|
|
+ else
|
|
|
+ pol->v.preferred_node = -1;
|
|
|
+ } else if (relative_nodes) {
|
|
|
+ mpol_relative_nodemask(&tmp, &pol->w.user_nodemask,
|
|
|
+ newmask);
|
|
|
+ pol->v.preferred_node = first_node(tmp);
|
|
|
+ } else {
|
|
|
+ pol->v.preferred_node = node_remap(pol->v.preferred_node,
|
|
|
+ pol->w.cpuset_mems_allowed, *newmask);
|
|
|
+ pol->w.cpuset_mems_allowed = *newmask;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ BUG();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Wrapper for mpol_rebind_policy() that just requires task
|
|
|
+ * pointer, and updates task mempolicy.
|
|
|
+ */
|
|
|
+
|
|
|
+void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new)
|
|
|
+{
|
|
|
+ mpol_rebind_policy(tsk->mempolicy, new);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Rebind each vma in mm to new nodemask.
|
|
|
+ *
|
|
|
+ * Call holding a reference to mm. Takes mm->mmap_sem during call.
|
|
|
+ */
|
|
|
+
|
|
|
+void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
|
|
|
+{
|
|
|
+ struct vm_area_struct *vma;
|
|
|
+
|
|
|
+ down_write(&mm->mmap_sem);
|
|
|
+ for (vma = mm->mmap; vma; vma = vma->vm_next)
|
|
|
+ mpol_rebind_policy(vma->vm_policy, new);
|
|
|
+ up_write(&mm->mmap_sem);
|
|
|
+}
|
|
|
+
|
|
|
static void gather_stats(struct page *, void *, int pte_dirty);
|
|
|
static void migrate_page_add(struct page *page, struct list_head *pagelist,
|
|
|
unsigned long flags);
|
|
@@ -1757,97 +1845,6 @@ void numa_default_policy(void)
|
|
|
do_set_mempolicy(MPOL_DEFAULT, 0, NULL);
|
|
|
}
|
|
|
|
|
|
-/* Migrate a policy to a different set of nodes */
|
|
|
-static void mpol_rebind_policy(struct mempolicy *pol,
|
|
|
- const nodemask_t *newmask)
|
|
|
-{
|
|
|
- nodemask_t tmp;
|
|
|
- int static_nodes;
|
|
|
- int relative_nodes;
|
|
|
-
|
|
|
- if (!pol)
|
|
|
- return;
|
|
|
- static_nodes = pol->flags & MPOL_F_STATIC_NODES;
|
|
|
- relative_nodes = pol->flags & MPOL_F_RELATIVE_NODES;
|
|
|
- if (!mpol_store_user_nodemask(pol) &&
|
|
|
- nodes_equal(pol->w.cpuset_mems_allowed, *newmask))
|
|
|
- return;
|
|
|
-
|
|
|
- switch (pol->policy) {
|
|
|
- case MPOL_DEFAULT:
|
|
|
- break;
|
|
|
- case MPOL_BIND:
|
|
|
- /* Fall through */
|
|
|
- case MPOL_INTERLEAVE:
|
|
|
- if (static_nodes)
|
|
|
- nodes_and(tmp, pol->w.user_nodemask, *newmask);
|
|
|
- else if (relative_nodes)
|
|
|
- mpol_relative_nodemask(&tmp, &pol->w.user_nodemask,
|
|
|
- newmask);
|
|
|
- else {
|
|
|
- nodes_remap(tmp, pol->v.nodes,
|
|
|
- pol->w.cpuset_mems_allowed, *newmask);
|
|
|
- pol->w.cpuset_mems_allowed = *newmask;
|
|
|
- }
|
|
|
- pol->v.nodes = tmp;
|
|
|
- if (!node_isset(current->il_next, tmp)) {
|
|
|
- current->il_next = next_node(current->il_next, tmp);
|
|
|
- if (current->il_next >= MAX_NUMNODES)
|
|
|
- current->il_next = first_node(tmp);
|
|
|
- if (current->il_next >= MAX_NUMNODES)
|
|
|
- current->il_next = numa_node_id();
|
|
|
- }
|
|
|
- break;
|
|
|
- case MPOL_PREFERRED:
|
|
|
- if (static_nodes) {
|
|
|
- int node = first_node(pol->w.user_nodemask);
|
|
|
-
|
|
|
- if (node_isset(node, *newmask))
|
|
|
- pol->v.preferred_node = node;
|
|
|
- else
|
|
|
- pol->v.preferred_node = -1;
|
|
|
- } else if (relative_nodes) {
|
|
|
- mpol_relative_nodemask(&tmp, &pol->w.user_nodemask,
|
|
|
- newmask);
|
|
|
- pol->v.preferred_node = first_node(tmp);
|
|
|
- } else {
|
|
|
- pol->v.preferred_node = node_remap(pol->v.preferred_node,
|
|
|
- pol->w.cpuset_mems_allowed, *newmask);
|
|
|
- pol->w.cpuset_mems_allowed = *newmask;
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- BUG();
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Wrapper for mpol_rebind_policy() that just requires task
|
|
|
- * pointer, and updates task mempolicy.
|
|
|
- */
|
|
|
-
|
|
|
-void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new)
|
|
|
-{
|
|
|
- mpol_rebind_policy(tsk->mempolicy, new);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Rebind each vma in mm to new nodemask.
|
|
|
- *
|
|
|
- * Call holding a reference to mm. Takes mm->mmap_sem during call.
|
|
|
- */
|
|
|
-
|
|
|
-void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
|
|
|
-{
|
|
|
- struct vm_area_struct *vma;
|
|
|
-
|
|
|
- down_write(&mm->mmap_sem);
|
|
|
- for (vma = mm->mmap; vma; vma = vma->vm_next)
|
|
|
- mpol_rebind_policy(vma->vm_policy, new);
|
|
|
- up_write(&mm->mmap_sem);
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Display pages allocated per node and memory policy via /proc.
|
|
|
*/
|