diff options
author | Lee Schermerhorn <lee.schermerhorn@hp.com> | 2008-04-28 02:13:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 08:58:24 -0700 |
commit | 095f1fc4ebf36c64fddf9b6db29b1ab5517378e6 (patch) | |
tree | 39aae9d5b05d8501d1794e92c6115331c0a40848 /mm/mempolicy.c | |
parent | 2291990ab36b4b2d8a81b1f92e7a046e51632a60 (diff) | |
download | lwn-095f1fc4ebf36c64fddf9b6db29b1ab5517378e6.tar.gz lwn-095f1fc4ebf36c64fddf9b6db29b1ab5517378e6.zip |
mempolicy: rework shmem mpol parsing and display
mm/shmem.c currently contains functions to parse and display memory policy
strings for the tmpfs 'mpol' mount option. Move this to mm/mempolicy.c with
the rest of the mempolicy support. With subsequent patches, we'll be able to
remove knowledge of the details [mode, flags, policy, ...] completely from
shmem.c
1) replace shmem_parse_mpol() in mm/shmem.c with mpol_parse_str() in
mm/mempolicy.c. Rework to use the policy_types[] array [used by
mpol_to_str()] to look up mode by name.
2) use mpol_to_str() to format policy for shmem_show_mpol(). mpol_to_str()
expects a pointer to a struct mempolicy, so temporarily construct one.
This will be replaced with a reference to a struct mempolicy in the tmpfs
superblock in a subsequent patch.
NOTE 1: I changed mpol_to_str() to use a colon ':' rather than an equal
sign '=' as the nodemask delimiter to match mpol_parse_str() and the
tmpfs/shmem mpol mount option formatting that now uses mpol_to_str(). This
is a user visible change to numa_maps, but then the addition of the mode
flags already changed the display. It makes sense to me to have the mounts
and numa_maps display the policy in the same format. However, if anyone
objects strongly, I can pass the desired nodemask delimeter as an arg to
mpol_to_str().
Note 2: Like show_numa_map(), I don't check the return code from
mpol_to_str(). I do use a longer buffer than the one provided by
show_numa_map(), which seems to have sufficed so far.
Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Christoph Lameter <clameter@sgi.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 104 |
1 files changed, 102 insertions, 2 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 3c8ee31572ec..155bb284dbf1 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -88,6 +88,7 @@ #include <linux/rmap.h> #include <linux/security.h> #include <linux/syscalls.h> +#include <linux/ctype.h> #include <asm/tlbflush.h> #include <asm/uaccess.h> @@ -1945,6 +1946,10 @@ void numa_default_policy(void) } /* + * Parse and format mempolicy from/to strings + */ + +/* * "local" is pseudo-policy: MPOL_PREFERRED with MPOL_F_LOCAL flag * Used only for mpol_to_str() */ @@ -1952,12 +1957,107 @@ void numa_default_policy(void) static const char * const policy_types[] = { "default", "prefer", "bind", "interleave", "local" }; + +#ifdef CONFIG_TMPFS +/** + * mpol_parse_str - parse string to mempolicy + * @str: string containing mempolicy to parse + * @mode: pointer to returned policy mode + * @mode_flags: pointer to returned flags + * @policy_nodes: pointer to returned nodemask + * + * Format of input: + * <mode>[=<flags>][:<nodelist>] + * + * Currently only used for tmpfs/shmem mount options + */ +int mpol_parse_str(char *str, unsigned short *mode, unsigned short *mode_flags, + nodemask_t *policy_nodes) +{ + char *nodelist = strchr(str, ':'); + char *flags = strchr(str, '='); + int i; + int err = 1; + + if (nodelist) { + /* NUL-terminate mode or flags string */ + *nodelist++ = '\0'; + if (nodelist_parse(nodelist, *policy_nodes)) + goto out; + if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY])) + goto out; + } + if (flags) + *flags++ = '\0'; /* terminate mode string */ + + for (i = 0; i < MPOL_MAX; i++) { + if (!strcmp(str, policy_types[i])) { + *mode = i; + break; + } + } + if (i == MPOL_MAX) + goto out; + + switch (*mode) { + case MPOL_DEFAULT: + /* Don't allow a nodelist nor flags */ + if (!nodelist && !flags) + err = 0; + break; + case MPOL_PREFERRED: + /* Insist on a nodelist of one node only */ + if (nodelist) { + char *rest = nodelist; + while (isdigit(*rest)) + rest++; + if (!*rest) + err = 0; + } + break; + case MPOL_BIND: + /* Insist on a nodelist */ + if (nodelist) + err = 0; + break; + case MPOL_INTERLEAVE: + /* + * Default to online nodes with memory if no nodelist + */ + if (!nodelist) + *policy_nodes = node_states[N_HIGH_MEMORY]; + err = 0; + } + + *mode_flags = 0; + if (flags) { + /* + * Currently, we only support two mutually exclusive + * mode flags. + */ + if (!strcmp(flags, "static")) + *mode_flags |= MPOL_F_STATIC_NODES; + else if (!strcmp(flags, "relative")) + *mode_flags |= MPOL_F_RELATIVE_NODES; + else + err = 1; + } +out: + /* Restore string for error message */ + if (nodelist) + *--nodelist = ':'; + if (flags) + *--flags = '='; + return err; +} +#endif /* CONFIG_TMPFS */ + /* * Convert a mempolicy into a string. * Returns the number of characters in buffer (if positive) * or an error (negative) */ -static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) +int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) { char *p = buffer; int l; @@ -2022,7 +2122,7 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) if (!nodes_empty(nodes)) { if (buffer + maxlen < p + 2) return -ENOSPC; - *p++ = '='; + *p++ = ':'; p += nodelist_scnprintf(p, buffer + maxlen - p, nodes); } return p - buffer; |