Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Howells and committed by
Al Viro
ec10a24f 74f78fc5

+96 -101
+11 -10
fs/jffs2/fs.c
··· 17 17 #include <linux/sched.h> 18 18 #include <linux/cred.h> 19 19 #include <linux/fs.h> 20 + #include <linux/fs_context.h> 20 21 #include <linux/list.h> 21 22 #include <linux/mtd/mtd.h> 22 23 #include <linux/pagemap.h> ··· 185 184 if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) { 186 185 truncate_setsize(inode, iattr->ia_size); 187 186 inode->i_blocks = (inode->i_size + 511) >> 9; 188 - } 187 + } 189 188 190 189 return 0; 191 190 } ··· 392 391 jffs2_do_setattr(inode, &iattr); 393 392 } 394 393 395 - int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data) 394 + int jffs2_do_remount_fs(struct super_block *sb, struct fs_context *fc) 396 395 { 397 396 struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 398 397 ··· 410 409 mutex_unlock(&c->alloc_sem); 411 410 } 412 411 413 - if (!(*flags & SB_RDONLY)) 412 + if (!(fc->sb_flags & SB_RDONLY)) 414 413 jffs2_start_garbage_collect_thread(c); 415 414 416 - *flags |= SB_NOATIME; 415 + fc->sb_flags |= SB_NOATIME; 417 416 return 0; 418 417 } 419 418 ··· 510 509 return hashsize; 511 510 } 512 511 513 - int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) 512 + int jffs2_do_fill_super(struct super_block *sb, struct fs_context *fc) 514 513 { 515 514 struct jffs2_sb_info *c; 516 515 struct inode *root_i; ··· 525 524 526 525 #ifndef CONFIG_JFFS2_FS_WRITEBUFFER 527 526 if (c->mtd->type == MTD_NANDFLASH) { 528 - pr_err("Cannot operate on NAND flash unless jffs2 NAND support is compiled in\n"); 527 + errorf(fc, "Cannot operate on NAND flash unless jffs2 NAND support is compiled in"); 529 528 return -EINVAL; 530 529 } 531 530 if (c->mtd->type == MTD_DATAFLASH) { 532 - pr_err("Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in\n"); 531 + errorf(fc, "Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in"); 533 532 return -EINVAL; 534 533 } 535 534 #endif ··· 543 542 */ 544 543 if ((c->sector_size * blocks) != c->flash_size) { 545 544 c->flash_size = c->sector_size * blocks; 546 - pr_info("Flash size not aligned to erasesize, reducing to %dKiB\n", 547 - c->flash_size / 1024); 545 + infof(fc, "Flash size not aligned to erasesize, reducing to %dKiB", 546 + c->flash_size / 1024); 548 547 } 549 548 550 549 if (c->flash_size < 5*c->sector_size) { 551 - pr_err("Too few erase blocks (%d)\n", 550 + errorf(fc, "Too few erase blocks (%d)", 552 551 c->flash_size / c->sector_size); 553 552 return -EINVAL; 554 553 }
+2 -2
fs/jffs2/os-linux.h
··· 172 172 struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, 173 173 struct jffs2_raw_inode *ri); 174 174 int jffs2_statfs (struct dentry *, struct kstatfs *); 175 - int jffs2_do_remount_fs(struct super_block *, int *, char *); 176 - int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); 175 + int jffs2_do_remount_fs(struct super_block *sb, struct fs_context *fc); 176 + int jffs2_do_fill_super(struct super_block *sb, struct fs_context *fc); 177 177 void jffs2_gc_release_inode(struct jffs2_sb_info *c, 178 178 struct jffs2_inode_info *f); 179 179 struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
+83 -89
fs/jffs2/super.c
··· 19 19 #include <linux/fs.h> 20 20 #include <linux/err.h> 21 21 #include <linux/mount.h> 22 - #include <linux/parser.h> 22 + #include <linux/fs_context.h> 23 + #include <linux/fs_parser.h> 23 24 #include <linux/jffs2.h> 24 25 #include <linux/pagemap.h> 25 26 #include <linux/mtd/super.h> ··· 158 157 /* 159 158 * JFFS2 mount options. 160 159 * 160 + * Opt_source: The source device 161 161 * Opt_override_compr: override default compressor 162 162 * Opt_rp_size: size of reserved pool in KiB 163 - * Opt_err: just end of array marker 164 163 */ 165 164 enum { 165 + Opt_source, 166 166 Opt_override_compr, 167 167 Opt_rp_size, 168 - Opt_err, 169 168 }; 170 169 171 - static const match_table_t tokens = { 172 - {Opt_override_compr, "compr=%s"}, 173 - {Opt_rp_size, "rp_size=%u"}, 174 - {Opt_err, NULL}, 170 + static const struct fs_parameter_spec jffs2_param_specs[] = { 171 + fsparam_string ("source", Opt_source), 172 + fsparam_enum ("compr", Opt_override_compr), 173 + fsparam_u32 ("rp_size", Opt_rp_size), 174 + {} 175 175 }; 176 176 177 - static int jffs2_parse_options(struct jffs2_sb_info *c, char *data) 178 - { 179 - substring_t args[MAX_OPT_ARGS]; 180 - char *p, *name; 181 - unsigned int opt; 182 - 183 - if (!data) 184 - return 0; 185 - 186 - while ((p = strsep(&data, ","))) { 187 - int token; 188 - 189 - if (!*p) 190 - continue; 191 - 192 - token = match_token(p, tokens, args); 193 - switch (token) { 194 - case Opt_override_compr: 195 - name = match_strdup(&args[0]); 196 - 197 - if (!name) 198 - return -ENOMEM; 199 - if (!strcmp(name, "none")) 200 - c->mount_opts.compr = JFFS2_COMPR_MODE_NONE; 177 + static const struct fs_parameter_enum jffs2_param_enums[] = { 178 + { Opt_override_compr, "none", JFFS2_COMPR_MODE_NONE }, 201 179 #ifdef CONFIG_JFFS2_LZO 202 - else if (!strcmp(name, "lzo")) 203 - c->mount_opts.compr = JFFS2_COMPR_MODE_FORCELZO; 180 + { Opt_override_compr, "lzo", JFFS2_COMPR_MODE_FORCELZO }, 204 181 #endif 205 182 #ifdef CONFIG_JFFS2_ZLIB 206 - else if (!strcmp(name, "zlib")) 207 - c->mount_opts.compr = 208 - JFFS2_COMPR_MODE_FORCEZLIB; 183 + { Opt_override_compr, "zlib", JFFS2_COMPR_MODE_FORCEZLIB }, 209 184 #endif 210 - else { 211 - pr_err("Error: unknown compressor \"%s\"\n", 212 - name); 213 - kfree(name); 214 - return -EINVAL; 215 - } 216 - kfree(name); 217 - c->mount_opts.override_compr = true; 218 - break; 219 - case Opt_rp_size: 220 - if (match_int(&args[0], &opt)) 221 - return -EINVAL; 222 - opt *= 1024; 223 - if (opt > c->mtd->size) { 224 - pr_warn("Too large reserve pool specified, max " 225 - "is %llu KB\n", c->mtd->size / 1024); 226 - return -EINVAL; 227 - } 228 - c->mount_opts.rp_size = opt; 229 - break; 230 - default: 231 - pr_err("Error: unrecognized mount option '%s' or missing value\n", 232 - p); 233 - return -EINVAL; 234 - } 185 + {} 186 + }; 187 + 188 + const struct fs_parameter_description jffs2_fs_parameters = { 189 + .name = "jffs2", 190 + .specs = jffs2_param_specs, 191 + .enums = jffs2_param_enums, 192 + }; 193 + 194 + static int jffs2_parse_param(struct fs_context *fc, struct fs_parameter *param) 195 + { 196 + struct fs_parse_result result; 197 + struct jffs2_sb_info *c = fc->s_fs_info; 198 + int opt; 199 + 200 + opt = fs_parse(fc, &jffs2_fs_parameters, param, &result); 201 + if (opt < 0) 202 + return opt; 203 + 204 + switch (opt) { 205 + case Opt_override_compr: 206 + c->mount_opts.compr = result.uint_32; 207 + c->mount_opts.override_compr = true; 208 + break; 209 + case Opt_rp_size: 210 + if (result.uint_32 > UINT_MAX / 1024) 211 + return invalf(fc, "jffs2: rp_size unrepresentable"); 212 + opt = result.uint_32 * 1024; 213 + if (opt > c->mtd->size) 214 + return invalf(fc, "jffs2: Too large reserve pool specified, max is %llu KB", 215 + c->mtd->size / 1024); 216 + c->mount_opts.rp_size = opt; 217 + break; 218 + default: 219 + return -EINVAL; 235 220 } 236 221 237 222 return 0; 238 223 } 239 224 240 - static int jffs2_remount_fs(struct super_block *sb, int *flags, char *data) 225 + static int jffs2_reconfigure(struct fs_context *fc) 241 226 { 242 - struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 243 - int err; 227 + struct super_block *sb = fc->root->d_sb; 244 228 245 229 sync_filesystem(sb); 246 - err = jffs2_parse_options(c, data); 247 - if (err) 248 - return -EINVAL; 249 - 250 - return jffs2_do_remount_fs(sb, flags, data); 230 + return jffs2_do_remount_fs(sb, fc); 251 231 } 252 232 253 233 static const struct super_operations jffs2_super_operations = ··· 237 255 .free_inode = jffs2_free_inode, 238 256 .put_super = jffs2_put_super, 239 257 .statfs = jffs2_statfs, 240 - .remount_fs = jffs2_remount_fs, 241 258 .evict_inode = jffs2_evict_inode, 242 259 .dirty_inode = jffs2_dirty_inode, 243 260 .show_options = jffs2_show_options, ··· 246 265 /* 247 266 * fill in the superblock 248 267 */ 249 - static int jffs2_fill_super(struct super_block *sb, void *data, int silent) 268 + static int jffs2_fill_super(struct super_block *sb, struct fs_context *fc) 250 269 { 251 - struct jffs2_sb_info *c; 252 - int ret; 270 + struct jffs2_sb_info *c = sb->s_fs_info; 253 271 254 272 jffs2_dbg(1, "jffs2_get_sb_mtd():" 255 273 " New superblock for device %d (\"%s\")\n", 256 274 sb->s_mtd->index, sb->s_mtd->name); 257 275 258 - c = kzalloc(sizeof(*c), GFP_KERNEL); 259 - if (!c) 260 - return -ENOMEM; 261 - 262 276 c->mtd = sb->s_mtd; 263 277 c->os_priv = sb; 264 - sb->s_fs_info = c; 265 - 266 - ret = jffs2_parse_options(c, data); 267 - if (ret) 268 - return -EINVAL; 269 278 270 279 /* Initialize JFFS2 superblock locks, the further initialization will 271 280 * be done later */ ··· 273 302 #ifdef CONFIG_JFFS2_FS_POSIX_ACL 274 303 sb->s_flags |= SB_POSIXACL; 275 304 #endif 276 - ret = jffs2_do_fill_super(sb, data, silent); 277 - return ret; 305 + return jffs2_do_fill_super(sb, fc); 278 306 } 279 307 280 - static struct dentry *jffs2_mount(struct file_system_type *fs_type, 281 - int flags, const char *dev_name, 282 - void *data) 308 + static int jffs2_get_tree(struct fs_context *fc) 283 309 { 284 - return mount_mtd(fs_type, flags, dev_name, data, jffs2_fill_super); 310 + return get_tree_mtd(fc, jffs2_fill_super); 311 + } 312 + 313 + static void jffs2_free_fc(struct fs_context *fc) 314 + { 315 + kfree(fc->s_fs_info); 316 + } 317 + 318 + static const struct fs_context_operations jffs2_context_ops = { 319 + .free = jffs2_free_fc, 320 + .parse_param = jffs2_parse_param, 321 + .get_tree = jffs2_get_tree, 322 + .reconfigure = jffs2_reconfigure, 323 + }; 324 + 325 + static int jffs2_init_fs_context(struct fs_context *fc) 326 + { 327 + struct jffs2_sb_info *ctx; 328 + 329 + ctx = kzalloc(sizeof(struct jffs2_sb_info), GFP_KERNEL); 330 + if (!ctx) 331 + return -ENOMEM; 332 + 333 + fc->s_fs_info = ctx; 334 + fc->ops = &jffs2_context_ops; 335 + return 0; 285 336 } 286 337 287 338 static void jffs2_put_super (struct super_block *sb) ··· 340 347 static struct file_system_type jffs2_fs_type = { 341 348 .owner = THIS_MODULE, 342 349 .name = "jffs2", 343 - .mount = jffs2_mount, 350 + .init_fs_context = jffs2_init_fs_context, 351 + .parameters = &jffs2_fs_parameters, 344 352 .kill_sb = jffs2_kill_sb, 345 353 }; 346 354 MODULE_ALIAS_FS("jffs2");