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) | |
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; | 
