aboutsummaryrefslogtreecommitdiffstats
path: root/mm/shmem.c
diff options
context:
space:
mode:
authorLee Schermerhorn <lee.schermerhorn@hp.com>2008-04-28 05:13:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:25 -0400
commit71fe804b6d56d6a7aed680e096901434cef6a2c3 (patch)
tree3dd437e09fe6ee57644c72c79e08c562d4bb6389 /mm/shmem.c
parent3f226aa1cbc006f9d90f22084f519ad2a1286cd8 (diff)
mempolicy: use struct mempolicy pointer in shmem_sb_info
This patch replaces the mempolicy mode, mode_flags, and nodemask in the shmem_sb_info struct with a struct mempolicy pointer, initialized to NULL. This removes dependency on the details of mempolicy from shmem.c and hugetlbfs inode.c and simplifies the interfaces. mpol_parse_str() in mempolicy.c is changed to return, via a pointer to a pointer arg, a struct mempolicy pointer on success. For MPOL_DEFAULT, the returned pointer is NULL. Further, mpol_parse_str() now takes a 'no_context' argument that causes the input nodemask to be stored in the w.user_nodemask of the created mempolicy for use when the mempolicy is installed in a tmpfs inode shared policy tree. At that time, any cpuset contextualization is applied to the original input nodemask. This preserves the previous behavior where the input nodemask was stored in the superblock. We can think of the returned mempolicy as "context free". Because mpol_parse_str() is now calling mpol_new(), we can remove from mpol_to_str() the semantic checks that mpol_new() already performs. Add 'no_context' parameter to mpol_to_str() to specify that it should format the nodemask in w.user_nodemask for 'bind' and 'interleave' policies. Change mpol_shared_policy_init() to take a pointer to a "context free" struct mempolicy and to create a new, "contextualized" mempolicy using the mode, mode_flags and user_nodemask from the input mempolicy. Note: we know that the mempolicy passed to mpol_to_str() or mpol_shared_policy_init() from a tmpfs superblock is "context free". This is currently the only instance thereof. However, if we found more uses for this concept, and introduced any ambiguity as to whether a mempolicy was context free or not, we could add another internal mode flag to identify context free mempolicies. Then, we could remove the 'no_context' argument from mpol_to_str(). Added shmem_get_sbmpol() to return a reference counted superblock mempolicy, if one exists, to pass to mpol_shared_policy_init(). We must add the reference under the sb stat_lock to prevent races with replacement of the mpol by remount. This reference is removed in mpol_shared_policy_init(). [akpm@linux-foundation.org: build fix] [akpm@linux-foundation.org: another build fix] [akpm@linux-foundation.org: yet another build fix] 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/shmem.c')
-rw-r--r--mm/shmem.c57
1 files changed, 32 insertions, 25 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index 3c620dc10135..e6d9298aa22a 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1079,23 +1079,29 @@ redirty:
1079 1079
1080#ifdef CONFIG_NUMA 1080#ifdef CONFIG_NUMA
1081#ifdef CONFIG_TMPFS 1081#ifdef CONFIG_TMPFS
1082static void shmem_show_mpol(struct seq_file *seq, unsigned short mode, 1082static void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol)
1083 unsigned short flags, const nodemask_t policy_nodes)
1084{ 1083{
1085 struct mempolicy temp;
1086 char buffer[64]; 1084 char buffer[64];
1087 1085
1088 if (mode == MPOL_DEFAULT) 1086 if (!mpol || mpol->mode == MPOL_DEFAULT)
1089 return; /* show nothing */ 1087 return; /* show nothing */
1090 1088
1091 temp.mode = mode; 1089 mpol_to_str(buffer, sizeof(buffer), mpol, 1);
1092 temp.flags = flags;
1093 temp.v.nodes = policy_nodes;
1094
1095 mpol_to_str(buffer, sizeof(buffer), &temp);
1096 1090
1097 seq_printf(seq, ",mpol=%s", buffer); 1091 seq_printf(seq, ",mpol=%s", buffer);
1098} 1092}
1093
1094static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
1095{
1096 struct mempolicy *mpol = NULL;
1097 if (sbinfo->mpol) {
1098 spin_lock(&sbinfo->stat_lock); /* prevent replace/use races */
1099 mpol = sbinfo->mpol;
1100 mpol_get(mpol);
1101 spin_unlock(&sbinfo->stat_lock);
1102 }
1103 return mpol;
1104}
1099#endif /* CONFIG_TMPFS */ 1105#endif /* CONFIG_TMPFS */
1100 1106
1101static struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp, 1107static struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp,
@@ -1135,8 +1141,7 @@ static struct page *shmem_alloc_page(gfp_t gfp,
1135} 1141}
1136#else /* !CONFIG_NUMA */ 1142#else /* !CONFIG_NUMA */
1137#ifdef CONFIG_TMPFS 1143#ifdef CONFIG_TMPFS
1138static inline void shmem_show_mpol(struct seq_file *seq, unsigned short policy, 1144static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *p)
1139 unsigned short flags, const nodemask_t policy_nodes)
1140{ 1145{
1141} 1146}
1142#endif /* CONFIG_TMPFS */ 1147#endif /* CONFIG_TMPFS */
@@ -1154,6 +1159,13 @@ static inline struct page *shmem_alloc_page(gfp_t gfp,
1154} 1159}
1155#endif /* CONFIG_NUMA */ 1160#endif /* CONFIG_NUMA */
1156 1161
1162#if !defined(CONFIG_NUMA) || !defined(CONFIG_TMPFS)
1163static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
1164{
1165 return NULL;
1166}
1167#endif
1168
1157/* 1169/*
1158 * shmem_getpage - either get the page from swap or allocate a new one 1170 * shmem_getpage - either get the page from swap or allocate a new one
1159 * 1171 *
@@ -1508,8 +1520,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
1508 case S_IFREG: 1520 case S_IFREG:
1509 inode->i_op = &shmem_inode_operations; 1521 inode->i_op = &shmem_inode_operations;
1510 inode->i_fop = &shmem_file_operations; 1522 inode->i_fop = &shmem_file_operations;
1511 mpol_shared_policy_init(&info->policy, sbinfo->policy, 1523 mpol_shared_policy_init(&info->policy,
1512 sbinfo->flags, &sbinfo->policy_nodes); 1524 shmem_get_sbmpol(sbinfo));
1513 break; 1525 break;
1514 case S_IFDIR: 1526 case S_IFDIR:
1515 inc_nlink(inode); 1527 inc_nlink(inode);
@@ -1523,8 +1535,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
1523 * Must not load anything in the rbtree, 1535 * Must not load anything in the rbtree,
1524 * mpol_free_shared_policy will not be called. 1536 * mpol_free_shared_policy will not be called.
1525 */ 1537 */
1526 mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, 0, 1538 mpol_shared_policy_init(&info->policy, NULL);
1527 NULL);
1528 break; 1539 break;
1529 } 1540 }
1530 } else 1541 } else
@@ -2139,8 +2150,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
2139 if (*rest) 2150 if (*rest)
2140 goto bad_val; 2151 goto bad_val;
2141 } else if (!strcmp(this_char,"mpol")) { 2152 } else if (!strcmp(this_char,"mpol")) {
2142 if (mpol_parse_str(value, &sbinfo->policy, 2153 if (mpol_parse_str(value, &sbinfo->mpol, 1))
2143 &sbinfo->flags, &sbinfo->policy_nodes))
2144 goto bad_val; 2154 goto bad_val;
2145 } else { 2155 } else {
2146 printk(KERN_ERR "tmpfs: Bad mount option %s\n", 2156 printk(KERN_ERR "tmpfs: Bad mount option %s\n",
@@ -2191,9 +2201,9 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
2191 sbinfo->free_blocks = config.max_blocks - blocks; 2201 sbinfo->free_blocks = config.max_blocks - blocks;
2192 sbinfo->max_inodes = config.max_inodes; 2202 sbinfo->max_inodes = config.max_inodes;
2193 sbinfo->free_inodes = config.max_inodes - inodes; 2203 sbinfo->free_inodes = config.max_inodes - inodes;
2194 sbinfo->policy = config.policy; 2204
2195 sbinfo->flags = config.flags; 2205 mpol_put(sbinfo->mpol);
2196 sbinfo->policy_nodes = config.policy_nodes; 2206 sbinfo->mpol = config.mpol; /* transfers initial ref */
2197out: 2207out:
2198 spin_unlock(&sbinfo->stat_lock); 2208 spin_unlock(&sbinfo->stat_lock);
2199 return error; 2209 return error;
@@ -2214,8 +2224,7 @@ static int shmem_show_options(struct seq_file *seq, struct vfsmount *vfs)
2214 seq_printf(seq, ",uid=%u", sbinfo->uid); 2224 seq_printf(seq, ",uid=%u", sbinfo->uid);
2215 if (sbinfo->gid != 0) 2225 if (sbinfo->gid != 0)
2216 seq_printf(seq, ",gid=%u", sbinfo->gid); 2226 seq_printf(seq, ",gid=%u", sbinfo->gid);
2217 shmem_show_mpol(seq, sbinfo->policy, sbinfo->flags, 2227 shmem_show_mpol(seq, sbinfo->mpol);
2218 sbinfo->policy_nodes);
2219 return 0; 2228 return 0;
2220} 2229}
2221#endif /* CONFIG_TMPFS */ 2230#endif /* CONFIG_TMPFS */
@@ -2245,9 +2254,7 @@ static int shmem_fill_super(struct super_block *sb,
2245 sbinfo->mode = S_IRWXUGO | S_ISVTX; 2254 sbinfo->mode = S_IRWXUGO | S_ISVTX;
2246 sbinfo->uid = current->fsuid; 2255 sbinfo->uid = current->fsuid;
2247 sbinfo->gid = current->fsgid; 2256 sbinfo->gid = current->fsgid;
2248 sbinfo->policy = MPOL_DEFAULT; 2257 sbinfo->mpol = NULL;
2249 sbinfo->flags = 0;
2250 sbinfo->policy_nodes = node_states[N_HIGH_MEMORY];
2251 sb->s_fs_info = sbinfo; 2258 sb->s_fs_info = sbinfo;
2252 2259
2253#ifdef CONFIG_TMPFS 2260#ifdef CONFIG_TMPFS