Commit 754af6f5 authored by Lee Schermerhorn's avatar Lee Schermerhorn Committed by Linus Torvalds

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: default avatarLee Schermerhorn <lee.schermerhorn@hp.com>
Acked-by: default avatarChristoph Lameter <clameter@sgi.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 32a4330d
...@@ -302,31 +302,30 @@ MEMORY POLICIES AND CPUSETS ...@@ -302,31 +302,30 @@ MEMORY POLICIES AND CPUSETS
Memory policies work within cpusets as described above. For memory policies Memory policies work within cpusets as described above. For memory policies
that require a node or set of nodes, the nodes are restricted to the set of that require a node or set of nodes, the nodes are restricted to the set of
nodes whose memories are allowed by the cpuset constraints. If the nodes whose memories are allowed by the cpuset constraints. If the nodemask
intersection of the set of nodes specified for the policy and the set of nodes specified for the policy contains nodes that are not allowed by the cpuset, or
allowed by the cpuset is the empty set, the policy is considered invalid and the intersection of the set of nodes specified for the policy and the set of
cannot be installed. nodes with memory is the empty set, the policy is considered invalid
and cannot be installed.
The interaction of memory policies and cpusets can be problematic for a The interaction of memory policies and cpusets can be problematic for a
couple of reasons: couple of reasons:
1) the memory policy APIs take physical node id's as arguments. However, the 1) the memory policy APIs take physical node id's as arguments. As mentioned
memory policy APIs do not provide a way to determine what nodes are valid above, it is illegal to specify nodes that are not allowed in the cpuset.
in the context where the application is running. An application MAY consult The application must query the allowed nodes using the get_mempolicy()
the cpuset file system [directly or via an out of tree, and not generally API with the MPOL_F_MEMS_ALLOWED flag to determine the allowed nodes and
available, libcpuset API] to obtain this information, but then the restrict itself to those nodes. However, the resources available to a
application must be aware that it is running in a cpuset and use what are cpuset can be changed by the system administrator, or a workload manager
intended primarily as administrative APIs. application, at any time. So, a task may still get errors attempting to
specify policy nodes, and must query the allowed memories again.
However, as long as the policy specifies at least one node that is valid
in the controlling cpuset, the policy can be used.
2) when tasks in two cpusets share access to a memory region, such as shared 2) when tasks in two cpusets share access to a memory region, such as shared
memory segments created by shmget() of mmap() with the MAP_ANONYMOUS and memory segments created by shmget() of mmap() with the MAP_ANONYMOUS and
MAP_SHARED flags, and any of the tasks install shared policy on the region, MAP_SHARED flags, and any of the tasks install shared policy on the region,
only nodes whose memories are allowed in both cpusets may be used in the only nodes whose memories are allowed in both cpusets may be used in the
policies. Again, obtaining this information requires "stepping outside" policies. Obtaining this information requires "stepping outside" the
the memory policy APIs, as well as knowing in what cpusets other task might memory policy APIs to use the cpuset information and requires that one
be attaching to the shared region, to use the cpuset information. know in what cpusets other task might be attaching to the shared region.
Furthermore, if the cpusets' allowed memory sets are disjoint, "local" Furthermore, if the cpusets' allowed memory sets are disjoint, "local"
allocation is the only valid policy. allocation is the only valid policy.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
/* Flags for get_mem_policy */ /* Flags for get_mem_policy */
#define MPOL_F_NODE (1<<0) /* return next IL mode instead of node mask */ #define MPOL_F_NODE (1<<0) /* return next IL mode instead of node mask */
#define MPOL_F_ADDR (1<<1) /* look up vma using address */ #define MPOL_F_ADDR (1<<1) /* look up vma using address */
#define MPOL_F_MEMS_ALLOWED (1<<2) /* return allowed memories */
/* Flags for mbind */ /* Flags for mbind */
#define MPOL_MF_STRICT (1<<0) /* Verify existing pages in the mapping */ #define MPOL_MF_STRICT (1<<0) /* Verify existing pages in the mapping */
......
...@@ -526,8 +526,18 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask, ...@@ -526,8 +526,18 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask,
struct mempolicy *pol = current->mempolicy; struct mempolicy *pol = current->mempolicy;
cpuset_update_task_memory_state(); cpuset_update_task_memory_state();
if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR)) if (flags &
~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR|MPOL_F_MEMS_ALLOWED))
return -EINVAL; return -EINVAL;
if (flags & MPOL_F_MEMS_ALLOWED) {
if (flags & (MPOL_F_NODE|MPOL_F_ADDR))
return -EINVAL;
*policy = 0; /* just so it's initialized */
*nmask = cpuset_current_mems_allowed;
return 0;
}
if (flags & MPOL_F_ADDR) { if (flags & MPOL_F_ADDR) {
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
vma = find_vma_intersection(mm, addr, addr+1); vma = find_vma_intersection(mm, addr, addr+1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment