diff options
author | Lee Schermerhorn <Lee.Schermerhorn@hp.com> | 2007-10-16 04:24:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:42:54 -0400 |
commit | 754af6f5a85fcd1ecb456851d20c65e4c6ce10ab (patch) | |
tree | 8c985bfd704a8c993d6ca992725969c6fc5c9e5a | |
parent | 32a4330d4156e55a4888a201f484dbafed9504ed (diff) |
Mem Policy: add MPOL_F_MEMS_ALLOWED get_mempolicy() flag
Allow an application to query the memories allowed by its context.
Updated numa_memory_policy.txt to mention that applications can use this to
obtain allowed memories for constructing valid policies.
TODO: update out-of-tree libnuma wrapper[s], or maybe add a new
wrapper--e.g., numa_get_mems_allowed() ?
Also, update numa syscall man pages.
Tested with memtoy V>=0.13.
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Acked-by: Christoph Lameter <clameter@sgi.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | Documentation/vm/numa_memory_policy.txt | 33 | ||||
-rw-r--r-- | include/linux/mempolicy.h | 1 | ||||
-rw-r--r-- | mm/mempolicy.c | 12 |
3 files changed, 28 insertions, 18 deletions
diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt index 8242f52d0f22..dd4986497996 100644 --- a/Documentation/vm/numa_memory_policy.txt +++ b/Documentation/vm/numa_memory_policy.txt | |||
@@ -302,31 +302,30 @@ MEMORY POLICIES AND CPUSETS | |||
302 | 302 | ||
303 | Memory policies work within cpusets as described above. For memory policies | 303 | Memory policies work within cpusets as described above. For memory policies |
304 | that require a node or set of nodes, the nodes are restricted to the set of | 304 | that require a node or set of nodes, the nodes are restricted to the set of |
305 | nodes whose memories are allowed by the cpuset constraints. If the | 305 | nodes whose memories are allowed by the cpuset constraints. If the nodemask |
306 | intersection of the set of nodes specified for the policy and the set of nodes | 306 | specified for the policy contains nodes that are not allowed by the cpuset, or |
307 | allowed by the cpuset is the empty set, the policy is considered invalid and | 307 | the intersection of the set of nodes specified for the policy and the set of |
308 | cannot be installed. | 308 | nodes with memory is the empty set, the policy is considered invalid |
309 | and cannot be installed. | ||
309 | 310 | ||
310 | The interaction of memory policies and cpusets can be problematic for a | 311 | The interaction of memory policies and cpusets can be problematic for a |
311 | couple of reasons: | 312 | couple of reasons: |
312 | 313 | ||
313 | 1) the memory policy APIs take physical node id's as arguments. However, the | 314 | 1) the memory policy APIs take physical node id's as arguments. As mentioned |
314 | memory policy APIs do not provide a way to determine what nodes are valid | 315 | above, it is illegal to specify nodes that are not allowed in the cpuset. |
315 | in the context where the application is running. An application MAY consult | 316 | The application must query the allowed nodes using the get_mempolicy() |
316 | the cpuset file system [directly or via an out of tree, and not generally | 317 | API with the MPOL_F_MEMS_ALLOWED flag to determine the allowed nodes and |
317 | available, libcpuset API] to obtain this information, but then the | 318 | restrict itself to those nodes. However, the resources available to a |
318 | application must be aware that it is running in a cpuset and use what are | 319 | cpuset can be changed by the system administrator, or a workload manager |
319 | intended primarily as administrative APIs. | 320 | application, at any time. So, a task may still get errors attempting to |
320 | 321 | specify policy nodes, and must query the allowed memories again. | |
321 | However, as long as the policy specifies at least one node that is valid | ||
322 | in the controlling cpuset, the policy can be used. | ||
323 | 322 | ||
324 | 2) when tasks in two cpusets share access to a memory region, such as shared | 323 | 2) when tasks in two cpusets share access to a memory region, such as shared |
325 | memory segments created by shmget() of mmap() with the MAP_ANONYMOUS and | 324 | memory segments created by shmget() of mmap() with the MAP_ANONYMOUS and |
326 | MAP_SHARED flags, and any of the tasks install shared policy on the region, | 325 | MAP_SHARED flags, and any of the tasks install shared policy on the region, |
327 | only nodes whose memories are allowed in both cpusets may be used in the | 326 | only nodes whose memories are allowed in both cpusets may be used in the |
328 | policies. Again, obtaining this information requires "stepping outside" | 327 | policies. Obtaining this information requires "stepping outside" the |
329 | the memory policy APIs, as well as knowing in what cpusets other task might | 328 | memory policy APIs to use the cpuset information and requires that one |
330 | be attaching to the shared region, to use the cpuset information. | 329 | know in what cpusets other task might be attaching to the shared region. |
331 | Furthermore, if the cpusets' allowed memory sets are disjoint, "local" | 330 | Furthermore, if the cpusets' allowed memory sets are disjoint, "local" |
332 | allocation is the only valid policy. | 331 | allocation is the only valid policy. |
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index a020eb2d4e2a..7e9698ec839b 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h | |||
@@ -19,6 +19,7 @@ | |||
19 | /* Flags for get_mem_policy */ | 19 | /* Flags for get_mem_policy */ |
20 | #define MPOL_F_NODE (1<<0) /* return next IL mode instead of node mask */ | 20 | #define MPOL_F_NODE (1<<0) /* return next IL mode instead of node mask */ |
21 | #define MPOL_F_ADDR (1<<1) /* look up vma using address */ | 21 | #define MPOL_F_ADDR (1<<1) /* look up vma using address */ |
22 | #define MPOL_F_MEMS_ALLOWED (1<<2) /* return allowed memories */ | ||
22 | 23 | ||
23 | /* Flags for mbind */ | 24 | /* Flags for mbind */ |
24 | #define MPOL_MF_STRICT (1<<0) /* Verify existing pages in the mapping */ | 25 | #define MPOL_MF_STRICT (1<<0) /* Verify existing pages in the mapping */ |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 3a45b7dd0a09..ccbdb22147bb 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -526,8 +526,18 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask, | |||
526 | struct mempolicy *pol = current->mempolicy; | 526 | struct mempolicy *pol = current->mempolicy; |
527 | 527 | ||
528 | cpuset_update_task_memory_state(); | 528 | cpuset_update_task_memory_state(); |
529 | if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR)) | 529 | if (flags & |
530 | ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR|MPOL_F_MEMS_ALLOWED)) | ||
530 | return -EINVAL; | 531 | return -EINVAL; |
532 | |||
533 | if (flags & MPOL_F_MEMS_ALLOWED) { | ||
534 | if (flags & (MPOL_F_NODE|MPOL_F_ADDR)) | ||
535 | return -EINVAL; | ||
536 | *policy = 0; /* just so it's initialized */ | ||
537 | *nmask = cpuset_current_mems_allowed; | ||
538 | return 0; | ||
539 | } | ||
540 | |||
531 | if (flags & MPOL_F_ADDR) { | 541 | if (flags & MPOL_F_ADDR) { |
532 | down_read(&mm->mmap_sem); | 542 | down_read(&mm->mmap_sem); |
533 | vma = find_vma_intersection(mm, addr, addr+1); | 543 | vma = find_vma_intersection(mm, addr, addr+1); |