aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/linux/mempolicy.h21
-rw-r--r--mm/mempolicy.c104
-rw-r--r--mm/shmem.c118
3 files changed, 136 insertions, 107 deletions
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index b0fab9e80655..dcc17378c952 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -214,6 +214,13 @@ static inline void check_highest_zone(enum zone_type k)
214int do_migrate_pages(struct mm_struct *mm, 214int do_migrate_pages(struct mm_struct *mm,
215 const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags); 215 const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags);
216 216
217
218#ifdef CONFIG_TMPFS
219extern int mpol_parse_str(char *str, unsigned short *mode,
220 unsigned short *mode_flags, nodemask_t *policy_nodes);
221
222extern int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol);
223#endif
217#else 224#else
218 225
219struct mempolicy {}; 226struct mempolicy {};
@@ -313,6 +320,20 @@ static inline int do_migrate_pages(struct mm_struct *mm,
313static inline void check_highest_zone(int k) 320static inline void check_highest_zone(int k)
314{ 321{
315} 322}
323
324#ifdef CONFIG_TMPFS
325static inline int mpol_parse_str(char *value, unsigned short *policy,
326 unsigned short flags, nodemask_t *policy_nodes)
327{
328 return 1;
329}
330
331static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
332{
333 return 0;
334}
335#endif
336
316#endif /* CONFIG_NUMA */ 337#endif /* CONFIG_NUMA */
317#endif /* __KERNEL__ */ 338#endif /* __KERNEL__ */
318 339
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;
diff --git a/mm/shmem.c b/mm/shmem.c
index 0b591c669b2d..3c620dc10135 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1079,108 +1079,22 @@ redirty:
1079 1079
1080#ifdef CONFIG_NUMA 1080#ifdef CONFIG_NUMA
1081#ifdef CONFIG_TMPFS 1081#ifdef CONFIG_TMPFS
1082static int shmem_parse_mpol(char *value, unsigned short *policy, 1082static void shmem_show_mpol(struct seq_file *seq, unsigned short mode,
1083 unsigned short *mode_flags, nodemask_t *policy_nodes)
1084{
1085 char *nodelist = strchr(value, ':');
1086 char *flags = strchr(value, '=');
1087 int err = 1;
1088
1089 if (nodelist) {
1090 /* NUL-terminate policy string */
1091 *nodelist++ = '\0';
1092 if (nodelist_parse(nodelist, *policy_nodes))
1093 goto out;
1094 if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY]))
1095 goto out;
1096 }
1097 if (flags)
1098 *flags++ = '\0';
1099 if (!strcmp(value, "default")) {
1100 *policy = MPOL_DEFAULT;
1101 /* Don't allow a nodelist */
1102 if (!nodelist)
1103 err = 0;
1104 } else if (!strcmp(value, "prefer")) {
1105 *policy = MPOL_PREFERRED;
1106 /* Insist on a nodelist of one node only */
1107 if (nodelist) {
1108 char *rest = nodelist;
1109 while (isdigit(*rest))
1110 rest++;
1111 if (!*rest)
1112 err = 0;
1113 }
1114 } else if (!strcmp(value, "bind")) {
1115 *policy = MPOL_BIND;
1116 /* Insist on a nodelist */
1117 if (nodelist)
1118 err = 0;
1119 } else if (!strcmp(value, "interleave")) {
1120 *policy = MPOL_INTERLEAVE;
1121 /*
1122 * Default to online nodes with memory if no nodelist
1123 */
1124 if (!nodelist)
1125 *policy_nodes = node_states[N_HIGH_MEMORY];
1126 err = 0;
1127 }
1128
1129 *mode_flags = 0;
1130 if (flags) {
1131 /*
1132 * Currently, we only support two mutually exclusive
1133 * mode flags.
1134 */
1135 if (!strcmp(flags, "static"))
1136 *mode_flags |= MPOL_F_STATIC_NODES;
1137 else if (!strcmp(flags, "relative"))
1138 *mode_flags |= MPOL_F_RELATIVE_NODES;
1139 else
1140 err = 1; /* unrecognized flag */
1141 }
1142out:
1143 /* Restore string for error message */
1144 if (nodelist)
1145 *--nodelist = ':';
1146 if (flags)
1147 *--flags = '=';
1148 return err;
1149}
1150
1151static void shmem_show_mpol(struct seq_file *seq, unsigned short policy,
1152 unsigned short flags, const nodemask_t policy_nodes) 1083 unsigned short flags, const nodemask_t policy_nodes)
1153{ 1084{
1154 char *policy_string; 1085 struct mempolicy temp;
1155 1086 char buffer[64];
1156 switch (policy) {
1157 case MPOL_PREFERRED:
1158 policy_string = "prefer";
1159 break;
1160 case MPOL_BIND:
1161 policy_string = "bind";
1162 break;
1163 case MPOL_INTERLEAVE:
1164 policy_string = "interleave";
1165 break;
1166 default:
1167 /* MPOL_DEFAULT */
1168 return;
1169 }
1170 1087
1171 seq_printf(seq, ",mpol=%s", policy_string); 1088 if (mode == MPOL_DEFAULT)
1089 return; /* show nothing */
1172 1090
1173 if (policy != MPOL_INTERLEAVE || 1091 temp.mode = mode;
1174 !nodes_equal(policy_nodes, node_states[N_HIGH_MEMORY])) { 1092 temp.flags = flags;
1175 char buffer[64]; 1093 temp.v.nodes = policy_nodes;
1176 int len;
1177 1094
1178 len = nodelist_scnprintf(buffer, sizeof(buffer), policy_nodes); 1095 mpol_to_str(buffer, sizeof(buffer), &temp);
1179 if (len < sizeof(buffer)) 1096
1180 seq_printf(seq, ":%s", buffer); 1097 seq_printf(seq, ",mpol=%s", buffer);
1181 else
1182 seq_printf(seq, ":?");
1183 }
1184} 1098}
1185#endif /* CONFIG_TMPFS */ 1099#endif /* CONFIG_TMPFS */
1186 1100
@@ -1221,12 +1135,6 @@ static struct page *shmem_alloc_page(gfp_t gfp,
1221} 1135}
1222#else /* !CONFIG_NUMA */ 1136#else /* !CONFIG_NUMA */
1223#ifdef CONFIG_TMPFS 1137#ifdef CONFIG_TMPFS
1224static inline int shmem_parse_mpol(char *value, unsigned short *policy,
1225 unsigned short *mode_flags, nodemask_t *policy_nodes)
1226{
1227 return 1;
1228}
1229
1230static inline void shmem_show_mpol(struct seq_file *seq, unsigned short policy, 1138static inline void shmem_show_mpol(struct seq_file *seq, unsigned short policy,
1231 unsigned short flags, const nodemask_t policy_nodes) 1139 unsigned short flags, const nodemask_t policy_nodes)
1232{ 1140{
@@ -2231,8 +2139,8 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
2231 if (*rest) 2139 if (*rest)
2232 goto bad_val; 2140 goto bad_val;
2233 } else if (!strcmp(this_char,"mpol")) { 2141 } else if (!strcmp(this_char,"mpol")) {
2234 if (shmem_parse_mpol(value, &sbinfo->policy, 2142 if (mpol_parse_str(value, &sbinfo->policy,
2235 &sbinfo->flags, &sbinfo->policy_nodes)) 2143 &sbinfo->flags, &sbinfo->policy_nodes))
2236 goto bad_val; 2144 goto bad_val;
2237 } else { 2145 } else {
2238 printk(KERN_ERR "tmpfs: Bad mount option %s\n", 2146 printk(KERN_ERR "tmpfs: Bad mount option %s\n",