diff options
author | Lee Schermerhorn <lee.schermerhorn@hp.com> | 2008-04-28 05:13:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 11:58:24 -0400 |
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 @@ | |||
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) | |||
1952 | static const char * const policy_types[] = | 1957 | static 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 | */ | ||
1974 | int 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 | } | ||
2045 | out: | ||
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 | */ |
1960 | static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) | 2060 | int 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; |