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

Merge patch series "adfs, affs, befs, hfs, hfsplus: convert to new mount api"

Eric Sandeen <sandeen@redhat.com> says:

These were all tested against images I created or obtained, using a
script to test random combinations of valid and invalid mount and
remount options, and comparing the results before and after the changes.

AFAICT, all parsing works as expected and behavior is unchanged.

* patches from https://lore.kernel.org/r/20240916172735.866916-1-sandeen@redhat.com:
hfsplus: convert hfsplus to use the new mount api
hfs: convert hfs to use the new mount api
befs: convert befs to use the new mount api
affs: convert affs to use the new mount api
adfs: convert adfs to use the new mount api

Link: https://lore.kernel.org/r/20240916172735.866916-1-sandeen@redhat.com
Signed-off-by: Christian Brauner <brauner@kernel.org>

+677 -751
+93 -89
fs/adfs/super.c
··· 6 6 */ 7 7 #include <linux/module.h> 8 8 #include <linux/init.h> 9 - #include <linux/parser.h> 9 + #include <linux/fs_parser.h> 10 + #include <linux/fs_context.h> 10 11 #include <linux/mount.h> 11 12 #include <linux/seq_file.h> 12 13 #include <linux/slab.h> ··· 116 115 return 0; 117 116 } 118 117 119 - enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_ftsuffix, Opt_err}; 118 + enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_ftsuffix}; 120 119 121 - static const match_table_t tokens = { 122 - {Opt_uid, "uid=%u"}, 123 - {Opt_gid, "gid=%u"}, 124 - {Opt_ownmask, "ownmask=%o"}, 125 - {Opt_othmask, "othmask=%o"}, 126 - {Opt_ftsuffix, "ftsuffix=%u"}, 127 - {Opt_err, NULL} 120 + static const struct fs_parameter_spec adfs_param_spec[] = { 121 + fsparam_uid ("uid", Opt_uid), 122 + fsparam_gid ("gid", Opt_gid), 123 + fsparam_u32oct ("ownmask", Opt_ownmask), 124 + fsparam_u32oct ("othmask", Opt_othmask), 125 + fsparam_u32 ("ftsuffix", Opt_ftsuffix), 126 + {} 128 127 }; 129 128 130 - static int parse_options(struct super_block *sb, struct adfs_sb_info *asb, 131 - char *options) 129 + static int adfs_parse_param(struct fs_context *fc, struct fs_parameter *param) 132 130 { 133 - char *p; 134 - int option; 131 + struct adfs_sb_info *asb = fc->s_fs_info; 132 + struct fs_parse_result result; 133 + int opt; 135 134 136 - if (!options) 137 - return 0; 135 + opt = fs_parse(fc, adfs_param_spec, param, &result); 136 + if (opt < 0) 137 + return opt; 138 138 139 - while ((p = strsep(&options, ",")) != NULL) { 140 - substring_t args[MAX_OPT_ARGS]; 141 - int token; 142 - if (!*p) 143 - continue; 144 - 145 - token = match_token(p, tokens, args); 146 - switch (token) { 147 - case Opt_uid: 148 - if (match_int(args, &option)) 149 - return -EINVAL; 150 - asb->s_uid = make_kuid(current_user_ns(), option); 151 - if (!uid_valid(asb->s_uid)) 152 - return -EINVAL; 153 - break; 154 - case Opt_gid: 155 - if (match_int(args, &option)) 156 - return -EINVAL; 157 - asb->s_gid = make_kgid(current_user_ns(), option); 158 - if (!gid_valid(asb->s_gid)) 159 - return -EINVAL; 160 - break; 161 - case Opt_ownmask: 162 - if (match_octal(args, &option)) 163 - return -EINVAL; 164 - asb->s_owner_mask = option; 165 - break; 166 - case Opt_othmask: 167 - if (match_octal(args, &option)) 168 - return -EINVAL; 169 - asb->s_other_mask = option; 170 - break; 171 - case Opt_ftsuffix: 172 - if (match_int(args, &option)) 173 - return -EINVAL; 174 - asb->s_ftsuffix = option; 175 - break; 176 - default: 177 - adfs_msg(sb, KERN_ERR, 178 - "unrecognised mount option \"%s\" or missing value", 179 - p); 180 - return -EINVAL; 181 - } 139 + switch (opt) { 140 + case Opt_uid: 141 + asb->s_uid = result.uid; 142 + break; 143 + case Opt_gid: 144 + asb->s_gid = result.gid; 145 + break; 146 + case Opt_ownmask: 147 + asb->s_owner_mask = result.uint_32; 148 + break; 149 + case Opt_othmask: 150 + asb->s_other_mask = result.uint_32; 151 + break; 152 + case Opt_ftsuffix: 153 + asb->s_ftsuffix = result.uint_32; 154 + break; 155 + default: 156 + return -EINVAL; 182 157 } 183 158 return 0; 184 159 } 185 160 186 - static int adfs_remount(struct super_block *sb, int *flags, char *data) 161 + static int adfs_reconfigure(struct fs_context *fc) 187 162 { 188 - struct adfs_sb_info temp_asb; 189 - int ret; 163 + struct adfs_sb_info *new_asb = fc->s_fs_info; 164 + struct adfs_sb_info *asb = ADFS_SB(fc->root->d_sb); 190 165 191 - sync_filesystem(sb); 192 - *flags |= ADFS_SB_FLAGS; 166 + sync_filesystem(fc->root->d_sb); 167 + fc->sb_flags |= ADFS_SB_FLAGS; 193 168 194 - temp_asb = *ADFS_SB(sb); 195 - ret = parse_options(sb, &temp_asb, data); 196 - if (ret == 0) 197 - *ADFS_SB(sb) = temp_asb; 169 + /* Structure copy newly parsed options */ 170 + *asb = *new_asb; 198 171 199 - return ret; 172 + return 0; 200 173 } 201 174 202 175 static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf) ··· 248 273 .write_inode = adfs_write_inode, 249 274 .put_super = adfs_put_super, 250 275 .statfs = adfs_statfs, 251 - .remount_fs = adfs_remount, 252 276 .show_options = adfs_show_options, 253 277 }; 254 278 ··· 335 361 return 0; 336 362 } 337 363 338 - static int adfs_fill_super(struct super_block *sb, void *data, int silent) 364 + static int adfs_fill_super(struct super_block *sb, struct fs_context *fc) 339 365 { 340 366 struct adfs_discrecord *dr; 341 367 struct object_info root_obj; 342 - struct adfs_sb_info *asb; 368 + struct adfs_sb_info *asb = sb->s_fs_info; 343 369 struct inode *root; 344 370 int ret = -EINVAL; 371 + int silent = fc->sb_flags & SB_SILENT; 345 372 346 373 sb->s_flags |= ADFS_SB_FLAGS; 347 - 348 - asb = kzalloc(sizeof(*asb), GFP_KERNEL); 349 - if (!asb) 350 - return -ENOMEM; 351 374 352 375 sb->s_fs_info = asb; 353 376 sb->s_magic = ADFS_SUPER_MAGIC; 354 377 sb->s_time_gran = 10000000; 355 - 356 - /* set default options */ 357 - asb->s_uid = GLOBAL_ROOT_UID; 358 - asb->s_gid = GLOBAL_ROOT_GID; 359 - asb->s_owner_mask = ADFS_DEFAULT_OWNER_MASK; 360 - asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK; 361 - asb->s_ftsuffix = 0; 362 - 363 - if (parse_options(sb, asb, data)) 364 - goto error; 365 378 366 379 /* Try to probe the filesystem boot block */ 367 380 ret = adfs_probe(sb, ADFS_DISCRECORD, 1, adfs_validate_bblk); ··· 414 453 return ret; 415 454 } 416 455 417 - static struct dentry *adfs_mount(struct file_system_type *fs_type, 418 - int flags, const char *dev_name, void *data) 456 + static int adfs_get_tree(struct fs_context *fc) 419 457 { 420 - return mount_bdev(fs_type, flags, dev_name, data, adfs_fill_super); 458 + return get_tree_bdev(fc, adfs_fill_super); 459 + } 460 + 461 + static void adfs_free_fc(struct fs_context *fc) 462 + { 463 + struct adfs_context *asb = fc->s_fs_info; 464 + 465 + kfree(asb); 466 + } 467 + 468 + static const struct fs_context_operations adfs_context_ops = { 469 + .parse_param = adfs_parse_param, 470 + .get_tree = adfs_get_tree, 471 + .reconfigure = adfs_reconfigure, 472 + .free = adfs_free_fc, 473 + }; 474 + 475 + static int adfs_init_fs_context(struct fs_context *fc) 476 + { 477 + struct adfs_sb_info *asb; 478 + 479 + asb = kzalloc(sizeof(struct adfs_sb_info), GFP_KERNEL); 480 + if (!asb) 481 + return -ENOMEM; 482 + 483 + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) { 484 + struct super_block *sb = fc->root->d_sb; 485 + struct adfs_sb_info *old_asb = ADFS_SB(sb); 486 + 487 + /* structure copy existing options before parsing */ 488 + *asb = *old_asb; 489 + } else { 490 + /* set default options */ 491 + asb->s_uid = GLOBAL_ROOT_UID; 492 + asb->s_gid = GLOBAL_ROOT_GID; 493 + asb->s_owner_mask = ADFS_DEFAULT_OWNER_MASK; 494 + asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK; 495 + asb->s_ftsuffix = 0; 496 + } 497 + 498 + fc->ops = &adfs_context_ops; 499 + fc->s_fs_info = asb; 500 + 501 + return 0; 421 502 } 422 503 423 504 static struct file_system_type adfs_fs_type = { 424 505 .owner = THIS_MODULE, 425 506 .name = "adfs", 426 - .mount = adfs_mount, 427 507 .kill_sb = kill_block_super, 428 508 .fs_flags = FS_REQUIRES_DEV, 509 + .init_fs_context = adfs_init_fs_context, 510 + .parameters = adfs_param_spec, 429 511 }; 430 512 MODULE_ALIAS_FS("adfs"); 431 513
+186 -184
fs/affs/super.c
··· 14 14 #include <linux/module.h> 15 15 #include <linux/init.h> 16 16 #include <linux/statfs.h> 17 - #include <linux/parser.h> 17 + #include <linux/fs_parser.h> 18 + #include <linux/fs_context.h> 18 19 #include <linux/magic.h> 19 20 #include <linux/sched.h> 20 21 #include <linux/cred.h> ··· 28 27 29 28 static int affs_statfs(struct dentry *dentry, struct kstatfs *buf); 30 29 static int affs_show_options(struct seq_file *m, struct dentry *root); 31 - static int affs_remount (struct super_block *sb, int *flags, char *data); 32 30 33 31 static void 34 32 affs_commit_super(struct super_block *sb, int wait) ··· 155 155 .put_super = affs_put_super, 156 156 .sync_fs = affs_sync_fs, 157 157 .statfs = affs_statfs, 158 - .remount_fs = affs_remount, 159 158 .show_options = affs_show_options, 160 159 }; 161 160 162 161 enum { 163 162 Opt_bs, Opt_mode, Opt_mufs, Opt_notruncate, Opt_prefix, Opt_protect, 164 163 Opt_reserved, Opt_root, Opt_setgid, Opt_setuid, 165 - Opt_verbose, Opt_volume, Opt_ignore, Opt_err, 164 + Opt_verbose, Opt_volume, Opt_ignore, 166 165 }; 167 166 168 - static const match_table_t tokens = { 169 - {Opt_bs, "bs=%u"}, 170 - {Opt_mode, "mode=%o"}, 171 - {Opt_mufs, "mufs"}, 172 - {Opt_notruncate, "nofilenametruncate"}, 173 - {Opt_prefix, "prefix=%s"}, 174 - {Opt_protect, "protect"}, 175 - {Opt_reserved, "reserved=%u"}, 176 - {Opt_root, "root=%u"}, 177 - {Opt_setgid, "setgid=%u"}, 178 - {Opt_setuid, "setuid=%u"}, 179 - {Opt_verbose, "verbose"}, 180 - {Opt_volume, "volume=%s"}, 181 - {Opt_ignore, "grpquota"}, 182 - {Opt_ignore, "noquota"}, 183 - {Opt_ignore, "quota"}, 184 - {Opt_ignore, "usrquota"}, 185 - {Opt_err, NULL}, 167 + struct affs_context { 168 + kuid_t uid; /* uid to override */ 169 + kgid_t gid; /* gid to override */ 170 + unsigned int mode; /* mode to override */ 171 + unsigned int reserved; /* Number of reserved blocks */ 172 + int root_block; /* FFS root block number */ 173 + int blocksize; /* Initial device blksize */ 174 + char *prefix; /* Prefix for volumes and assigns */ 175 + char volume[32]; /* Vol. prefix for absolute symlinks */ 176 + unsigned long mount_flags; /* Options */ 186 177 }; 187 178 188 - static int 189 - parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved, s32 *root, 190 - int *blocksize, char **prefix, char *volume, unsigned long *mount_opts) 179 + static const struct fs_parameter_spec affs_param_spec[] = { 180 + fsparam_u32 ("bs", Opt_bs), 181 + fsparam_u32oct ("mode", Opt_mode), 182 + fsparam_flag ("mufs", Opt_mufs), 183 + fsparam_flag ("nofilenametruncate", Opt_notruncate), 184 + fsparam_string ("prefix", Opt_prefix), 185 + fsparam_flag ("protect", Opt_protect), 186 + fsparam_u32 ("reserved", Opt_reserved), 187 + fsparam_u32 ("root", Opt_root), 188 + fsparam_gid ("setgid", Opt_setgid), 189 + fsparam_uid ("setuid", Opt_setuid), 190 + fsparam_flag ("verbose", Opt_verbose), 191 + fsparam_string ("volume", Opt_volume), 192 + fsparam_flag ("grpquota", Opt_ignore), 193 + fsparam_flag ("noquota", Opt_ignore), 194 + fsparam_flag ("quota", Opt_ignore), 195 + fsparam_flag ("usrquota", Opt_ignore), 196 + {}, 197 + }; 198 + 199 + static int affs_parse_param(struct fs_context *fc, struct fs_parameter *param) 191 200 { 192 - char *p; 193 - substring_t args[MAX_OPT_ARGS]; 201 + struct affs_context *ctx = fc->fs_private; 202 + struct fs_parse_result result; 203 + int n; 204 + int opt; 194 205 195 - /* Fill in defaults */ 206 + opt = fs_parse(fc, affs_param_spec, param, &result); 207 + if (opt < 0) 208 + return opt; 196 209 197 - *uid = current_uid(); 198 - *gid = current_gid(); 199 - *reserved = 2; 200 - *root = -1; 201 - *blocksize = -1; 202 - volume[0] = ':'; 203 - volume[1] = 0; 204 - *mount_opts = 0; 205 - if (!options) 206 - return 1; 207 - 208 - while ((p = strsep(&options, ",")) != NULL) { 209 - int token, n, option; 210 - if (!*p) 211 - continue; 212 - 213 - token = match_token(p, tokens, args); 214 - switch (token) { 215 - case Opt_bs: 216 - if (match_int(&args[0], &n)) 217 - return 0; 218 - if (n != 512 && n != 1024 && n != 2048 219 - && n != 4096) { 220 - pr_warn("Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); 221 - return 0; 222 - } 223 - *blocksize = n; 224 - break; 225 - case Opt_mode: 226 - if (match_octal(&args[0], &option)) 227 - return 0; 228 - *mode = option & 0777; 229 - affs_set_opt(*mount_opts, SF_SETMODE); 230 - break; 231 - case Opt_mufs: 232 - affs_set_opt(*mount_opts, SF_MUFS); 233 - break; 234 - case Opt_notruncate: 235 - affs_set_opt(*mount_opts, SF_NO_TRUNCATE); 236 - break; 237 - case Opt_prefix: 238 - kfree(*prefix); 239 - *prefix = match_strdup(&args[0]); 240 - if (!*prefix) 241 - return 0; 242 - affs_set_opt(*mount_opts, SF_PREFIX); 243 - break; 244 - case Opt_protect: 245 - affs_set_opt(*mount_opts, SF_IMMUTABLE); 246 - break; 247 - case Opt_reserved: 248 - if (match_int(&args[0], reserved)) 249 - return 0; 250 - break; 251 - case Opt_root: 252 - if (match_int(&args[0], root)) 253 - return 0; 254 - break; 255 - case Opt_setgid: 256 - if (match_int(&args[0], &option)) 257 - return 0; 258 - *gid = make_kgid(current_user_ns(), option); 259 - if (!gid_valid(*gid)) 260 - return 0; 261 - affs_set_opt(*mount_opts, SF_SETGID); 262 - break; 263 - case Opt_setuid: 264 - if (match_int(&args[0], &option)) 265 - return 0; 266 - *uid = make_kuid(current_user_ns(), option); 267 - if (!uid_valid(*uid)) 268 - return 0; 269 - affs_set_opt(*mount_opts, SF_SETUID); 270 - break; 271 - case Opt_verbose: 272 - affs_set_opt(*mount_opts, SF_VERBOSE); 273 - break; 274 - case Opt_volume: { 275 - char *vol = match_strdup(&args[0]); 276 - if (!vol) 277 - return 0; 278 - strscpy(volume, vol, 32); 279 - kfree(vol); 280 - break; 210 + switch (opt) { 211 + case Opt_bs: 212 + n = result.uint_32; 213 + if (n != 512 && n != 1024 && n != 2048 214 + && n != 4096) { 215 + pr_warn("Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); 216 + return -EINVAL; 281 217 } 282 - case Opt_ignore: 283 - /* Silently ignore the quota options */ 284 - break; 285 - default: 286 - pr_warn("Unrecognized mount option \"%s\" or missing value\n", 287 - p); 288 - return 0; 289 - } 218 + ctx->blocksize = n; 219 + break; 220 + case Opt_mode: 221 + ctx->mode = result.uint_32 & 0777; 222 + affs_set_opt(ctx->mount_flags, SF_SETMODE); 223 + break; 224 + case Opt_mufs: 225 + affs_set_opt(ctx->mount_flags, SF_MUFS); 226 + break; 227 + case Opt_notruncate: 228 + affs_set_opt(ctx->mount_flags, SF_NO_TRUNCATE); 229 + break; 230 + case Opt_prefix: 231 + kfree(ctx->prefix); 232 + ctx->prefix = param->string; 233 + param->string = NULL; 234 + affs_set_opt(ctx->mount_flags, SF_PREFIX); 235 + break; 236 + case Opt_protect: 237 + affs_set_opt(ctx->mount_flags, SF_IMMUTABLE); 238 + break; 239 + case Opt_reserved: 240 + ctx->reserved = result.uint_32; 241 + break; 242 + case Opt_root: 243 + ctx->root_block = result.uint_32; 244 + break; 245 + case Opt_setgid: 246 + ctx->gid = result.gid; 247 + affs_set_opt(ctx->mount_flags, SF_SETGID); 248 + break; 249 + case Opt_setuid: 250 + ctx->uid = result.uid; 251 + affs_set_opt(ctx->mount_flags, SF_SETUID); 252 + break; 253 + case Opt_verbose: 254 + affs_set_opt(ctx->mount_flags, SF_VERBOSE); 255 + break; 256 + case Opt_volume: 257 + strscpy(ctx->volume, param->string, 32); 258 + break; 259 + case Opt_ignore: 260 + /* Silently ignore the quota options */ 261 + break; 262 + default: 263 + return -EINVAL; 290 264 } 291 - return 1; 265 + return 0; 292 266 } 293 267 294 268 static int affs_show_options(struct seq_file *m, struct dentry *root) ··· 303 329 * hopefully have the guts to do so. Until then: sorry for the mess. 304 330 */ 305 331 306 - static int affs_fill_super(struct super_block *sb, void *data, int silent) 332 + static int affs_fill_super(struct super_block *sb, struct fs_context *fc) 307 333 { 308 334 struct affs_sb_info *sbi; 335 + struct affs_context *ctx = fc->fs_private; 309 336 struct buffer_head *root_bh = NULL; 310 337 struct buffer_head *boot_bh; 311 338 struct inode *root_inode = NULL; 312 - s32 root_block; 339 + int silent = fc->sb_flags & SB_SILENT; 313 340 int size, blocksize; 314 341 u32 chksum; 315 342 int num_bm; 316 343 int i, j; 317 - kuid_t uid; 318 - kgid_t gid; 319 - int reserved; 320 - unsigned long mount_flags; 321 344 int tmp_flags; /* fix remount prototype... */ 322 345 u8 sig[4]; 323 346 int ret; 324 - 325 - pr_debug("read_super(%s)\n", data ? (const char *)data : "no options"); 326 347 327 348 sb->s_magic = AFFS_SUPER_MAGIC; 328 349 sb->s_op = &affs_sops; ··· 338 369 spin_lock_init(&sbi->work_lock); 339 370 INIT_DELAYED_WORK(&sbi->sb_work, flush_superblock); 340 371 341 - if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, 342 - &blocksize,&sbi->s_prefix, 343 - sbi->s_volume, &mount_flags)) { 344 - pr_err("Error parsing options\n"); 345 - return -EINVAL; 346 - } 347 - /* N.B. after this point s_prefix must be released */ 372 + sbi->s_flags = ctx->mount_flags; 373 + sbi->s_mode = ctx->mode; 374 + sbi->s_uid = ctx->uid; 375 + sbi->s_gid = ctx->gid; 376 + sbi->s_reserved = ctx->reserved; 377 + sbi->s_prefix = ctx->prefix; 378 + ctx->prefix = NULL; 379 + memcpy(sbi->s_volume, ctx->volume, 32); 348 380 349 - sbi->s_flags = mount_flags; 350 - sbi->s_mode = i; 351 - sbi->s_uid = uid; 352 - sbi->s_gid = gid; 353 - sbi->s_reserved= reserved; 381 + /* N.B. after this point s_prefix must be released */ 354 382 355 383 /* Get the size of the device in 512-byte blocks. 356 384 * If we later see that the partition uses bigger ··· 362 396 363 397 i = bdev_logical_block_size(sb->s_bdev); 364 398 j = PAGE_SIZE; 399 + blocksize = ctx->blocksize; 365 400 if (blocksize > 0) { 366 401 i = j = blocksize; 367 402 size = size / (blocksize / 512); 368 403 } 369 404 370 405 for (blocksize = i; blocksize <= j; blocksize <<= 1, size >>= 1) { 371 - sbi->s_root_block = root_block; 372 - if (root_block < 0) 373 - sbi->s_root_block = (reserved + size - 1) / 2; 406 + sbi->s_root_block = ctx->root_block; 407 + if (ctx->root_block < 0) 408 + sbi->s_root_block = (ctx->reserved + size - 1) / 2; 374 409 pr_debug("setting blocksize to %d\n", blocksize); 375 410 affs_set_blocksize(sb, blocksize); 376 411 sbi->s_partition_size = size; ··· 391 424 "size=%d, reserved=%d\n", 392 425 sb->s_id, 393 426 sbi->s_root_block + num_bm, 394 - blocksize, size, reserved); 427 + ctx->blocksize, size, ctx->reserved); 395 428 root_bh = affs_bread(sb, sbi->s_root_block + num_bm); 396 429 if (!root_bh) 397 430 continue; ··· 414 447 got_root: 415 448 /* Keep super block in cache */ 416 449 sbi->s_root_bh = root_bh; 417 - root_block = sbi->s_root_block; 450 + ctx->root_block = sbi->s_root_block; 418 451 419 452 /* Find out which kind of FS we have */ 420 453 boot_bh = sb_bread(sb, 0); ··· 473 506 return -EINVAL; 474 507 } 475 508 476 - if (affs_test_opt(mount_flags, SF_VERBOSE)) { 509 + if (affs_test_opt(ctx->mount_flags, SF_VERBOSE)) { 477 510 u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0]; 478 511 pr_notice("Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n", 479 512 len > 31 ? 31 : len, ··· 495 528 496 529 /* set up enough so that it can read an inode */ 497 530 498 - root_inode = affs_iget(sb, root_block); 531 + root_inode = affs_iget(sb, ctx->root_block); 499 532 if (IS_ERR(root_inode)) 500 533 return PTR_ERR(root_inode); 501 534 ··· 515 548 return 0; 516 549 } 517 550 518 - static int 519 - affs_remount(struct super_block *sb, int *flags, char *data) 551 + static int affs_reconfigure(struct fs_context *fc) 520 552 { 553 + struct super_block *sb = fc->root->d_sb; 554 + struct affs_context *ctx = fc->fs_private; 521 555 struct affs_sb_info *sbi = AFFS_SB(sb); 522 - int blocksize; 523 - kuid_t uid; 524 - kgid_t gid; 525 - int mode; 526 - int reserved; 527 - int root_block; 528 - unsigned long mount_flags; 529 556 int res = 0; 530 - char volume[32]; 531 - char *prefix = NULL; 532 - 533 - pr_debug("%s(flags=0x%x,opts=\"%s\")\n", __func__, *flags, data); 534 557 535 558 sync_filesystem(sb); 536 - *flags |= SB_NODIRATIME; 537 - 538 - memcpy(volume, sbi->s_volume, 32); 539 - if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block, 540 - &blocksize, &prefix, volume, 541 - &mount_flags)) { 542 - kfree(prefix); 543 - return -EINVAL; 544 - } 559 + fc->sb_flags |= SB_NODIRATIME; 545 560 546 561 flush_delayed_work(&sbi->sb_work); 547 562 548 - sbi->s_flags = mount_flags; 549 - sbi->s_mode = mode; 550 - sbi->s_uid = uid; 551 - sbi->s_gid = gid; 563 + /* 564 + * NB: Historically, only mount_flags, mode, uid, gic, prefix, 565 + * and volume are accepted during remount. 566 + */ 567 + sbi->s_flags = ctx->mount_flags; 568 + sbi->s_mode = ctx->mode; 569 + sbi->s_uid = ctx->uid; 570 + sbi->s_gid = ctx->gid; 552 571 /* protect against readers */ 553 572 spin_lock(&sbi->symlink_lock); 554 - if (prefix) { 573 + if (ctx->prefix) { 555 574 kfree(sbi->s_prefix); 556 - sbi->s_prefix = prefix; 575 + sbi->s_prefix = ctx->prefix; 576 + ctx->prefix = NULL; 557 577 } 558 - memcpy(sbi->s_volume, volume, 32); 578 + memcpy(sbi->s_volume, ctx->volume, 32); 559 579 spin_unlock(&sbi->symlink_lock); 560 580 561 - if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb)) 581 + if ((bool)(fc->sb_flags & SB_RDONLY) == sb_rdonly(sb)) 562 582 return 0; 563 583 564 - if (*flags & SB_RDONLY) 584 + if (fc->sb_flags & SB_RDONLY) 565 585 affs_free_bitmap(sb); 566 586 else 567 - res = affs_init_bitmap(sb, flags); 587 + res = affs_init_bitmap(sb, &fc->sb_flags); 568 588 569 589 return res; 570 590 } ··· 578 624 return 0; 579 625 } 580 626 581 - static struct dentry *affs_mount(struct file_system_type *fs_type, 582 - int flags, const char *dev_name, void *data) 627 + static int affs_get_tree(struct fs_context *fc) 583 628 { 584 - return mount_bdev(fs_type, flags, dev_name, data, affs_fill_super); 629 + return get_tree_bdev(fc, affs_fill_super); 585 630 } 586 631 587 632 static void affs_kill_sb(struct super_block *sb) ··· 596 643 } 597 644 } 598 645 646 + static void affs_free_fc(struct fs_context *fc) 647 + { 648 + struct affs_context *ctx = fc->fs_private; 649 + 650 + kfree(ctx->prefix); 651 + kfree(ctx); 652 + } 653 + 654 + static const struct fs_context_operations affs_context_ops = { 655 + .parse_param = affs_parse_param, 656 + .get_tree = affs_get_tree, 657 + .reconfigure = affs_reconfigure, 658 + .free = affs_free_fc, 659 + }; 660 + 661 + static int affs_init_fs_context(struct fs_context *fc) 662 + { 663 + struct affs_context *ctx; 664 + 665 + ctx = kzalloc(sizeof(struct affs_context), GFP_KERNEL); 666 + if (!ctx) 667 + return -ENOMEM; 668 + 669 + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) { 670 + struct super_block *sb = fc->root->d_sb; 671 + struct affs_sb_info *sbi = AFFS_SB(sb); 672 + 673 + /* 674 + * NB: historically, no options other than volume were 675 + * preserved across a remount unless they were explicitly 676 + * passed in. 677 + */ 678 + memcpy(ctx->volume, sbi->s_volume, 32); 679 + } else { 680 + ctx->uid = current_uid(); 681 + ctx->gid = current_gid(); 682 + ctx->reserved = 2; 683 + ctx->root_block = -1; 684 + ctx->blocksize = -1; 685 + ctx->volume[0] = ':'; 686 + } 687 + 688 + fc->ops = &affs_context_ops; 689 + fc->fs_private = ctx; 690 + 691 + return 0; 692 + } 693 + 599 694 static struct file_system_type affs_fs_type = { 600 695 .owner = THIS_MODULE, 601 696 .name = "affs", 602 - .mount = affs_mount, 603 697 .kill_sb = affs_kill_sb, 604 698 .fs_flags = FS_REQUIRES_DEV, 699 + .init_fs_context = affs_init_fs_context, 700 + .parameters = affs_param_spec, 605 701 }; 606 702 MODULE_ALIAS_FS("affs"); 607 703
+99 -94
fs/befs/linuxvfs.c
··· 11 11 #include <linux/module.h> 12 12 #include <linux/slab.h> 13 13 #include <linux/fs.h> 14 + #include <linux/fs_context.h> 15 + #include <linux/fs_parser.h> 14 16 #include <linux/errno.h> 15 17 #include <linux/stat.h> 16 18 #include <linux/nls.h> 17 19 #include <linux/buffer_head.h> 18 20 #include <linux/vfs.h> 19 - #include <linux/parser.h> 20 21 #include <linux/namei.h> 21 22 #include <linux/sched.h> 22 23 #include <linux/cred.h> ··· 55 54 static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, 56 55 char **out, int *out_len); 57 56 static void befs_put_super(struct super_block *); 58 - static int befs_remount(struct super_block *, int *, char *); 59 57 static int befs_statfs(struct dentry *, struct kstatfs *); 60 58 static int befs_show_options(struct seq_file *, struct dentry *); 61 - static int parse_options(char *, struct befs_mount_options *); 62 59 static struct dentry *befs_fh_to_dentry(struct super_block *sb, 63 60 struct fid *fid, int fh_len, int fh_type); 64 61 static struct dentry *befs_fh_to_parent(struct super_block *sb, 65 62 struct fid *fid, int fh_len, int fh_type); 66 63 static struct dentry *befs_get_parent(struct dentry *child); 64 + static void befs_free_fc(struct fs_context *fc); 67 65 68 66 static const struct super_operations befs_sops = { 69 67 .alloc_inode = befs_alloc_inode, /* allocate a new inode */ 70 68 .free_inode = befs_free_inode, /* deallocate an inode */ 71 69 .put_super = befs_put_super, /* uninit super */ 72 70 .statfs = befs_statfs, /* statfs */ 73 - .remount_fs = befs_remount, 74 71 .show_options = befs_show_options, 75 72 }; 76 73 ··· 671 672 } 672 673 673 674 enum { 674 - Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err, 675 + Opt_uid, Opt_gid, Opt_charset, Opt_debug, 675 676 }; 676 677 677 - static const match_table_t befs_tokens = { 678 - {Opt_uid, "uid=%d"}, 679 - {Opt_gid, "gid=%d"}, 680 - {Opt_charset, "iocharset=%s"}, 681 - {Opt_debug, "debug"}, 682 - {Opt_err, NULL} 678 + static const struct fs_parameter_spec befs_param_spec[] = { 679 + fsparam_uid ("uid", Opt_uid), 680 + fsparam_gid ("gid", Opt_gid), 681 + fsparam_string ("iocharset", Opt_charset), 682 + fsparam_flag ("debug", Opt_debug), 683 + {} 683 684 }; 684 685 685 686 static int 686 - parse_options(char *options, struct befs_mount_options *opts) 687 + befs_parse_param(struct fs_context *fc, struct fs_parameter *param) 687 688 { 688 - char *p; 689 - substring_t args[MAX_OPT_ARGS]; 690 - int option; 691 - kuid_t uid; 692 - kgid_t gid; 689 + struct befs_mount_options *opts = fc->fs_private; 690 + int token; 691 + struct fs_parse_result result; 693 692 694 - /* Initialize options */ 695 - opts->uid = GLOBAL_ROOT_UID; 696 - opts->gid = GLOBAL_ROOT_GID; 697 - opts->use_uid = 0; 698 - opts->use_gid = 0; 699 - opts->iocharset = NULL; 700 - opts->debug = 0; 693 + /* befs ignores all options on remount */ 694 + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) 695 + return 0; 701 696 702 - if (!options) 703 - return 1; 697 + token = fs_parse(fc, befs_param_spec, param, &result); 698 + if (token < 0) 699 + return token; 704 700 705 - while ((p = strsep(&options, ",")) != NULL) { 706 - int token; 707 - 708 - if (!*p) 709 - continue; 710 - 711 - token = match_token(p, befs_tokens, args); 712 - switch (token) { 713 - case Opt_uid: 714 - if (match_int(&args[0], &option)) 715 - return 0; 716 - uid = INVALID_UID; 717 - if (option >= 0) 718 - uid = make_kuid(current_user_ns(), option); 719 - if (!uid_valid(uid)) { 720 - pr_err("Invalid uid %d, " 721 - "using default\n", option); 722 - break; 723 - } 724 - opts->uid = uid; 725 - opts->use_uid = 1; 726 - break; 727 - case Opt_gid: 728 - if (match_int(&args[0], &option)) 729 - return 0; 730 - gid = INVALID_GID; 731 - if (option >= 0) 732 - gid = make_kgid(current_user_ns(), option); 733 - if (!gid_valid(gid)) { 734 - pr_err("Invalid gid %d, " 735 - "using default\n", option); 736 - break; 737 - } 738 - opts->gid = gid; 739 - opts->use_gid = 1; 740 - break; 741 - case Opt_charset: 742 - kfree(opts->iocharset); 743 - opts->iocharset = match_strdup(&args[0]); 744 - if (!opts->iocharset) { 745 - pr_err("allocation failure for " 746 - "iocharset string\n"); 747 - return 0; 748 - } 749 - break; 750 - case Opt_debug: 751 - opts->debug = 1; 752 - break; 753 - default: 754 - pr_err("Unrecognized mount option \"%s\" " 755 - "or missing value\n", p); 756 - return 0; 757 - } 701 + switch (token) { 702 + case Opt_uid: 703 + opts->uid = result.uid; 704 + opts->use_uid = 1; 705 + break; 706 + case Opt_gid: 707 + opts->gid = result.gid; 708 + opts->use_gid = 1; 709 + break; 710 + case Opt_charset: 711 + kfree(opts->iocharset); 712 + opts->iocharset = param->string; 713 + param->string = NULL; 714 + break; 715 + case Opt_debug: 716 + opts->debug = 1; 717 + break; 718 + default: 719 + return -EINVAL; 758 720 } 759 - return 1; 721 + return 0; 760 722 } 761 723 762 724 static int befs_show_options(struct seq_file *m, struct dentry *root) ··· 753 793 sb->s_fs_info = NULL; 754 794 } 755 795 796 + /* 797 + * Copy the parsed options into the sbi mount_options member 798 + */ 799 + static void 800 + befs_set_options(struct befs_sb_info *sbi, struct befs_mount_options *opts) 801 + { 802 + sbi->mount_opts.uid = opts->uid; 803 + sbi->mount_opts.gid = opts->gid; 804 + sbi->mount_opts.use_uid = opts->use_uid; 805 + sbi->mount_opts.use_gid = opts->use_gid; 806 + sbi->mount_opts.debug = opts->debug; 807 + sbi->mount_opts.iocharset = opts->iocharset; 808 + opts->iocharset = NULL; 809 + } 810 + 756 811 /* Allocate private field of the superblock, fill it. 757 812 * 758 813 * Finish filling the public superblock fields ··· 775 800 * Load a set of NLS translations if needed. 776 801 */ 777 802 static int 778 - befs_fill_super(struct super_block *sb, void *data, int silent) 803 + befs_fill_super(struct super_block *sb, struct fs_context *fc) 779 804 { 780 805 struct buffer_head *bh; 781 806 struct befs_sb_info *befs_sb; ··· 785 810 const unsigned long sb_block = 0; 786 811 const off_t x86_sb_off = 512; 787 812 int blocksize; 813 + struct befs_mount_options *parsed_opts = fc->fs_private; 814 + int silent = fc->sb_flags & SB_SILENT; 788 815 789 816 sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL); 790 817 if (sb->s_fs_info == NULL) ··· 794 817 795 818 befs_sb = BEFS_SB(sb); 796 819 797 - if (!parse_options((char *) data, &befs_sb->mount_opts)) { 798 - if (!silent) 799 - befs_error(sb, "cannot parse mount options"); 800 - goto unacquire_priv_sbp; 801 - } 820 + befs_set_options(befs_sb, parsed_opts); 802 821 803 822 befs_debug(sb, "---> %s", __func__); 804 823 ··· 907 934 } 908 935 909 936 static int 910 - befs_remount(struct super_block *sb, int *flags, char *data) 937 + befs_reconfigure(struct fs_context *fc) 911 938 { 912 - sync_filesystem(sb); 913 - if (!(*flags & SB_RDONLY)) 939 + sync_filesystem(fc->root->d_sb); 940 + if (!(fc->sb_flags & SB_RDONLY)) 914 941 return -EINVAL; 915 942 return 0; 916 943 } ··· 938 965 return 0; 939 966 } 940 967 941 - static struct dentry * 942 - befs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, 943 - void *data) 968 + static int befs_get_tree(struct fs_context *fc) 944 969 { 945 - return mount_bdev(fs_type, flags, dev_name, data, befs_fill_super); 970 + return get_tree_bdev(fc, befs_fill_super); 971 + } 972 + 973 + static const struct fs_context_operations befs_context_ops = { 974 + .parse_param = befs_parse_param, 975 + .get_tree = befs_get_tree, 976 + .reconfigure = befs_reconfigure, 977 + .free = befs_free_fc, 978 + }; 979 + 980 + static int befs_init_fs_context(struct fs_context *fc) 981 + { 982 + struct befs_mount_options *opts; 983 + 984 + opts = kzalloc(sizeof(*opts), GFP_KERNEL); 985 + if (!opts) 986 + return -ENOMEM; 987 + 988 + /* Initialize options */ 989 + opts->uid = GLOBAL_ROOT_UID; 990 + opts->gid = GLOBAL_ROOT_GID; 991 + 992 + fc->fs_private = opts; 993 + fc->ops = &befs_context_ops; 994 + 995 + return 0; 996 + } 997 + 998 + static void befs_free_fc(struct fs_context *fc) 999 + { 1000 + struct befs_mount_options *opts = fc->fs_private; 1001 + 1002 + kfree(opts->iocharset); 1003 + kfree(fc->fs_private); 946 1004 } 947 1005 948 1006 static struct file_system_type befs_fs_type = { 949 1007 .owner = THIS_MODULE, 950 1008 .name = "befs", 951 - .mount = befs_mount, 952 1009 .kill_sb = kill_block_super, 953 1010 .fs_flags = FS_REQUIRES_DEV, 1011 + .init_fs_context = befs_init_fs_context, 1012 + .parameters = befs_param_spec, 954 1013 }; 955 1014 MODULE_ALIAS_FS("befs"); 956 1015
+152 -184
fs/hfs/super.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/blkdev.h> 17 17 #include <linux/backing-dev.h> 18 + #include <linux/fs_context.h> 19 + #include <linux/fs_parser.h> 18 20 #include <linux/mount.h> 19 21 #include <linux/init.h> 20 22 #include <linux/nls.h> 21 - #include <linux/parser.h> 22 23 #include <linux/seq_file.h> 23 24 #include <linux/slab.h> 24 25 #include <linux/vfs.h> ··· 112 111 return 0; 113 112 } 114 113 115 - static int hfs_remount(struct super_block *sb, int *flags, char *data) 114 + static int hfs_reconfigure(struct fs_context *fc) 116 115 { 116 + struct super_block *sb = fc->root->d_sb; 117 + 117 118 sync_filesystem(sb); 118 - *flags |= SB_NODIRATIME; 119 - if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb)) 119 + fc->sb_flags |= SB_NODIRATIME; 120 + if ((bool)(fc->sb_flags & SB_RDONLY) == sb_rdonly(sb)) 120 121 return 0; 121 - if (!(*flags & SB_RDONLY)) { 122 + 123 + if (!(fc->sb_flags & SB_RDONLY)) { 122 124 if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) { 123 125 pr_warn("filesystem was not cleanly unmounted, running fsck.hfs is recommended. leaving read-only.\n"); 124 126 sb->s_flags |= SB_RDONLY; 125 - *flags |= SB_RDONLY; 127 + fc->sb_flags |= SB_RDONLY; 126 128 } else if (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_SLOCK)) { 127 129 pr_warn("filesystem is marked locked, leaving read-only.\n"); 128 130 sb->s_flags |= SB_RDONLY; 129 - *flags |= SB_RDONLY; 131 + fc->sb_flags |= SB_RDONLY; 130 132 } 131 133 } 132 134 return 0; ··· 184 180 .put_super = hfs_put_super, 185 181 .sync_fs = hfs_sync_fs, 186 182 .statfs = hfs_statfs, 187 - .remount_fs = hfs_remount, 188 183 .show_options = hfs_show_options, 189 184 }; 190 185 ··· 191 188 opt_uid, opt_gid, opt_umask, opt_file_umask, opt_dir_umask, 192 189 opt_part, opt_session, opt_type, opt_creator, opt_quiet, 193 190 opt_codepage, opt_iocharset, 194 - opt_err 195 191 }; 196 192 197 - static const match_table_t tokens = { 198 - { opt_uid, "uid=%u" }, 199 - { opt_gid, "gid=%u" }, 200 - { opt_umask, "umask=%o" }, 201 - { opt_file_umask, "file_umask=%o" }, 202 - { opt_dir_umask, "dir_umask=%o" }, 203 - { opt_part, "part=%u" }, 204 - { opt_session, "session=%u" }, 205 - { opt_type, "type=%s" }, 206 - { opt_creator, "creator=%s" }, 207 - { opt_quiet, "quiet" }, 208 - { opt_codepage, "codepage=%s" }, 209 - { opt_iocharset, "iocharset=%s" }, 210 - { opt_err, NULL } 193 + static const struct fs_parameter_spec hfs_param_spec[] = { 194 + fsparam_u32 ("uid", opt_uid), 195 + fsparam_u32 ("gid", opt_gid), 196 + fsparam_u32oct ("umask", opt_umask), 197 + fsparam_u32oct ("file_umask", opt_file_umask), 198 + fsparam_u32oct ("dir_umask", opt_dir_umask), 199 + fsparam_u32 ("part", opt_part), 200 + fsparam_u32 ("session", opt_session), 201 + fsparam_string ("type", opt_type), 202 + fsparam_string ("creator", opt_creator), 203 + fsparam_flag ("quiet", opt_quiet), 204 + fsparam_string ("codepage", opt_codepage), 205 + fsparam_string ("iocharset", opt_iocharset), 206 + {} 211 207 }; 212 - 213 - static inline int match_fourchar(substring_t *arg, u32 *result) 214 - { 215 - if (arg->to - arg->from != 4) 216 - return -EINVAL; 217 - memcpy(result, arg->from, 4); 218 - return 0; 219 - } 220 208 221 209 /* 222 - * parse_options() 210 + * hfs_parse_param() 223 211 * 224 - * adapted from linux/fs/msdos/inode.c written 1992,93 by Werner Almesberger 225 - * This function is called by hfs_read_super() to parse the mount options. 212 + * This function is called by the vfs to parse the mount options. 226 213 */ 227 - static int parse_options(char *options, struct hfs_sb_info *hsb) 214 + static int hfs_parse_param(struct fs_context *fc, struct fs_parameter *param) 228 215 { 229 - char *p; 230 - substring_t args[MAX_OPT_ARGS]; 231 - int tmp, token; 216 + struct hfs_sb_info *hsb = fc->s_fs_info; 217 + struct fs_parse_result result; 218 + int opt; 232 219 233 - /* initialize the sb with defaults */ 234 - hsb->s_uid = current_uid(); 235 - hsb->s_gid = current_gid(); 236 - hsb->s_file_umask = 0133; 237 - hsb->s_dir_umask = 0022; 238 - hsb->s_type = hsb->s_creator = cpu_to_be32(0x3f3f3f3f); /* == '????' */ 239 - hsb->s_quiet = 0; 240 - hsb->part = -1; 241 - hsb->session = -1; 220 + /* hfs does not honor any fs-specific options on remount */ 221 + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) 222 + return 0; 242 223 243 - if (!options) 244 - return 1; 224 + opt = fs_parse(fc, hfs_param_spec, param, &result); 225 + if (opt < 0) 226 + return opt; 245 227 246 - while ((p = strsep(&options, ",")) != NULL) { 247 - if (!*p) 248 - continue; 249 - 250 - token = match_token(p, tokens, args); 251 - switch (token) { 252 - case opt_uid: 253 - if (match_int(&args[0], &tmp)) { 254 - pr_err("uid requires an argument\n"); 255 - return 0; 256 - } 257 - hsb->s_uid = make_kuid(current_user_ns(), (uid_t)tmp); 258 - if (!uid_valid(hsb->s_uid)) { 259 - pr_err("invalid uid %d\n", tmp); 260 - return 0; 261 - } 262 - break; 263 - case opt_gid: 264 - if (match_int(&args[0], &tmp)) { 265 - pr_err("gid requires an argument\n"); 266 - return 0; 267 - } 268 - hsb->s_gid = make_kgid(current_user_ns(), (gid_t)tmp); 269 - if (!gid_valid(hsb->s_gid)) { 270 - pr_err("invalid gid %d\n", tmp); 271 - return 0; 272 - } 273 - break; 274 - case opt_umask: 275 - if (match_octal(&args[0], &tmp)) { 276 - pr_err("umask requires a value\n"); 277 - return 0; 278 - } 279 - hsb->s_file_umask = (umode_t)tmp; 280 - hsb->s_dir_umask = (umode_t)tmp; 281 - break; 282 - case opt_file_umask: 283 - if (match_octal(&args[0], &tmp)) { 284 - pr_err("file_umask requires a value\n"); 285 - return 0; 286 - } 287 - hsb->s_file_umask = (umode_t)tmp; 288 - break; 289 - case opt_dir_umask: 290 - if (match_octal(&args[0], &tmp)) { 291 - pr_err("dir_umask requires a value\n"); 292 - return 0; 293 - } 294 - hsb->s_dir_umask = (umode_t)tmp; 295 - break; 296 - case opt_part: 297 - if (match_int(&args[0], &hsb->part)) { 298 - pr_err("part requires an argument\n"); 299 - return 0; 300 - } 301 - break; 302 - case opt_session: 303 - if (match_int(&args[0], &hsb->session)) { 304 - pr_err("session requires an argument\n"); 305 - return 0; 306 - } 307 - break; 308 - case opt_type: 309 - if (match_fourchar(&args[0], &hsb->s_type)) { 310 - pr_err("type requires a 4 character value\n"); 311 - return 0; 312 - } 313 - break; 314 - case opt_creator: 315 - if (match_fourchar(&args[0], &hsb->s_creator)) { 316 - pr_err("creator requires a 4 character value\n"); 317 - return 0; 318 - } 319 - break; 320 - case opt_quiet: 321 - hsb->s_quiet = 1; 322 - break; 323 - case opt_codepage: 324 - if (hsb->nls_disk) { 325 - pr_err("unable to change codepage\n"); 326 - return 0; 327 - } 328 - p = match_strdup(&args[0]); 329 - if (p) 330 - hsb->nls_disk = load_nls(p); 331 - if (!hsb->nls_disk) { 332 - pr_err("unable to load codepage \"%s\"\n", p); 333 - kfree(p); 334 - return 0; 335 - } 336 - kfree(p); 337 - break; 338 - case opt_iocharset: 339 - if (hsb->nls_io) { 340 - pr_err("unable to change iocharset\n"); 341 - return 0; 342 - } 343 - p = match_strdup(&args[0]); 344 - if (p) 345 - hsb->nls_io = load_nls(p); 346 - if (!hsb->nls_io) { 347 - pr_err("unable to load iocharset \"%s\"\n", p); 348 - kfree(p); 349 - return 0; 350 - } 351 - kfree(p); 352 - break; 353 - default: 354 - return 0; 228 + switch (opt) { 229 + case opt_uid: 230 + hsb->s_uid = result.uid; 231 + break; 232 + case opt_gid: 233 + hsb->s_gid = result.gid; 234 + break; 235 + case opt_umask: 236 + hsb->s_file_umask = (umode_t)result.uint_32; 237 + hsb->s_dir_umask = (umode_t)result.uint_32; 238 + break; 239 + case opt_file_umask: 240 + hsb->s_file_umask = (umode_t)result.uint_32; 241 + break; 242 + case opt_dir_umask: 243 + hsb->s_dir_umask = (umode_t)result.uint_32; 244 + break; 245 + case opt_part: 246 + hsb->part = result.uint_32; 247 + break; 248 + case opt_session: 249 + hsb->session = result.uint_32; 250 + break; 251 + case opt_type: 252 + if (strlen(param->string) != 4) { 253 + pr_err("type requires a 4 character value\n"); 254 + return -EINVAL; 355 255 } 356 - } 357 - 358 - if (hsb->nls_disk && !hsb->nls_io) { 359 - hsb->nls_io = load_nls_default(); 256 + memcpy(&hsb->s_type, param->string, 4); 257 + break; 258 + case opt_creator: 259 + if (strlen(param->string) != 4) { 260 + pr_err("creator requires a 4 character value\n"); 261 + return -EINVAL; 262 + } 263 + memcpy(&hsb->s_creator, param->string, 4); 264 + break; 265 + case opt_quiet: 266 + hsb->s_quiet = 1; 267 + break; 268 + case opt_codepage: 269 + if (hsb->nls_disk) { 270 + pr_err("unable to change codepage\n"); 271 + return -EINVAL; 272 + } 273 + hsb->nls_disk = load_nls(param->string); 274 + if (!hsb->nls_disk) { 275 + pr_err("unable to load codepage \"%s\"\n", 276 + param->string); 277 + return -EINVAL; 278 + } 279 + break; 280 + case opt_iocharset: 281 + if (hsb->nls_io) { 282 + pr_err("unable to change iocharset\n"); 283 + return -EINVAL; 284 + } 285 + hsb->nls_io = load_nls(param->string); 360 286 if (!hsb->nls_io) { 361 - pr_err("unable to load default iocharset\n"); 362 - return 0; 287 + pr_err("unable to load iocharset \"%s\"\n", 288 + param->string); 289 + return -EINVAL; 363 290 } 291 + break; 292 + default: 293 + return -EINVAL; 364 294 } 365 - hsb->s_dir_umask &= 0777; 366 - hsb->s_file_umask &= 0577; 367 295 368 - return 1; 296 + return 0; 369 297 } 370 298 371 299 /* ··· 310 376 * hfs_btree_init() to get the necessary data about the extents and 311 377 * catalog B-trees and, finally, reading the root inode into memory. 312 378 */ 313 - static int hfs_fill_super(struct super_block *sb, void *data, int silent) 379 + static int hfs_fill_super(struct super_block *sb, struct fs_context *fc) 314 380 { 315 - struct hfs_sb_info *sbi; 381 + struct hfs_sb_info *sbi = HFS_SB(sb); 316 382 struct hfs_find_data fd; 317 383 hfs_cat_rec rec; 318 384 struct inode *root_inode; 385 + int silent = fc->sb_flags & SB_SILENT; 319 386 int res; 320 387 321 - sbi = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL); 322 - if (!sbi) 323 - return -ENOMEM; 388 + /* load_nls_default does not fail */ 389 + if (sbi->nls_disk && !sbi->nls_io) 390 + sbi->nls_io = load_nls_default(); 391 + sbi->s_dir_umask &= 0777; 392 + sbi->s_file_umask &= 0577; 324 393 325 - sbi->sb = sb; 326 - sb->s_fs_info = sbi; 327 394 spin_lock_init(&sbi->work_lock); 328 395 INIT_DELAYED_WORK(&sbi->mdb_work, flush_mdb); 329 396 330 - res = -EINVAL; 331 - if (!parse_options((char *)data, sbi)) { 332 - pr_err("unable to parse mount options\n"); 333 - goto bail; 334 - } 335 - 397 + sbi->sb = sb; 336 398 sb->s_op = &hfs_super_operations; 337 399 sb->s_xattr = hfs_xattr_handlers; 338 400 sb->s_flags |= SB_NODIRATIME; ··· 381 451 return res; 382 452 } 383 453 384 - static struct dentry *hfs_mount(struct file_system_type *fs_type, 385 - int flags, const char *dev_name, void *data) 454 + static int hfs_get_tree(struct fs_context *fc) 386 455 { 387 - return mount_bdev(fs_type, flags, dev_name, data, hfs_fill_super); 456 + return get_tree_bdev(fc, hfs_fill_super); 457 + } 458 + 459 + static void hfs_free_fc(struct fs_context *fc) 460 + { 461 + kfree(fc->s_fs_info); 462 + } 463 + 464 + static const struct fs_context_operations hfs_context_ops = { 465 + .parse_param = hfs_parse_param, 466 + .get_tree = hfs_get_tree, 467 + .reconfigure = hfs_reconfigure, 468 + .free = hfs_free_fc, 469 + }; 470 + 471 + static int hfs_init_fs_context(struct fs_context *fc) 472 + { 473 + struct hfs_sb_info *hsb; 474 + 475 + hsb = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL); 476 + if (!hsb) 477 + return -ENOMEM; 478 + 479 + fc->s_fs_info = hsb; 480 + fc->ops = &hfs_context_ops; 481 + 482 + if (fc->purpose != FS_CONTEXT_FOR_RECONFIGURE) { 483 + /* initialize options with defaults */ 484 + hsb->s_uid = current_uid(); 485 + hsb->s_gid = current_gid(); 486 + hsb->s_file_umask = 0133; 487 + hsb->s_dir_umask = 0022; 488 + hsb->s_type = cpu_to_be32(0x3f3f3f3f); /* == '????' */ 489 + hsb->s_creator = cpu_to_be32(0x3f3f3f3f); /* == '????' */ 490 + hsb->s_quiet = 0; 491 + hsb->part = -1; 492 + hsb->session = -1; 493 + } 494 + 495 + return 0; 388 496 } 389 497 390 498 static struct file_system_type hfs_fs_type = { 391 499 .owner = THIS_MODULE, 392 500 .name = "hfs", 393 - .mount = hfs_mount, 394 501 .kill_sb = kill_block_super, 395 502 .fs_flags = FS_REQUIRES_DEV, 503 + .init_fs_context = hfs_init_fs_context, 396 504 }; 397 505 MODULE_ALIAS_FS("hfs"); 398 506
+2 -2
fs/hfsplus/hfsplus_fs.h
··· 21 21 #include <linux/mutex.h> 22 22 #include <linux/buffer_head.h> 23 23 #include <linux/blkdev.h> 24 + #include <linux/fs_context.h> 24 25 #include "hfsplus_raw.h" 25 26 26 27 #define DBG_BNODE_REFS 0x00000001 ··· 497 496 498 497 /* options.c */ 499 498 void hfsplus_fill_defaults(struct hfsplus_sb_info *opts); 500 - int hfsplus_parse_options_remount(char *input, int *force); 501 - int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi); 499 + int hfsplus_parse_param(struct fs_context *fc, struct fs_parameter *param); 502 500 int hfsplus_show_options(struct seq_file *seq, struct dentry *root); 503 501 504 502 /* part_tbl.c */
+91 -166
fs/hfsplus/options.c
··· 12 12 #include <linux/string.h> 13 13 #include <linux/kernel.h> 14 14 #include <linux/sched.h> 15 - #include <linux/parser.h> 15 + #include <linux/fs_context.h> 16 + #include <linux/fs_parser.h> 16 17 #include <linux/nls.h> 17 18 #include <linux/mount.h> 18 19 #include <linux/seq_file.h> ··· 24 23 opt_creator, opt_type, 25 24 opt_umask, opt_uid, opt_gid, 26 25 opt_part, opt_session, opt_nls, 27 - opt_nodecompose, opt_decompose, 28 - opt_barrier, opt_nobarrier, 29 - opt_force, opt_err 26 + opt_decompose, opt_barrier, 27 + opt_force, 30 28 }; 31 29 32 - static const match_table_t tokens = { 33 - { opt_creator, "creator=%s" }, 34 - { opt_type, "type=%s" }, 35 - { opt_umask, "umask=%o" }, 36 - { opt_uid, "uid=%u" }, 37 - { opt_gid, "gid=%u" }, 38 - { opt_part, "part=%u" }, 39 - { opt_session, "session=%u" }, 40 - { opt_nls, "nls=%s" }, 41 - { opt_decompose, "decompose" }, 42 - { opt_nodecompose, "nodecompose" }, 43 - { opt_barrier, "barrier" }, 44 - { opt_nobarrier, "nobarrier" }, 45 - { opt_force, "force" }, 46 - { opt_err, NULL } 30 + static const struct fs_parameter_spec hfs_param_spec[] = { 31 + fsparam_string ("creator", opt_creator), 32 + fsparam_string ("type", opt_type), 33 + fsparam_u32oct ("umask", opt_umask), 34 + fsparam_u32 ("uid", opt_uid), 35 + fsparam_u32 ("gid", opt_gid), 36 + fsparam_u32 ("part", opt_part), 37 + fsparam_u32 ("session", opt_session), 38 + fsparam_string ("nls", opt_nls), 39 + fsparam_flag_no ("decompose", opt_decompose), 40 + fsparam_flag_no ("barrier", opt_barrier), 41 + fsparam_flag ("force", opt_force), 42 + {} 47 43 }; 48 44 49 45 /* Initialize an options object to reasonable defaults */ ··· 58 60 opts->session = -1; 59 61 } 60 62 61 - /* convert a "four byte character" to a 32 bit int with error checks */ 62 - static inline int match_fourchar(substring_t *arg, u32 *result) 63 + /* Parse options from mount. Returns nonzero errno on failure */ 64 + int hfsplus_parse_param(struct fs_context *fc, struct fs_parameter *param) 63 65 { 64 - if (arg->to - arg->from != 4) 65 - return -EINVAL; 66 - memcpy(result, arg->from, 4); 67 - return 0; 68 - } 66 + struct hfsplus_sb_info *sbi = fc->s_fs_info; 67 + struct fs_parse_result result; 68 + int opt; 69 69 70 - int hfsplus_parse_options_remount(char *input, int *force) 71 - { 72 - char *p; 73 - substring_t args[MAX_OPT_ARGS]; 74 - int token; 70 + /* 71 + * Only the force option is examined during remount, all others 72 + * are ignored. 73 + */ 74 + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE && 75 + strncmp(param->key, "force", 5)) 76 + return 0; 75 77 76 - if (!input) 77 - return 1; 78 + opt = fs_parse(fc, hfs_param_spec, param, &result); 79 + if (opt < 0) 80 + return opt; 78 81 79 - while ((p = strsep(&input, ",")) != NULL) { 80 - if (!*p) 81 - continue; 82 - 83 - token = match_token(p, tokens, args); 84 - switch (token) { 85 - case opt_force: 86 - *force = 1; 87 - break; 88 - default: 89 - break; 82 + switch (opt) { 83 + case opt_creator: 84 + if (strlen(param->string) != 4) { 85 + pr_err("creator requires a 4 character value\n"); 86 + return -EINVAL; 90 87 } 91 - } 92 - 93 - return 1; 94 - } 95 - 96 - /* Parse options from mount. Returns 0 on failure */ 97 - /* input is the options passed to mount() as a string */ 98 - int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) 99 - { 100 - char *p; 101 - substring_t args[MAX_OPT_ARGS]; 102 - int tmp, token; 103 - 104 - if (!input) 105 - goto done; 106 - 107 - while ((p = strsep(&input, ",")) != NULL) { 108 - if (!*p) 109 - continue; 110 - 111 - token = match_token(p, tokens, args); 112 - switch (token) { 113 - case opt_creator: 114 - if (match_fourchar(&args[0], &sbi->creator)) { 115 - pr_err("creator requires a 4 character value\n"); 116 - return 0; 117 - } 118 - break; 119 - case opt_type: 120 - if (match_fourchar(&args[0], &sbi->type)) { 121 - pr_err("type requires a 4 character value\n"); 122 - return 0; 123 - } 124 - break; 125 - case opt_umask: 126 - if (match_octal(&args[0], &tmp)) { 127 - pr_err("umask requires a value\n"); 128 - return 0; 129 - } 130 - sbi->umask = (umode_t)tmp; 131 - break; 132 - case opt_uid: 133 - if (match_int(&args[0], &tmp)) { 134 - pr_err("uid requires an argument\n"); 135 - return 0; 136 - } 137 - sbi->uid = make_kuid(current_user_ns(), (uid_t)tmp); 138 - if (!uid_valid(sbi->uid)) { 139 - pr_err("invalid uid specified\n"); 140 - return 0; 141 - } else { 142 - set_bit(HFSPLUS_SB_UID, &sbi->flags); 143 - } 144 - break; 145 - case opt_gid: 146 - if (match_int(&args[0], &tmp)) { 147 - pr_err("gid requires an argument\n"); 148 - return 0; 149 - } 150 - sbi->gid = make_kgid(current_user_ns(), (gid_t)tmp); 151 - if (!gid_valid(sbi->gid)) { 152 - pr_err("invalid gid specified\n"); 153 - return 0; 154 - } else { 155 - set_bit(HFSPLUS_SB_GID, &sbi->flags); 156 - } 157 - break; 158 - case opt_part: 159 - if (match_int(&args[0], &sbi->part)) { 160 - pr_err("part requires an argument\n"); 161 - return 0; 162 - } 163 - break; 164 - case opt_session: 165 - if (match_int(&args[0], &sbi->session)) { 166 - pr_err("session requires an argument\n"); 167 - return 0; 168 - } 169 - break; 170 - case opt_nls: 171 - if (sbi->nls) { 172 - pr_err("unable to change nls mapping\n"); 173 - return 0; 174 - } 175 - p = match_strdup(&args[0]); 176 - if (p) 177 - sbi->nls = load_nls(p); 178 - if (!sbi->nls) { 179 - pr_err("unable to load nls mapping \"%s\"\n", 180 - p); 181 - kfree(p); 182 - return 0; 183 - } 184 - kfree(p); 185 - break; 186 - case opt_decompose: 187 - clear_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags); 188 - break; 189 - case opt_nodecompose: 88 + memcpy(&sbi->creator, param->string, 4); 89 + break; 90 + case opt_type: 91 + if (strlen(param->string) != 4) { 92 + pr_err("type requires a 4 character value\n"); 93 + return -EINVAL; 94 + } 95 + memcpy(&sbi->type, param->string, 4); 96 + break; 97 + case opt_umask: 98 + sbi->umask = (umode_t)result.uint_32; 99 + break; 100 + case opt_uid: 101 + sbi->uid = result.uid; 102 + set_bit(HFSPLUS_SB_UID, &sbi->flags); 103 + break; 104 + case opt_gid: 105 + sbi->gid = result.gid; 106 + set_bit(HFSPLUS_SB_GID, &sbi->flags); 107 + break; 108 + case opt_part: 109 + sbi->part = result.uint_32; 110 + break; 111 + case opt_session: 112 + sbi->session = result.uint_32; 113 + break; 114 + case opt_nls: 115 + if (sbi->nls) { 116 + pr_err("unable to change nls mapping\n"); 117 + return -EINVAL; 118 + } 119 + sbi->nls = load_nls(param->string); 120 + if (!sbi->nls) { 121 + pr_err("unable to load nls mapping \"%s\"\n", 122 + param->string); 123 + return -EINVAL; 124 + } 125 + break; 126 + case opt_decompose: 127 + if (result.negated) 190 128 set_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags); 191 - break; 192 - case opt_barrier: 193 - clear_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags); 194 - break; 195 - case opt_nobarrier: 129 + else 130 + clear_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags); 131 + break; 132 + case opt_barrier: 133 + if (result.negated) 196 134 set_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags); 197 - break; 198 - case opt_force: 199 - set_bit(HFSPLUS_SB_FORCE, &sbi->flags); 200 - break; 201 - default: 202 - return 0; 203 - } 135 + else 136 + clear_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags); 137 + break; 138 + case opt_force: 139 + set_bit(HFSPLUS_SB_FORCE, &sbi->flags); 140 + break; 141 + default: 142 + return -EINVAL; 204 143 } 205 144 206 - done: 207 - if (!sbi->nls) { 208 - /* try utf8 first, as this is the old default behaviour */ 209 - sbi->nls = load_nls("utf8"); 210 - if (!sbi->nls) 211 - sbi->nls = load_nls_default(); 212 - if (!sbi->nls) 213 - return 0; 214 - } 215 - 216 - return 1; 145 + return 0; 217 146 } 218 147 219 148 int hfsplus_show_options(struct seq_file *seq, struct dentry *root)
+54 -32
fs/hfsplus/super.c
··· 14 14 #include <linux/blkdev.h> 15 15 #include <linux/backing-dev.h> 16 16 #include <linux/fs.h> 17 + #include <linux/fs_context.h> 17 18 #include <linux/slab.h> 18 19 #include <linux/vfs.h> 19 20 #include <linux/nls.h> ··· 333 332 return 0; 334 333 } 335 334 336 - static int hfsplus_remount(struct super_block *sb, int *flags, char *data) 335 + static int hfsplus_reconfigure(struct fs_context *fc) 337 336 { 338 - sync_filesystem(sb); 339 - if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb)) 340 - return 0; 341 - if (!(*flags & SB_RDONLY)) { 342 - struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr; 343 - int force = 0; 337 + struct super_block *sb = fc->root->d_sb; 344 338 345 - if (!hfsplus_parse_options_remount(data, &force)) 346 - return -EINVAL; 339 + sync_filesystem(sb); 340 + if ((bool)(fc->sb_flags & SB_RDONLY) == sb_rdonly(sb)) 341 + return 0; 342 + if (!(fc->sb_flags & SB_RDONLY)) { 343 + struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 344 + struct hfsplus_vh *vhdr = sbi->s_vhdr; 347 345 348 346 if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { 349 347 pr_warn("filesystem was not cleanly unmounted, running fsck.hfsplus is recommended. leaving read-only.\n"); 350 348 sb->s_flags |= SB_RDONLY; 351 - *flags |= SB_RDONLY; 352 - } else if (force) { 349 + fc->sb_flags |= SB_RDONLY; 350 + } else if (test_bit(HFSPLUS_SB_FORCE, &sbi->flags)) { 353 351 /* nothing */ 354 352 } else if (vhdr->attributes & 355 353 cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { 356 354 pr_warn("filesystem is marked locked, leaving read-only.\n"); 357 355 sb->s_flags |= SB_RDONLY; 358 - *flags |= SB_RDONLY; 356 + fc->sb_flags |= SB_RDONLY; 359 357 } else if (vhdr->attributes & 360 358 cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { 361 359 pr_warn("filesystem is marked journaled, leaving read-only.\n"); 362 360 sb->s_flags |= SB_RDONLY; 363 - *flags |= SB_RDONLY; 361 + fc->sb_flags |= SB_RDONLY; 364 362 } 365 363 } 366 364 return 0; ··· 373 373 .put_super = hfsplus_put_super, 374 374 .sync_fs = hfsplus_sync_fs, 375 375 .statfs = hfsplus_statfs, 376 - .remount_fs = hfsplus_remount, 377 376 .show_options = hfsplus_show_options, 378 377 }; 379 378 380 - static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) 379 + static int hfsplus_fill_super(struct super_block *sb, struct fs_context *fc) 381 380 { 382 381 struct hfsplus_vh *vhdr; 383 - struct hfsplus_sb_info *sbi; 382 + struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 384 383 hfsplus_cat_entry entry; 385 384 struct hfs_find_data fd; 386 385 struct inode *root, *inode; 387 386 struct qstr str; 388 - struct nls_table *nls = NULL; 387 + struct nls_table *nls; 389 388 u64 last_fs_block, last_fs_page; 389 + int silent = fc->sb_flags & SB_SILENT; 390 390 int err; 391 391 392 - err = -ENOMEM; 393 - sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); 394 - if (!sbi) 395 - goto out; 396 - 397 - sb->s_fs_info = sbi; 398 392 mutex_init(&sbi->alloc_mutex); 399 393 mutex_init(&sbi->vh_mutex); 400 394 spin_lock_init(&sbi->work_lock); 401 395 INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); 402 - hfsplus_fill_defaults(sbi); 403 396 404 397 err = -EINVAL; 405 - if (!hfsplus_parse_options(data, sbi)) { 406 - pr_err("unable to parse mount options\n"); 407 - goto out_unload_nls; 398 + if (!sbi->nls) { 399 + /* try utf8 first, as this is the old default behaviour */ 400 + sbi->nls = load_nls("utf8"); 401 + if (!sbi->nls) 402 + sbi->nls = load_nls_default(); 408 403 } 409 404 410 405 /* temporarily use utf8 to correctly find the hidden dir below */ ··· 611 616 unload_nls(sbi->nls); 612 617 unload_nls(nls); 613 618 kfree(sbi); 614 - out: 615 619 return err; 616 620 } 617 621 ··· 635 641 636 642 #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) 637 643 638 - static struct dentry *hfsplus_mount(struct file_system_type *fs_type, 639 - int flags, const char *dev_name, void *data) 644 + static int hfsplus_get_tree(struct fs_context *fc) 640 645 { 641 - return mount_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super); 646 + return get_tree_bdev(fc, hfsplus_fill_super); 647 + } 648 + 649 + static void hfsplus_free_fc(struct fs_context *fc) 650 + { 651 + kfree(fc->s_fs_info); 652 + } 653 + 654 + static const struct fs_context_operations hfsplus_context_ops = { 655 + .parse_param = hfsplus_parse_param, 656 + .get_tree = hfsplus_get_tree, 657 + .reconfigure = hfsplus_reconfigure, 658 + .free = hfsplus_free_fc, 659 + }; 660 + 661 + static int hfsplus_init_fs_context(struct fs_context *fc) 662 + { 663 + struct hfsplus_sb_info *sbi; 664 + 665 + sbi = kzalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL); 666 + if (!sbi) 667 + return -ENOMEM; 668 + 669 + if (fc->purpose != FS_CONTEXT_FOR_RECONFIGURE) 670 + hfsplus_fill_defaults(sbi); 671 + 672 + fc->s_fs_info = sbi; 673 + fc->ops = &hfsplus_context_ops; 674 + 675 + return 0; 642 676 } 643 677 644 678 static struct file_system_type hfsplus_fs_type = { 645 679 .owner = THIS_MODULE, 646 680 .name = "hfsplus", 647 - .mount = hfsplus_mount, 648 681 .kill_sb = kill_block_super, 649 682 .fs_flags = FS_REQUIRES_DEV, 683 + .init_fs_context = hfsplus_init_fs_context, 650 684 }; 651 685 MODULE_ALIAS_FS("hfsplus"); 652 686