aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mempolicy.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r--mm/mempolicy.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index a94d994eaaa8..c1b907789d84 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -181,27 +181,43 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
181{ 181{
182 struct mempolicy *policy; 182 struct mempolicy *policy;
183 nodemask_t cpuset_context_nmask; 183 nodemask_t cpuset_context_nmask;
184 int localalloc = 0;
185 int ret; 184 int ret;
186 185
187 pr_debug("setting mode %d flags %d nodes[0] %lx\n", 186 pr_debug("setting mode %d flags %d nodes[0] %lx\n",
188 mode, flags, nodes ? nodes_addr(*nodes)[0] : -1); 187 mode, flags, nodes ? nodes_addr(*nodes)[0] : -1);
189 188
190 if (mode == MPOL_DEFAULT) 189 if (mode == MPOL_DEFAULT) {
191 return NULL; 190 if (nodes && !nodes_empty(*nodes))
192 if (!nodes || nodes_empty(*nodes)) {
193 if (mode != MPOL_PREFERRED)
194 return ERR_PTR(-EINVAL); 191 return ERR_PTR(-EINVAL);
195 localalloc = 1; /* special case: no mode flags */ 192 return NULL;
196 } 193 }
194 VM_BUG_ON(!nodes);
195
196 /*
197 * MPOL_PREFERRED cannot be used with MPOL_F_STATIC_NODES or
198 * MPOL_F_RELATIVE_NODES if the nodemask is empty (local allocation).
199 * All other modes require a valid pointer to a non-empty nodemask.
200 */
201 if (mode == MPOL_PREFERRED) {
202 if (nodes_empty(*nodes)) {
203 if (((flags & MPOL_F_STATIC_NODES) ||
204 (flags & MPOL_F_RELATIVE_NODES)))
205 return ERR_PTR(-EINVAL);
206 nodes = NULL; /* flag local alloc */
207 }
208 } else if (nodes_empty(*nodes))
209 return ERR_PTR(-EINVAL);
197 policy = kmem_cache_alloc(policy_cache, GFP_KERNEL); 210 policy = kmem_cache_alloc(policy_cache, GFP_KERNEL);
198 if (!policy) 211 if (!policy)
199 return ERR_PTR(-ENOMEM); 212 return ERR_PTR(-ENOMEM);
200 atomic_set(&policy->refcnt, 1); 213 atomic_set(&policy->refcnt, 1);
201 policy->policy = mode; 214 policy->policy = mode;
215 policy->flags = flags;
202 216
203 if (!localalloc) { 217 if (nodes) {
204 policy->flags = flags; 218 /*
219 * cpuset related setup doesn't apply to local allocation
220 */
205 cpuset_update_task_memory_state(); 221 cpuset_update_task_memory_state();
206 if (flags & MPOL_F_RELATIVE_NODES) 222 if (flags & MPOL_F_RELATIVE_NODES)
207 mpol_relative_nodemask(&cpuset_context_nmask, nodes, 223 mpol_relative_nodemask(&cpuset_context_nmask, nodes,
@@ -217,7 +233,7 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags,
217 } 233 }
218 234
219 ret = mpol_ops[mode].create(policy, 235 ret = mpol_ops[mode].create(policy,
220 localalloc ? NULL : &cpuset_context_nmask); 236 nodes ? &cpuset_context_nmask : NULL);
221 if (ret < 0) { 237 if (ret < 0) {
222 kmem_cache_free(policy_cache, policy); 238 kmem_cache_free(policy_cache, policy);
223 return ERR_PTR(ret); 239 return ERR_PTR(ret);
@@ -259,10 +275,6 @@ static void mpol_rebind_preferred(struct mempolicy *pol,
259{ 275{
260 nodemask_t tmp; 276 nodemask_t tmp;
261 277
262 /*
263 * check 'STATIC_NODES first, as preferred_node == -1 may be
264 * a temporary, "fallback" state for this policy.
265 */
266 if (pol->flags & MPOL_F_STATIC_NODES) { 278 if (pol->flags & MPOL_F_STATIC_NODES) {
267 int node = first_node(pol->w.user_nodemask); 279 int node = first_node(pol->w.user_nodemask);
268 280
@@ -270,12 +282,10 @@ static void mpol_rebind_preferred(struct mempolicy *pol,
270 pol->v.preferred_node = node; 282 pol->v.preferred_node = node;
271 else 283 else
272 pol->v.preferred_node = -1; 284 pol->v.preferred_node = -1;
273 } else if (pol->v.preferred_node == -1) {
274 return; /* no remap required for explicit local alloc */
275 } else if (pol->flags & MPOL_F_RELATIVE_NODES) { 285 } else if (pol->flags & MPOL_F_RELATIVE_NODES) {
276 mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, nodes); 286 mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, nodes);
277 pol->v.preferred_node = first_node(tmp); 287 pol->v.preferred_node = first_node(tmp);
278 } else { 288 } else if (pol->v.preferred_node != -1) {
279 pol->v.preferred_node = node_remap(pol->v.preferred_node, 289 pol->v.preferred_node = node_remap(pol->v.preferred_node,
280 pol->w.cpuset_mems_allowed, 290 pol->w.cpuset_mems_allowed,
281 *nodes); 291 *nodes);