summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-03-25 12:38:32 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2019-09-05 14:34:25 -0400
commitec10a24f10c8fbb6fd45701c795b6173e7dc80cc (patch)
tree542e347728817c9f42c2e2d48b468a9e17cdcb1e
parent74f78fc5ef43d2bb676f212ffa4ad693dffc4141 (diff)
vfs: Convert jffs2 to use the new mount API
Convert the jffs2 filesystem to the new internal mount API as the old one will be obsoleted and removed. This allows greater flexibility in communication of mount parameters between userspace, the VFS and the filesystem. See Documentation/filesystems/mount_api.txt for more information. Signed-off-by: David Howells <dhowells@redhat.com> cc: David Woodhouse <dwmw2@infradead.org> cc: linux-mtd@lists.infradead.org Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/jffs2/fs.c21
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jffs2/super.c172
3 files changed, 96 insertions, 101 deletions
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 8a20ddd25f2d..25736676a456 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -17,6 +17,7 @@
17#include <linux/sched.h> 17#include <linux/sched.h>
18#include <linux/cred.h> 18#include <linux/cred.h>
19#include <linux/fs.h> 19#include <linux/fs.h>
20#include <linux/fs_context.h>
20#include <linux/list.h> 21#include <linux/list.h>
21#include <linux/mtd/mtd.h> 22#include <linux/mtd/mtd.h>
22#include <linux/pagemap.h> 23#include <linux/pagemap.h>
@@ -184,7 +185,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
184 if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) { 185 if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
185 truncate_setsize(inode, iattr->ia_size); 186 truncate_setsize(inode, iattr->ia_size);
186 inode->i_blocks = (inode->i_size + 511) >> 9; 187 inode->i_blocks = (inode->i_size + 511) >> 9;
187 } 188 }
188 189
189 return 0; 190 return 0;
190} 191}
@@ -391,7 +392,7 @@ void jffs2_dirty_inode(struct inode *inode, int flags)
391 jffs2_do_setattr(inode, &iattr); 392 jffs2_do_setattr(inode, &iattr);
392} 393}
393 394
394int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data) 395int jffs2_do_remount_fs(struct super_block *sb, struct fs_context *fc)
395{ 396{
396 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 397 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
397 398
@@ -409,10 +410,10 @@ int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data)
409 mutex_unlock(&c->alloc_sem); 410 mutex_unlock(&c->alloc_sem);
410 } 411 }
411 412
412 if (!(*flags & SB_RDONLY)) 413 if (!(fc->sb_flags & SB_RDONLY))
413 jffs2_start_garbage_collect_thread(c); 414 jffs2_start_garbage_collect_thread(c);
414 415
415 *flags |= SB_NOATIME; 416 fc->sb_flags |= SB_NOATIME;
416 return 0; 417 return 0;
417} 418}
418 419
@@ -509,7 +510,7 @@ static int calculate_inocache_hashsize(uint32_t flash_size)
509 return hashsize; 510 return hashsize;
510} 511}
511 512
512int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) 513int jffs2_do_fill_super(struct super_block *sb, struct fs_context *fc)
513{ 514{
514 struct jffs2_sb_info *c; 515 struct jffs2_sb_info *c;
515 struct inode *root_i; 516 struct inode *root_i;
@@ -524,11 +525,11 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
524 525
525#ifndef CONFIG_JFFS2_FS_WRITEBUFFER 526#ifndef CONFIG_JFFS2_FS_WRITEBUFFER
526 if (c->mtd->type == MTD_NANDFLASH) { 527 if (c->mtd->type == MTD_NANDFLASH) {
527 pr_err("Cannot operate on NAND flash unless jffs2 NAND support is compiled in\n"); 528 errorf(fc, "Cannot operate on NAND flash unless jffs2 NAND support is compiled in");
528 return -EINVAL; 529 return -EINVAL;
529 } 530 }
530 if (c->mtd->type == MTD_DATAFLASH) { 531 if (c->mtd->type == MTD_DATAFLASH) {
531 pr_err("Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in\n"); 532 errorf(fc, "Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in");
532 return -EINVAL; 533 return -EINVAL;
533 } 534 }
534#endif 535#endif
@@ -542,12 +543,12 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
542 */ 543 */
543 if ((c->sector_size * blocks) != c->flash_size) { 544 if ((c->sector_size * blocks) != c->flash_size) {
544 c->flash_size = c->sector_size * blocks; 545 c->flash_size = c->sector_size * blocks;
545 pr_info("Flash size not aligned to erasesize, reducing to %dKiB\n", 546 infof(fc, "Flash size not aligned to erasesize, reducing to %dKiB",
546 c->flash_size / 1024); 547 c->flash_size / 1024);
547 } 548 }
548 549
549 if (c->flash_size < 5*c->sector_size) { 550 if (c->flash_size < 5*c->sector_size) {
550 pr_err("Too few erase blocks (%d)\n", 551 errorf(fc, "Too few erase blocks (%d)",
551 c->flash_size / c->sector_size); 552 c->flash_size / c->sector_size);
552 return -EINVAL; 553 return -EINVAL;
553 } 554 }
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index bd3d5f0ddc34..21071fc2975d 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -172,8 +172,8 @@ void jffs2_dirty_inode(struct inode *inode, int flags);
172struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, 172struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode,
173 struct jffs2_raw_inode *ri); 173 struct jffs2_raw_inode *ri);
174int jffs2_statfs (struct dentry *, struct kstatfs *); 174int jffs2_statfs (struct dentry *, struct kstatfs *);
175int jffs2_do_remount_fs(struct super_block *, int *, char *); 175int jffs2_do_remount_fs(struct super_block *sb, struct fs_context *fc);
176int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); 176int jffs2_do_fill_super(struct super_block *sb, struct fs_context *fc);
177void jffs2_gc_release_inode(struct jffs2_sb_info *c, 177void jffs2_gc_release_inode(struct jffs2_sb_info *c,
178 struct jffs2_inode_info *f); 178 struct jffs2_inode_info *f);
179struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, 179struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
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");