aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mempolicy.c
diff options
context:
space:
mode:
authorLee Schermerhorn <lee.schermerhorn@hp.com>2008-04-28 05:13:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:24 -0400
commit095f1fc4ebf36c64fddf9b6db29b1ab5517378e6 (patch)
tree39aae9d5b05d8501d1794e92c6115331c0a40848 /mm/mempolicy.c
parent2291990ab36b4b2d8a81b1f92e7a046e51632a60 (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.c104
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 @@
88#include <linux/rmap.h> 88#include <linux/rmap.h>
89#include <linux/security.h> 89#include <linux/security.h>
90#include <linux/syscalls.h> 90#include <linux/syscalls.h>
91#include <linux/ctype.h>
91 92
92#include <asm/tlbflush.h> 93#include <asm/tlbflush.h>
93#include <asm/uaccess.h> 94#include <asm/uaccess.h>
@@ -1945,6 +1946,10 @@ void numa_default_policy(void)
1945} 1946}
1946 1947
1947/* 1948/*
1949 * Parse and format mempolicy from/to strings
1950 */
1951
1952/*
1948 * "local" is pseudo-policy: MPOL_PREFERRED with MPOL_F_LOCAL flag 1953 * "local" is pseudo-policy: MPOL_PREFERRED with MPOL_F_LOCAL flag
1949 * Used only for mpol_to_str() 1954 * Used only for mpol_to_str()
1950 */ 1955 */
@@ -1952,12 +1957,107 @@ void numa_default_policy(void)
1952static const char * const policy_types[] = 1957static const char * const policy_types[] =
1953 { "default", "prefer", "bind", "interleave", "local" }; 1958 { "default", "prefer", "bind", "interleave", "local" };
1954 1959
1960
1961#ifdef CONFIG_TMPFS
1962/**
1963 * mpol_parse_str - parse string to mempolicy
1964 * @str: string containing mempolicy to parse
1965 * @mode: pointer to returned policy mode
1966 * @mode_flags: pointer to returned flags
1967 * @policy_nodes: pointer to returned nodemask
1968 *
1969 * Format of input:
1970 * <mode>[=<flags>][:<nodelist>]
1971 *
1972 * Currently only used for tmpfs/shmem mount options
1973 */
1974int mpol_parse_str(char *str, unsigned short *mode, unsigned short *mode_flags,
1975 nodemask_t *policy_nodes)
1976{
1977 char *nodelist = strchr(str, ':');
1978 char *flags = strchr(str, '=');
1979 int i;
1980 int err = 1;
1981
1982 if (nodelist) {
1983 /* NUL-terminate mode or flags string */
1984 *nodelist++ = '\0';
1985 if (nodelist_parse(nodelist, *policy_nodes))
1986 goto out;
1987 if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY]))
1988 goto out;
1989 }
1990 if (flags)
1991 *flags++ = '\0'; /* terminate mode string */
1992
1993 for (i = 0; i < MPOL_MAX; i++) {
1994 if (!strcmp(str, policy_types[i])) {
1995 *mode = i;
1996 break;
1997 }
1998 }
1999 if (i == MPOL_MAX)
2000 goto out;
2001
2002 switch (*mode) {
2003 case MPOL_DEFAULT:
2004 /* Don't allow a nodelist nor flags */
2005 if (!nodelist && !flags)
2006 err = 0;
2007 break;
2008 case MPOL_PREFERRED:
2009 /* Insist on a nodelist of one node only */
2010 if (nodelist) {
2011 char *rest = nodelist;
2012 while (isdigit(*rest))
2013 rest++;
2014 if (!*rest)
2015 err = 0;
2016 }
2017 break;
2018 case MPOL_BIND:
2019 /* Insist on a nodelist */
2020 if (nodelist)
2021 err = 0;
2022 break;
2023 case MPOL_INTERLEAVE:
2024 /*
2025 * Default to online nodes with memory if no nodelist
2026 */
2027 if (!nodelist)
2028 *policy_nodes = node_states[N_HIGH_MEMORY];
2029 err = 0;
2030 }
2031
2032 *mode_flags = 0;
2033 if (flags) {
2034 /*
2035 * Currently, we only support two mutually exclusive
2036 * mode flags.
2037 */
2038 if (!strcmp(flags, "static"))
2039 *mode_flags |= MPOL_F_STATIC_NODES;
2040 else if (!strcmp(flags, "relative"))
2041 *mode_flags |= MPOL_F_RELATIVE_NODES;
2042 else
2043 err = 1;
2044 }
2045out:
2046 /* Restore string for error message */
2047 if (nodelist)
2048 *--nodelist = ':';
2049 if (flags)
2050 *--flags = '=';
2051 return err;
2052}
2053#endif /* CONFIG_TMPFS */
2054
1955/* 2055/*
1956 * Convert a mempolicy into a string. 2056 * Convert a mempolicy into a string.
1957 * Returns the number of characters in buffer (if positive) 2057 * Returns the number of characters in buffer (if positive)
1958 * or an error (negative) 2058 * or an error (negative)
1959 */ 2059 */
1960static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) 2060int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
1961{ 2061{
1962 char *p = buffer; 2062 char *p = buffer;
1963 int l; 2063 int l;
@@ -2022,7 +2122,7 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
2022 if (!nodes_empty(nodes)) { 2122 if (!nodes_empty(nodes)) {
2023 if (buffer + maxlen < p + 2) 2123 if (buffer + maxlen < p + 2)
2024 return -ENOSPC; 2124 return -ENOSPC;
2025 *p++ = '='; 2125 *p++ = ':';
2026 p += nodelist_scnprintf(p, buffer + maxlen - p, nodes); 2126 p += nodelist_scnprintf(p, buffer + maxlen - p, nodes);
2027 } 2127 }
2028 return p - buffer; 2128 return p - buffer;