summaryrefslogtreecommitdiffstats
path: root/fs/jffs2/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/super.c')
-rw-r--r--fs/jffs2/super.c172
1 files changed, 83 insertions, 89 deletions
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index af4aa6599473..cbe70637c117 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -19,7 +19,8 @@
19#include <linux/fs.h> 19#include <linux/fs.h>
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/mount.h> 21#include <linux/mount.h>
22#include <linux/parser.h> 22#include <linux/fs_context.h>
23#include <linux/fs_parser.h>
23#include <linux/jffs2.h> 24#include <linux/jffs2.h>
24#include <linux/pagemap.h> 25#include <linux/pagemap.h>
25#include <linux/mtd/super.h> 26#include <linux/mtd/super.h>
@@ -157,96 +158,77 @@ static const struct export_operations jffs2_export_ops = {
157/* 158/*
158 * JFFS2 mount options. 159 * JFFS2 mount options.
159 * 160 *
161 * Opt_source: The source device
160 * Opt_override_compr: override default compressor 162 * Opt_override_compr: override default compressor
161 * Opt_rp_size: size of reserved pool in KiB 163 * Opt_rp_size: size of reserved pool in KiB
162 * Opt_err: just end of array marker
163 */ 164 */
164enum { 165enum {
166 Opt_source,
165 Opt_override_compr, 167 Opt_override_compr,
166 Opt_rp_size, 168 Opt_rp_size,
167 Opt_err,
168}; 169};
169 170
170static const match_table_t tokens = { 171static const struct fs_parameter_spec jffs2_param_specs[] = {
171 {Opt_override_compr, "compr=%s"}, 172 fsparam_string ("source", Opt_source),
172 {Opt_rp_size, "rp_size=%u"}, 173 fsparam_enum ("compr", Opt_override_compr),
173 {Opt_err, NULL}, 174 fsparam_u32 ("rp_size", Opt_rp_size),
175 {}
174}; 176};
175 177
176static int jffs2_parse_options(struct jffs2_sb_info *c, char *data) 178static const struct fs_parameter_enum jffs2_param_enums[] = {
177{ 179 { Opt_override_compr, "none", JFFS2_COMPR_MODE_NONE },
178 substring_t args[MAX_OPT_ARGS];
179 char *p, *name;
180 unsigned int opt;
181
182 if (!data)
183 return 0;
184
185 while ((p = strsep(&data, ","))) {
186 int token;
187
188 if (!*p)
189 continue;
190
191 token = match_token(p, tokens, args);
192 switch (token) {
193 case Opt_override_compr:
194 name = match_strdup(&args[0]);
195
196 if (!name)
197 return -ENOMEM;
198 if (!strcmp(name, "none"))
199 c->mount_opts.compr = JFFS2_COMPR_MODE_NONE;
200#ifdef CONFIG_JFFS2_LZO 180#ifdef CONFIG_JFFS2_LZO
201 else if (!strcmp(name, "lzo")) 181 { Opt_override_compr, "lzo", JFFS2_COMPR_MODE_FORCELZO },
202 c->mount_opts.compr = JFFS2_COMPR_MODE_FORCELZO;
203#endif 182#endif
204#ifdef CONFIG_JFFS2_ZLIB 183#ifdef CONFIG_JFFS2_ZLIB
205 else if (!strcmp(name, "zlib")) 184 { Opt_override_compr, "zlib", JFFS2_COMPR_MODE_FORCEZLIB },
206 c->mount_opts.compr =
207 JFFS2_COMPR_MODE_FORCEZLIB;
208#endif 185#endif
209 else { 186 {}
210 pr_err("Error: unknown compressor \"%s\"\n", 187};
211 name); 188
212 kfree(name); 189const struct fs_parameter_description jffs2_fs_parameters = {
213 return -EINVAL; 190 .name = "jffs2",
214 } 191 .specs = jffs2_param_specs,
215 kfree(name); 192 .enums = jffs2_param_enums,
216 c->mount_opts.override_compr = true; 193};
217 break; 194
218 case Opt_rp_size: 195static int jffs2_parse_param(struct fs_context *fc, struct fs_parameter *param)
219 if (match_int(&args[0], &opt)) 196{
220 return -EINVAL; 197 struct fs_parse_result result;
221 opt *= 1024; 198 struct jffs2_sb_info *c = fc->s_fs_info;
222 if (opt > c->mtd->size) { 199 int opt;
223 pr_warn("Too large reserve pool specified, max " 200
224 "is %llu KB\n", c->mtd->size / 1024); 201 opt = fs_parse(fc, &jffs2_fs_parameters, param, &result);
225 return -EINVAL; 202 if (opt < 0)
226 } 203 return opt;
227 c->mount_opts.rp_size = opt; 204
228 break; 205 switch (opt) {
229 default: 206 case Opt_override_compr:
230 pr_err("Error: unrecognized mount option '%s' or missing value\n", 207 c->mount_opts.compr = result.uint_32;
231 p); 208 c->mount_opts.override_compr = true;
232 return -EINVAL; 209 break;
233 } 210 case Opt_rp_size:
211 if (result.uint_32 > UINT_MAX / 1024)
212 return invalf(fc, "jffs2: rp_size unrepresentable");
213 opt = result.uint_32 * 1024;
214 if (opt > c->mtd->size)
215 return invalf(fc, "jffs2: Too large reserve pool specified, max is %llu KB",
216 c->mtd->size / 1024);
217 c->mount_opts.rp_size = opt;
218 break;
219 default:
220 return -EINVAL;
234 } 221 }
235 222
236 return 0; 223 return 0;
237} 224}
238 225
239static int jffs2_remount_fs(struct super_block *sb, int *flags, char *data) 226static int jffs2_reconfigure(struct fs_context *fc)
240{ 227{
241 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 228 struct super_block *sb = fc->root->d_sb;
242 int err;
243 229
244 sync_filesystem(sb); 230 sync_filesystem(sb);
245 err = jffs2_parse_options(c, data); 231 return jffs2_do_remount_fs(sb, fc);
246 if (err)
247 return -EINVAL;
248
249 return jffs2_do_remount_fs(sb, flags, data);
250} 232}
251 233
252static const struct super_operations jffs2_super_operations = 234static const struct super_operations jffs2_super_operations =
@@ -255,7 +237,6 @@ static const struct super_operations jffs2_super_operations =
255 .free_inode = jffs2_free_inode, 237 .free_inode = jffs2_free_inode,
256 .put_super = jffs2_put_super, 238 .put_super = jffs2_put_super,
257 .statfs = jffs2_statfs, 239 .statfs = jffs2_statfs,
258 .remount_fs = jffs2_remount_fs,
259 .evict_inode = jffs2_evict_inode, 240 .evict_inode = jffs2_evict_inode,
260 .dirty_inode = jffs2_dirty_inode, 241 .dirty_inode = jffs2_dirty_inode,
261 .show_options = jffs2_show_options, 242 .show_options = jffs2_show_options,
@@ -265,26 +246,16 @@ static const struct super_operations jffs2_super_operations =
265/* 246/*
266 * fill in the superblock 247 * fill in the superblock
267 */ 248 */
268static int jffs2_fill_super(struct super_block *sb, void *data, int silent) 249static int jffs2_fill_super(struct super_block *sb, struct fs_context *fc)
269{ 250{
270 struct jffs2_sb_info *c; 251 struct jffs2_sb_info *c = sb->s_fs_info;
271 int ret;
272 252
273 jffs2_dbg(1, "jffs2_get_sb_mtd():" 253 jffs2_dbg(1, "jffs2_get_sb_mtd():"
274 " New superblock for device %d (\"%s\")\n", 254 " New superblock for device %d (\"%s\")\n",
275 sb->s_mtd->index, sb->s_mtd->name); 255 sb->s_mtd->index, sb->s_mtd->name);
276 256
277 c = kzalloc(sizeof(*c), GFP_KERNEL);
278 if (!c)
279 return -ENOMEM;
280
281 c->mtd = sb->s_mtd; 257 c->mtd = sb->s_mtd;
282 c->os_priv = sb; 258 c->os_priv = sb;
283 sb->s_fs_info = c;
284
285 ret = jffs2_parse_options(c, data);
286 if (ret)
287 return -EINVAL;
288 259
289 /* Initialize JFFS2 superblock locks, the further initialization will 260 /* Initialize JFFS2 superblock locks, the further initialization will
290 * be done later */ 261 * be done later */
@@ -302,15 +273,37 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
302#ifdef CONFIG_JFFS2_FS_POSIX_ACL 273#ifdef CONFIG_JFFS2_FS_POSIX_ACL
303 sb->s_flags |= SB_POSIXACL; 274 sb->s_flags |= SB_POSIXACL;
304#endif 275#endif
305 ret = jffs2_do_fill_super(sb, data, silent); 276 return jffs2_do_fill_super(sb, fc);
306 return ret;
307} 277}
308 278
309static struct dentry *jffs2_mount(struct file_system_type *fs_type, 279static int jffs2_get_tree(struct fs_context *fc)
310 int flags, const char *dev_name,
311 void *data)
312{ 280{
313 return mount_mtd(fs_type, flags, dev_name, data, jffs2_fill_super); 281 return get_tree_mtd(fc, jffs2_fill_super);
282}
283
284static void jffs2_free_fc(struct fs_context *fc)
285{
286 kfree(fc->s_fs_info);
287}
288
289static const struct fs_context_operations jffs2_context_ops = {
290 .free = jffs2_free_fc,
291 .parse_param = jffs2_parse_param,
292 .get_tree = jffs2_get_tree,
293 .reconfigure = jffs2_reconfigure,
294};
295
296static int jffs2_init_fs_context(struct fs_context *fc)
297{
298 struct jffs2_sb_info *ctx;
299
300 ctx = kzalloc(sizeof(struct jffs2_sb_info), GFP_KERNEL);
301 if (!ctx)
302 return -ENOMEM;
303
304 fc->s_fs_info = ctx;
305 fc->ops = &jffs2_context_ops;
306 return 0;
314} 307}
315 308
316static void jffs2_put_super (struct super_block *sb) 309static void jffs2_put_super (struct super_block *sb)
@@ -347,7 +340,8 @@ static void jffs2_kill_sb(struct super_block *sb)
347static struct file_system_type jffs2_fs_type = { 340static struct file_system_type jffs2_fs_type = {
348 .owner = THIS_MODULE, 341 .owner = THIS_MODULE,
349 .name = "jffs2", 342 .name = "jffs2",
350 .mount = jffs2_mount, 343 .init_fs_context = jffs2_init_fs_context,
344 .parameters = &jffs2_fs_parameters,
351 .kill_sb = jffs2_kill_sb, 345 .kill_sb = jffs2_kill_sb,
352}; 346};
353MODULE_ALIAS_FS("jffs2"); 347MODULE_ALIAS_FS("jffs2");