aboutsummaryrefslogtreecommitdiffstats
path: root/mm/shmem.c
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2008-04-28 05:12:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:19 -0400
commit028fec414d803117eb4b2ed12acb4dd5da65b32d (patch)
tree427f37ea0331369c1babc55c424c4fd2ac3b39f5 /mm/shmem.c
parenta3b51e0142d1be156ac697eaadadd6cfbb7ba32b (diff)
mempolicy: support optional mode flags
With the evolution of mempolicies, it is necessary to support mempolicy mode flags that specify how the policy shall behave in certain circumstances. The most immediate need for mode flag support is to suppress remapping the nodemask of a policy at the time of rebind. Both the mempolicy mode and flags are passed by the user in the 'int policy' formal of either the set_mempolicy() or mbind() syscall. A new constant, MPOL_MODE_FLAGS, represents the union of legal optional flags that may be passed as part of this int. Mempolicies that include illegal flags as part of their policy are rejected as invalid. An additional member to struct mempolicy is added to support the mode flags: struct mempolicy { ... unsigned short policy; unsigned short flags; } The splitting of the 'int' actual passed by the user is done in sys_set_mempolicy() and sys_mbind() for their respective syscalls. This is done by intersecting the actual with MPOL_MODE_FLAGS, rejecting the syscall of there are additional flags, and storing it in the new 'flags' member of struct mempolicy. The intersection of the actual with ~MPOL_MODE_FLAGS is stored in the 'policy' member of the struct and all current users of pol->policy remain unchanged. The union of the policy mode and optional mode flags is passed back to the user in get_mempolicy(). This combination of mode and flags within the same actual does not break userspace code that relies on get_mempolicy(&policy, ...) and either switch (policy) { case MPOL_BIND: ... case MPOL_INTERLEAVE: ... }; statements or if (policy == MPOL_INTERLEAVE) { ... } statements. Such applications would need to use optional mode flags when calling set_mempolicy() or mbind() for these previously implemented statements to stop working. If an application does start using optional mode flags, it will need to mask the optional flags off the policy in switch and conditional statements that only test mode. An additional member is also added to struct shmem_sb_info to store the optional mode flags. [hugh@veritas.com: shmem mpol: fix build warning] Cc: Paul Jackson <pj@sgi.com> Cc: Christoph Lameter <clameter@sgi.com> Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com> Cc: Andi Kleen <ak@suse.de> Signed-off-by: David Rientjes <rientjes@google.com> Signed-off-by: Hugh Dickins <hugh@veritas.com> 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.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index d8ef7ba831a5..1ccf794fbe61 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1080,9 +1080,10 @@ redirty:
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 int shmem_parse_mpol(char *value, unsigned short *policy,
1083 nodemask_t *policy_nodes) 1083 unsigned short *mode_flags, nodemask_t *policy_nodes)
1084{ 1084{
1085 char *nodelist = strchr(value, ':'); 1085 char *nodelist = strchr(value, ':');
1086 char *flags = strchr(value, '=');
1086 int err = 1; 1087 int err = 1;
1087 1088
1088 if (nodelist) { 1089 if (nodelist) {
@@ -1093,6 +1094,8 @@ static int shmem_parse_mpol(char *value, unsigned short *policy,
1093 if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY])) 1094 if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY]))
1094 goto out; 1095 goto out;
1095 } 1096 }
1097 if (flags)
1098 *flags++ = '\0';
1096 if (!strcmp(value, "default")) { 1099 if (!strcmp(value, "default")) {
1097 *policy = MPOL_DEFAULT; 1100 *policy = MPOL_DEFAULT;
1098 /* Don't allow a nodelist */ 1101 /* Don't allow a nodelist */
@@ -1122,6 +1125,8 @@ static int shmem_parse_mpol(char *value, unsigned short *policy,
1122 *policy_nodes = node_states[N_HIGH_MEMORY]; 1125 *policy_nodes = node_states[N_HIGH_MEMORY];
1123 err = 0; 1126 err = 0;
1124 } 1127 }
1128 if (flags) {
1129 }
1125out: 1130out:
1126 /* Restore string for error message */ 1131 /* Restore string for error message */
1127 if (nodelist) 1132 if (nodelist)
@@ -1130,7 +1135,7 @@ out:
1130} 1135}
1131 1136
1132static void shmem_show_mpol(struct seq_file *seq, unsigned short policy, 1137static void shmem_show_mpol(struct seq_file *seq, unsigned short policy,
1133 const nodemask_t policy_nodes) 1138 unsigned short flags, const nodemask_t policy_nodes)
1134{ 1139{
1135 char *policy_string; 1140 char *policy_string;
1136 1141
@@ -1199,13 +1204,13 @@ static struct page *shmem_alloc_page(gfp_t gfp,
1199#else /* !CONFIG_NUMA */ 1204#else /* !CONFIG_NUMA */
1200#ifdef CONFIG_TMPFS 1205#ifdef CONFIG_TMPFS
1201static inline int shmem_parse_mpol(char *value, unsigned short *policy, 1206static inline int shmem_parse_mpol(char *value, unsigned short *policy,
1202 nodemask_t *policy_nodes) 1207 unsigned short *mode_flags, nodemask_t *policy_nodes)
1203{ 1208{
1204 return 1; 1209 return 1;
1205} 1210}
1206 1211
1207static inline void shmem_show_mpol(struct seq_file *seq, unsigned short policy, 1212static inline void shmem_show_mpol(struct seq_file *seq, unsigned short policy,
1208 const nodemask_t policy_nodes) 1213 unsigned short flags, const nodemask_t policy_nodes)
1209{ 1214{
1210} 1215}
1211#endif /* CONFIG_TMPFS */ 1216#endif /* CONFIG_TMPFS */
@@ -1578,7 +1583,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
1578 inode->i_op = &shmem_inode_operations; 1583 inode->i_op = &shmem_inode_operations;
1579 inode->i_fop = &shmem_file_operations; 1584 inode->i_fop = &shmem_file_operations;
1580 mpol_shared_policy_init(&info->policy, sbinfo->policy, 1585 mpol_shared_policy_init(&info->policy, sbinfo->policy,
1581 &sbinfo->policy_nodes); 1586 sbinfo->flags, &sbinfo->policy_nodes);
1582 break; 1587 break;
1583 case S_IFDIR: 1588 case S_IFDIR:
1584 inc_nlink(inode); 1589 inc_nlink(inode);
@@ -1592,7 +1597,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
1592 * Must not load anything in the rbtree, 1597 * Must not load anything in the rbtree,
1593 * mpol_free_shared_policy will not be called. 1598 * mpol_free_shared_policy will not be called.
1594 */ 1599 */
1595 mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, 1600 mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, 0,
1596 NULL); 1601 NULL);
1597 break; 1602 break;
1598 } 1603 }
@@ -2209,7 +2214,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
2209 goto bad_val; 2214 goto bad_val;
2210 } else if (!strcmp(this_char,"mpol")) { 2215 } else if (!strcmp(this_char,"mpol")) {
2211 if (shmem_parse_mpol(value, &sbinfo->policy, 2216 if (shmem_parse_mpol(value, &sbinfo->policy,
2212 &sbinfo->policy_nodes)) 2217 &sbinfo->flags, &sbinfo->policy_nodes))
2213 goto bad_val; 2218 goto bad_val;
2214 } else { 2219 } else {
2215 printk(KERN_ERR "tmpfs: Bad mount option %s\n", 2220 printk(KERN_ERR "tmpfs: Bad mount option %s\n",
@@ -2261,6 +2266,7 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
2261 sbinfo->max_inodes = config.max_inodes; 2266 sbinfo->max_inodes = config.max_inodes;
2262 sbinfo->free_inodes = config.max_inodes - inodes; 2267 sbinfo->free_inodes = config.max_inodes - inodes;
2263 sbinfo->policy = config.policy; 2268 sbinfo->policy = config.policy;
2269 sbinfo->flags = config.flags;
2264 sbinfo->policy_nodes = config.policy_nodes; 2270 sbinfo->policy_nodes = config.policy_nodes;
2265out: 2271out:
2266 spin_unlock(&sbinfo->stat_lock); 2272 spin_unlock(&sbinfo->stat_lock);
@@ -2282,7 +2288,8 @@ static int shmem_show_options(struct seq_file *seq, struct vfsmount *vfs)
2282 seq_printf(seq, ",uid=%u", sbinfo->uid); 2288 seq_printf(seq, ",uid=%u", sbinfo->uid);
2283 if (sbinfo->gid != 0) 2289 if (sbinfo->gid != 0)
2284 seq_printf(seq, ",gid=%u", sbinfo->gid); 2290 seq_printf(seq, ",gid=%u", sbinfo->gid);
2285 shmem_show_mpol(seq, sbinfo->policy, sbinfo->policy_nodes); 2291 shmem_show_mpol(seq, sbinfo->policy, sbinfo->flags,
2292 sbinfo->policy_nodes);
2286 return 0; 2293 return 0;
2287} 2294}
2288#endif /* CONFIG_TMPFS */ 2295#endif /* CONFIG_TMPFS */
@@ -2313,6 +2320,7 @@ static int shmem_fill_super(struct super_block *sb,
2313 sbinfo->uid = current->fsuid; 2320 sbinfo->uid = current->fsuid;
2314 sbinfo->gid = current->fsgid; 2321 sbinfo->gid = current->fsgid;
2315 sbinfo->policy = MPOL_DEFAULT; 2322 sbinfo->policy = MPOL_DEFAULT;
2323 sbinfo->flags = 0;
2316 sbinfo->policy_nodes = node_states[N_HIGH_MEMORY]; 2324 sbinfo->policy_nodes = node_states[N_HIGH_MEMORY];
2317 sb->s_fs_info = sbinfo; 2325 sb->s_fs_info = sbinfo;
2318 2326