diff options
-rw-r--r-- | mm/mempolicy.c | 185 |
1 files changed, 91 insertions, 94 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index ffd3be66b255..d44c524e5ae4 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -110,9 +110,6 @@ struct mempolicy default_policy = { | |||
110 | .policy = MPOL_DEFAULT, | 110 | .policy = MPOL_DEFAULT, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | static void mpol_rebind_policy(struct mempolicy *pol, | ||
114 | const nodemask_t *newmask); | ||
115 | |||
116 | /* Check that the nodemask contains at least one populated zone */ | 113 | /* Check that the nodemask contains at least one populated zone */ |
117 | static int is_valid_nodemask(nodemask_t *nodemask) | 114 | static int is_valid_nodemask(nodemask_t *nodemask) |
118 | { | 115 | { |
@@ -203,6 +200,97 @@ free: | |||
203 | return ERR_PTR(-EINVAL); | 200 | return ERR_PTR(-EINVAL); |
204 | } | 201 | } |
205 | 202 | ||
203 | /* Migrate a policy to a different set of nodes */ | ||
204 | static void mpol_rebind_policy(struct mempolicy *pol, | ||
205 | const nodemask_t *newmask) | ||
206 | { | ||
207 | nodemask_t tmp; | ||
208 | int static_nodes; | ||
209 | int relative_nodes; | ||
210 | |||
211 | if (!pol) | ||
212 | return; | ||
213 | static_nodes = pol->flags & MPOL_F_STATIC_NODES; | ||
214 | relative_nodes = pol->flags & MPOL_F_RELATIVE_NODES; | ||
215 | if (!mpol_store_user_nodemask(pol) && | ||
216 | nodes_equal(pol->w.cpuset_mems_allowed, *newmask)) | ||
217 | return; | ||
218 | |||
219 | switch (pol->policy) { | ||
220 | case MPOL_DEFAULT: | ||
221 | break; | ||
222 | case MPOL_BIND: | ||
223 | /* Fall through */ | ||
224 | case MPOL_INTERLEAVE: | ||
225 | if (static_nodes) | ||
226 | nodes_and(tmp, pol->w.user_nodemask, *newmask); | ||
227 | else if (relative_nodes) | ||
228 | mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, | ||
229 | newmask); | ||
230 | else { | ||
231 | nodes_remap(tmp, pol->v.nodes, | ||
232 | pol->w.cpuset_mems_allowed, *newmask); | ||
233 | pol->w.cpuset_mems_allowed = *newmask; | ||
234 | } | ||
235 | pol->v.nodes = tmp; | ||
236 | if (!node_isset(current->il_next, tmp)) { | ||
237 | current->il_next = next_node(current->il_next, tmp); | ||
238 | if (current->il_next >= MAX_NUMNODES) | ||
239 | current->il_next = first_node(tmp); | ||
240 | if (current->il_next >= MAX_NUMNODES) | ||
241 | current->il_next = numa_node_id(); | ||
242 | } | ||
243 | break; | ||
244 | case MPOL_PREFERRED: | ||
245 | if (static_nodes) { | ||
246 | int node = first_node(pol->w.user_nodemask); | ||
247 | |||
248 | if (node_isset(node, *newmask)) | ||
249 | pol->v.preferred_node = node; | ||
250 | else | ||
251 | pol->v.preferred_node = -1; | ||
252 | } else if (relative_nodes) { | ||
253 | mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, | ||
254 | newmask); | ||
255 | pol->v.preferred_node = first_node(tmp); | ||
256 | } else { | ||
257 | pol->v.preferred_node = node_remap(pol->v.preferred_node, | ||
258 | pol->w.cpuset_mems_allowed, *newmask); | ||
259 | pol->w.cpuset_mems_allowed = *newmask; | ||
260 | } | ||
261 | break; | ||
262 | default: | ||
263 | BUG(); | ||
264 | break; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * Wrapper for mpol_rebind_policy() that just requires task | ||
270 | * pointer, and updates task mempolicy. | ||
271 | */ | ||
272 | |||
273 | void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new) | ||
274 | { | ||
275 | mpol_rebind_policy(tsk->mempolicy, new); | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * Rebind each vma in mm to new nodemask. | ||
280 | * | ||
281 | * Call holding a reference to mm. Takes mm->mmap_sem during call. | ||
282 | */ | ||
283 | |||
284 | void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new) | ||
285 | { | ||
286 | struct vm_area_struct *vma; | ||
287 | |||
288 | down_write(&mm->mmap_sem); | ||
289 | for (vma = mm->mmap; vma; vma = vma->vm_next) | ||
290 | mpol_rebind_policy(vma->vm_policy, new); | ||
291 | up_write(&mm->mmap_sem); | ||
292 | } | ||
293 | |||
206 | static void gather_stats(struct page *, void *, int pte_dirty); | 294 | static void gather_stats(struct page *, void *, int pte_dirty); |
207 | static void migrate_page_add(struct page *page, struct list_head *pagelist, | 295 | static void migrate_page_add(struct page *page, struct list_head *pagelist, |
208 | unsigned long flags); | 296 | unsigned long flags); |
@@ -1757,97 +1845,6 @@ void numa_default_policy(void) | |||
1757 | do_set_mempolicy(MPOL_DEFAULT, 0, NULL); | 1845 | do_set_mempolicy(MPOL_DEFAULT, 0, NULL); |
1758 | } | 1846 | } |
1759 | 1847 | ||
1760 | /* Migrate a policy to a different set of nodes */ | ||
1761 | static void mpol_rebind_policy(struct mempolicy *pol, | ||
1762 | const nodemask_t *newmask) | ||
1763 | { | ||
1764 | nodemask_t tmp; | ||
1765 | int static_nodes; | ||
1766 | int relative_nodes; | ||
1767 | |||
1768 | if (!pol) | ||
1769 | return; | ||
1770 | static_nodes = pol->flags & MPOL_F_STATIC_NODES; | ||
1771 | relative_nodes = pol->flags & MPOL_F_RELATIVE_NODES; | ||
1772 | if (!mpol_store_user_nodemask(pol) && | ||
1773 | nodes_equal(pol->w.cpuset_mems_allowed, *newmask)) | ||
1774 | return; | ||
1775 | |||
1776 | switch (pol->policy) { | ||
1777 | case MPOL_DEFAULT: | ||
1778 | break; | ||
1779 | case MPOL_BIND: | ||
1780 | /* Fall through */ | ||
1781 | case MPOL_INTERLEAVE: | ||
1782 | if (static_nodes) | ||
1783 | nodes_and(tmp, pol->w.user_nodemask, *newmask); | ||
1784 | else if (relative_nodes) | ||
1785 | mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, | ||
1786 | newmask); | ||
1787 | else { | ||
1788 | nodes_remap(tmp, pol->v.nodes, | ||
1789 | pol->w.cpuset_mems_allowed, *newmask); | ||
1790 | pol->w.cpuset_mems_allowed = *newmask; | ||
1791 | } | ||
1792 | pol->v.nodes = tmp; | ||
1793 | if (!node_isset(current->il_next, tmp)) { | ||
1794 | current->il_next = next_node(current->il_next, tmp); | ||
1795 | if (current->il_next >= MAX_NUMNODES) | ||
1796 | current->il_next = first_node(tmp); | ||
1797 | if (current->il_next >= MAX_NUMNODES) | ||
1798 | current->il_next = numa_node_id(); | ||
1799 | } | ||
1800 | break; | ||
1801 | case MPOL_PREFERRED: | ||
1802 | if (static_nodes) { | ||
1803 | int node = first_node(pol->w.user_nodemask); | ||
1804 | |||
1805 | if (node_isset(node, *newmask)) | ||
1806 | pol->v.preferred_node = node; | ||
1807 | else | ||
1808 | pol->v.preferred_node = -1; | ||
1809 | } else if (relative_nodes) { | ||
1810 | mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, | ||
1811 | newmask); | ||
1812 | pol->v.preferred_node = first_node(tmp); | ||
1813 | } else { | ||
1814 | pol->v.preferred_node = node_remap(pol->v.preferred_node, | ||
1815 | pol->w.cpuset_mems_allowed, *newmask); | ||
1816 | pol->w.cpuset_mems_allowed = *newmask; | ||
1817 | } | ||
1818 | break; | ||
1819 | default: | ||
1820 | BUG(); | ||
1821 | break; | ||
1822 | } | ||
1823 | } | ||
1824 | |||
1825 | /* | ||
1826 | * Wrapper for mpol_rebind_policy() that just requires task | ||
1827 | * pointer, and updates task mempolicy. | ||
1828 | */ | ||
1829 | |||
1830 | void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new) | ||
1831 | { | ||
1832 | mpol_rebind_policy(tsk->mempolicy, new); | ||
1833 | } | ||
1834 | |||
1835 | /* | ||
1836 | * Rebind each vma in mm to new nodemask. | ||
1837 | * | ||
1838 | * Call holding a reference to mm. Takes mm->mmap_sem during call. | ||
1839 | */ | ||
1840 | |||
1841 | void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new) | ||
1842 | { | ||
1843 | struct vm_area_struct *vma; | ||
1844 | |||
1845 | down_write(&mm->mmap_sem); | ||
1846 | for (vma = mm->mmap; vma; vma = vma->vm_next) | ||
1847 | mpol_rebind_policy(vma->vm_policy, new); | ||
1848 | up_write(&mm->mmap_sem); | ||
1849 | } | ||
1850 | |||
1851 | /* | 1848 | /* |
1852 | * Display pages allocated per node and memory policy via /proc. | 1849 | * Display pages allocated per node and memory policy via /proc. |
1853 | */ | 1850 | */ |