diff options
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 144 |
1 files changed, 43 insertions, 101 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index f514dd392cd9..e6d9298aa22a 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1079,104 +1079,47 @@ redirty: | |||
1079 | 1079 | ||
1080 | #ifdef CONFIG_NUMA | 1080 | #ifdef CONFIG_NUMA |
1081 | #ifdef CONFIG_TMPFS | 1081 | #ifdef CONFIG_TMPFS |
1082 | static int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_nodes) | 1082 | static void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol) |
1083 | { | 1083 | { |
1084 | char *nodelist = strchr(value, ':'); | 1084 | char buffer[64]; |
1085 | int err = 1; | ||
1086 | 1085 | ||
1087 | if (nodelist) { | 1086 | if (!mpol || mpol->mode == MPOL_DEFAULT) |
1088 | /* NUL-terminate policy string */ | 1087 | return; /* show nothing */ |
1089 | *nodelist++ = '\0'; | ||
1090 | if (nodelist_parse(nodelist, *policy_nodes)) | ||
1091 | goto out; | ||
1092 | if (!nodes_subset(*policy_nodes, node_states[N_HIGH_MEMORY])) | ||
1093 | goto out; | ||
1094 | } | ||
1095 | if (!strcmp(value, "default")) { | ||
1096 | *policy = MPOL_DEFAULT; | ||
1097 | /* Don't allow a nodelist */ | ||
1098 | if (!nodelist) | ||
1099 | err = 0; | ||
1100 | } else if (!strcmp(value, "prefer")) { | ||
1101 | *policy = MPOL_PREFERRED; | ||
1102 | /* Insist on a nodelist of one node only */ | ||
1103 | if (nodelist) { | ||
1104 | char *rest = nodelist; | ||
1105 | while (isdigit(*rest)) | ||
1106 | rest++; | ||
1107 | if (!*rest) | ||
1108 | err = 0; | ||
1109 | } | ||
1110 | } else if (!strcmp(value, "bind")) { | ||
1111 | *policy = MPOL_BIND; | ||
1112 | /* Insist on a nodelist */ | ||
1113 | if (nodelist) | ||
1114 | err = 0; | ||
1115 | } else if (!strcmp(value, "interleave")) { | ||
1116 | *policy = MPOL_INTERLEAVE; | ||
1117 | /* | ||
1118 | * Default to online nodes with memory if no nodelist | ||
1119 | */ | ||
1120 | if (!nodelist) | ||
1121 | *policy_nodes = node_states[N_HIGH_MEMORY]; | ||
1122 | err = 0; | ||
1123 | } | ||
1124 | out: | ||
1125 | /* Restore string for error message */ | ||
1126 | if (nodelist) | ||
1127 | *--nodelist = ':'; | ||
1128 | return err; | ||
1129 | } | ||
1130 | |||
1131 | static void shmem_show_mpol(struct seq_file *seq, int policy, | ||
1132 | const nodemask_t policy_nodes) | ||
1133 | { | ||
1134 | char *policy_string; | ||
1135 | 1088 | ||
1136 | switch (policy) { | 1089 | mpol_to_str(buffer, sizeof(buffer), mpol, 1); |
1137 | case MPOL_PREFERRED: | ||
1138 | policy_string = "prefer"; | ||
1139 | break; | ||
1140 | case MPOL_BIND: | ||
1141 | policy_string = "bind"; | ||
1142 | break; | ||
1143 | case MPOL_INTERLEAVE: | ||
1144 | policy_string = "interleave"; | ||
1145 | break; | ||
1146 | default: | ||
1147 | /* MPOL_DEFAULT */ | ||
1148 | return; | ||
1149 | } | ||
1150 | 1090 | ||
1151 | seq_printf(seq, ",mpol=%s", policy_string); | 1091 | seq_printf(seq, ",mpol=%s", buffer); |
1152 | 1092 | } | |
1153 | if (policy != MPOL_INTERLEAVE || | ||
1154 | !nodes_equal(policy_nodes, node_states[N_HIGH_MEMORY])) { | ||
1155 | char buffer[64]; | ||
1156 | int len; | ||
1157 | 1093 | ||
1158 | len = nodelist_scnprintf(buffer, sizeof(buffer), policy_nodes); | 1094 | static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo) |
1159 | if (len < sizeof(buffer)) | 1095 | { |
1160 | seq_printf(seq, ":%s", buffer); | 1096 | struct mempolicy *mpol = NULL; |
1161 | else | 1097 | if (sbinfo->mpol) { |
1162 | seq_printf(seq, ":?"); | 1098 | spin_lock(&sbinfo->stat_lock); /* prevent replace/use races */ |
1099 | mpol = sbinfo->mpol; | ||
1100 | mpol_get(mpol); | ||
1101 | spin_unlock(&sbinfo->stat_lock); | ||
1163 | } | 1102 | } |
1103 | return mpol; | ||
1164 | } | 1104 | } |
1165 | #endif /* CONFIG_TMPFS */ | 1105 | #endif /* CONFIG_TMPFS */ |
1166 | 1106 | ||
1167 | static struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp, | 1107 | static struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp, |
1168 | struct shmem_inode_info *info, unsigned long idx) | 1108 | struct shmem_inode_info *info, unsigned long idx) |
1169 | { | 1109 | { |
1110 | struct mempolicy mpol, *spol; | ||
1170 | struct vm_area_struct pvma; | 1111 | struct vm_area_struct pvma; |
1171 | struct page *page; | 1112 | struct page *page; |
1172 | 1113 | ||
1114 | spol = mpol_cond_copy(&mpol, | ||
1115 | mpol_shared_policy_lookup(&info->policy, idx)); | ||
1116 | |||
1173 | /* Create a pseudo vma that just contains the policy */ | 1117 | /* Create a pseudo vma that just contains the policy */ |
1174 | pvma.vm_start = 0; | 1118 | pvma.vm_start = 0; |
1175 | pvma.vm_pgoff = idx; | 1119 | pvma.vm_pgoff = idx; |
1176 | pvma.vm_ops = NULL; | 1120 | pvma.vm_ops = NULL; |
1177 | pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx); | 1121 | pvma.vm_policy = spol; |
1178 | page = swapin_readahead(entry, gfp, &pvma, 0); | 1122 | page = swapin_readahead(entry, gfp, &pvma, 0); |
1179 | mpol_free(pvma.vm_policy); | ||
1180 | return page; | 1123 | return page; |
1181 | } | 1124 | } |
1182 | 1125 | ||
@@ -1184,27 +1127,21 @@ static struct page *shmem_alloc_page(gfp_t gfp, | |||
1184 | struct shmem_inode_info *info, unsigned long idx) | 1127 | struct shmem_inode_info *info, unsigned long idx) |
1185 | { | 1128 | { |
1186 | struct vm_area_struct pvma; | 1129 | struct vm_area_struct pvma; |
1187 | struct page *page; | ||
1188 | 1130 | ||
1189 | /* Create a pseudo vma that just contains the policy */ | 1131 | /* Create a pseudo vma that just contains the policy */ |
1190 | pvma.vm_start = 0; | 1132 | pvma.vm_start = 0; |
1191 | pvma.vm_pgoff = idx; | 1133 | pvma.vm_pgoff = idx; |
1192 | pvma.vm_ops = NULL; | 1134 | pvma.vm_ops = NULL; |
1193 | pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx); | 1135 | pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx); |
1194 | page = alloc_page_vma(gfp, &pvma, 0); | 1136 | |
1195 | mpol_free(pvma.vm_policy); | 1137 | /* |
1196 | return page; | 1138 | * alloc_page_vma() will drop the shared policy reference |
1139 | */ | ||
1140 | return alloc_page_vma(gfp, &pvma, 0); | ||
1197 | } | 1141 | } |
1198 | #else /* !CONFIG_NUMA */ | 1142 | #else /* !CONFIG_NUMA */ |
1199 | #ifdef CONFIG_TMPFS | 1143 | #ifdef CONFIG_TMPFS |
1200 | static inline int shmem_parse_mpol(char *value, int *policy, | 1144 | static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *p) |
1201 | nodemask_t *policy_nodes) | ||
1202 | { | ||
1203 | return 1; | ||
1204 | } | ||
1205 | |||
1206 | static inline void shmem_show_mpol(struct seq_file *seq, int policy, | ||
1207 | const nodemask_t policy_nodes) | ||
1208 | { | 1145 | { |
1209 | } | 1146 | } |
1210 | #endif /* CONFIG_TMPFS */ | 1147 | #endif /* CONFIG_TMPFS */ |
@@ -1222,6 +1159,13 @@ static inline struct page *shmem_alloc_page(gfp_t gfp, | |||
1222 | } | 1159 | } |
1223 | #endif /* CONFIG_NUMA */ | 1160 | #endif /* CONFIG_NUMA */ |
1224 | 1161 | ||
1162 | #if !defined(CONFIG_NUMA) || !defined(CONFIG_TMPFS) | ||
1163 | static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo) | ||
1164 | { | ||
1165 | return NULL; | ||
1166 | } | ||
1167 | #endif | ||
1168 | |||
1225 | /* | 1169 | /* |
1226 | * 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 |
1227 | * | 1171 | * |
@@ -1576,8 +1520,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) | |||
1576 | case S_IFREG: | 1520 | case S_IFREG: |
1577 | inode->i_op = &shmem_inode_operations; | 1521 | inode->i_op = &shmem_inode_operations; |
1578 | inode->i_fop = &shmem_file_operations; | 1522 | inode->i_fop = &shmem_file_operations; |
1579 | mpol_shared_policy_init(&info->policy, sbinfo->policy, | 1523 | mpol_shared_policy_init(&info->policy, |
1580 | &sbinfo->policy_nodes); | 1524 | shmem_get_sbmpol(sbinfo)); |
1581 | break; | 1525 | break; |
1582 | case S_IFDIR: | 1526 | case S_IFDIR: |
1583 | inc_nlink(inode); | 1527 | inc_nlink(inode); |
@@ -1591,8 +1535,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) | |||
1591 | * Must not load anything in the rbtree, | 1535 | * Must not load anything in the rbtree, |
1592 | * mpol_free_shared_policy will not be called. | 1536 | * mpol_free_shared_policy will not be called. |
1593 | */ | 1537 | */ |
1594 | mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, | 1538 | mpol_shared_policy_init(&info->policy, NULL); |
1595 | NULL); | ||
1596 | break; | 1539 | break; |
1597 | } | 1540 | } |
1598 | } else | 1541 | } else |
@@ -2207,8 +2150,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo, | |||
2207 | if (*rest) | 2150 | if (*rest) |
2208 | goto bad_val; | 2151 | goto bad_val; |
2209 | } else if (!strcmp(this_char,"mpol")) { | 2152 | } else if (!strcmp(this_char,"mpol")) { |
2210 | if (shmem_parse_mpol(value, &sbinfo->policy, | 2153 | if (mpol_parse_str(value, &sbinfo->mpol, 1)) |
2211 | &sbinfo->policy_nodes)) | ||
2212 | goto bad_val; | 2154 | goto bad_val; |
2213 | } else { | 2155 | } else { |
2214 | printk(KERN_ERR "tmpfs: Bad mount option %s\n", | 2156 | printk(KERN_ERR "tmpfs: Bad mount option %s\n", |
@@ -2259,8 +2201,9 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) | |||
2259 | sbinfo->free_blocks = config.max_blocks - blocks; | 2201 | sbinfo->free_blocks = config.max_blocks - blocks; |
2260 | sbinfo->max_inodes = config.max_inodes; | 2202 | sbinfo->max_inodes = config.max_inodes; |
2261 | sbinfo->free_inodes = config.max_inodes - inodes; | 2203 | sbinfo->free_inodes = config.max_inodes - inodes; |
2262 | sbinfo->policy = config.policy; | 2204 | |
2263 | sbinfo->policy_nodes = config.policy_nodes; | 2205 | mpol_put(sbinfo->mpol); |
2206 | sbinfo->mpol = config.mpol; /* transfers initial ref */ | ||
2264 | out: | 2207 | out: |
2265 | spin_unlock(&sbinfo->stat_lock); | 2208 | spin_unlock(&sbinfo->stat_lock); |
2266 | return error; | 2209 | return error; |
@@ -2281,7 +2224,7 @@ static int shmem_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
2281 | seq_printf(seq, ",uid=%u", sbinfo->uid); | 2224 | seq_printf(seq, ",uid=%u", sbinfo->uid); |
2282 | if (sbinfo->gid != 0) | 2225 | if (sbinfo->gid != 0) |
2283 | seq_printf(seq, ",gid=%u", sbinfo->gid); | 2226 | seq_printf(seq, ",gid=%u", sbinfo->gid); |
2284 | shmem_show_mpol(seq, sbinfo->policy, sbinfo->policy_nodes); | 2227 | shmem_show_mpol(seq, sbinfo->mpol); |
2285 | return 0; | 2228 | return 0; |
2286 | } | 2229 | } |
2287 | #endif /* CONFIG_TMPFS */ | 2230 | #endif /* CONFIG_TMPFS */ |
@@ -2311,8 +2254,7 @@ static int shmem_fill_super(struct super_block *sb, | |||
2311 | sbinfo->mode = S_IRWXUGO | S_ISVTX; | 2254 | sbinfo->mode = S_IRWXUGO | S_ISVTX; |
2312 | sbinfo->uid = current->fsuid; | 2255 | sbinfo->uid = current->fsuid; |
2313 | sbinfo->gid = current->fsgid; | 2256 | sbinfo->gid = current->fsgid; |
2314 | sbinfo->policy = MPOL_DEFAULT; | 2257 | sbinfo->mpol = NULL; |
2315 | sbinfo->policy_nodes = node_states[N_HIGH_MEMORY]; | ||
2316 | sb->s_fs_info = sbinfo; | 2258 | sb->s_fs_info = sbinfo; |
2317 | 2259 | ||
2318 | #ifdef CONFIG_TMPFS | 2260 | #ifdef CONFIG_TMPFS |