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

jfs: convert jfs to use the new mount api

Convert the jfs filesystem to use the new mount API.
Tested by comparing random mount & remount options before and after
the change.

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

authored by

Eric Sandeen and committed by
Christian Brauner
945be8ca 5b00a0f9

+245 -221
+1
fs/jfs/jfs_filsys.h
··· 24 24 #define JFS_ERR_REMOUNT_RO 0x00000002 /* remount read-only */ 25 25 #define JFS_ERR_CONTINUE 0x00000004 /* continue */ 26 26 #define JFS_ERR_PANIC 0x00000008 /* panic */ 27 + #define JFS_ERR_MASK (JFS_ERR_REMOUNT_RO|JFS_ERR_CONTINUE|JFS_ERR_PANIC) 27 28 28 29 /* Quota support */ 29 30 #define JFS_USRQUOTA 0x00000010
+244 -221
fs/jfs/super.c
··· 6 6 7 7 #include <linux/fs.h> 8 8 #include <linux/module.h> 9 - #include <linux/parser.h> 10 9 #include <linux/completion.h> 11 10 #include <linux/vfs.h> 12 11 #include <linux/quotaops.h> 13 - #include <linux/mount.h> 12 + #include <linux/fs_context.h> 13 + #include <linux/fs_parser.h> 14 14 #include <linux/moduleparam.h> 15 15 #include <linux/kthread.h> 16 16 #include <linux/posix_acl.h> ··· 210 210 Opt_discard, Opt_nodiscard, Opt_discard_minblk 211 211 }; 212 212 213 - static const match_table_t tokens = { 214 - {Opt_integrity, "integrity"}, 215 - {Opt_nointegrity, "nointegrity"}, 216 - {Opt_iocharset, "iocharset=%s"}, 217 - {Opt_resize, "resize=%u"}, 218 - {Opt_resize_nosize, "resize"}, 219 - {Opt_errors, "errors=%s"}, 220 - {Opt_ignore, "noquota"}, 221 - {Opt_quota, "quota"}, 222 - {Opt_usrquota, "usrquota"}, 223 - {Opt_grpquota, "grpquota"}, 224 - {Opt_uid, "uid=%u"}, 225 - {Opt_gid, "gid=%u"}, 226 - {Opt_umask, "umask=%u"}, 227 - {Opt_discard, "discard"}, 228 - {Opt_nodiscard, "nodiscard"}, 229 - {Opt_discard_minblk, "discard=%u"}, 230 - {Opt_err, NULL} 213 + static const struct constant_table jfs_param_errors[] = { 214 + {"continue", JFS_ERR_CONTINUE}, 215 + {"remount-ro", JFS_ERR_REMOUNT_RO}, 216 + {"panic", JFS_ERR_PANIC}, 217 + {} 231 218 }; 232 219 233 - static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, 234 - int *flag) 220 + static const struct fs_parameter_spec jfs_param_spec[] = { 221 + fsparam_flag_no ("integrity", Opt_integrity), 222 + fsparam_string ("iocharset", Opt_iocharset), 223 + fsparam_u64 ("resize", Opt_resize), 224 + fsparam_flag ("resize", Opt_resize_nosize), 225 + fsparam_enum ("errors", Opt_errors, jfs_param_errors), 226 + fsparam_flag ("quota", Opt_quota), 227 + fsparam_flag ("noquota", Opt_ignore), 228 + fsparam_flag ("usrquota", Opt_usrquota), 229 + fsparam_flag ("grpquota", Opt_grpquota), 230 + fsparam_uid ("uid", Opt_uid), 231 + fsparam_gid ("gid", Opt_gid), 232 + fsparam_u32oct ("umask", Opt_umask), 233 + fsparam_flag ("discard", Opt_discard), 234 + fsparam_u32 ("discard", Opt_discard_minblk), 235 + fsparam_flag ("nodiscard", Opt_nodiscard), 236 + {} 237 + }; 238 + 239 + struct jfs_context { 240 + int flag; 241 + kuid_t uid; 242 + kgid_t gid; 243 + uint umask; 244 + uint minblks_trim; 245 + void *nls_map; 246 + bool resize; 247 + s64 newLVSize; 248 + }; 249 + 250 + static int jfs_parse_param(struct fs_context *fc, struct fs_parameter *param) 235 251 { 236 - void *nls_map = (void *)-1; /* -1: no change; NULL: none */ 237 - char *p; 238 - struct jfs_sb_info *sbi = JFS_SBI(sb); 252 + struct jfs_context *ctx = fc->fs_private; 253 + int reconfigure = (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE); 254 + struct fs_parse_result result; 255 + struct nls_table *nls_map; 256 + int opt; 239 257 240 - *newLVSize = 0; 258 + opt = fs_parse(fc, jfs_param_spec, param, &result); 259 + if (opt < 0) 260 + return opt; 241 261 242 - if (!options) 243 - return 1; 244 - 245 - while ((p = strsep(&options, ",")) != NULL) { 246 - substring_t args[MAX_OPT_ARGS]; 247 - int token; 248 - if (!*p) 249 - continue; 250 - 251 - token = match_token(p, tokens, args); 252 - switch (token) { 253 - case Opt_integrity: 254 - *flag &= ~JFS_NOINTEGRITY; 255 - break; 256 - case Opt_nointegrity: 257 - *flag |= JFS_NOINTEGRITY; 258 - break; 259 - case Opt_ignore: 260 - /* Silently ignore the quota options */ 261 - /* Don't do anything ;-) */ 262 - break; 263 - case Opt_iocharset: 264 - if (nls_map && nls_map != (void *) -1) 265 - unload_nls(nls_map); 266 - if (!strcmp(args[0].from, "none")) 267 - nls_map = NULL; 268 - else { 269 - nls_map = load_nls(args[0].from); 270 - if (!nls_map) { 271 - pr_err("JFS: charset not found\n"); 272 - goto cleanup; 273 - } 262 + switch (opt) { 263 + case Opt_integrity: 264 + if (result.negated) 265 + ctx->flag |= JFS_NOINTEGRITY; 266 + else 267 + ctx->flag &= ~JFS_NOINTEGRITY; 268 + break; 269 + case Opt_ignore: 270 + /* Silently ignore the quota options */ 271 + /* Don't do anything ;-) */ 272 + break; 273 + case Opt_iocharset: 274 + if (ctx->nls_map && ctx->nls_map != (void *) -1) { 275 + unload_nls(ctx->nls_map); 276 + ctx->nls_map = NULL; 277 + } 278 + if (!strcmp(param->string, "none")) 279 + ctx->nls_map = NULL; 280 + else { 281 + nls_map = load_nls(param->string); 282 + if (!nls_map) { 283 + pr_err("JFS: charset not found\n"); 284 + return -EINVAL; 274 285 } 275 - break; 276 - case Opt_resize: 277 - { 278 - char *resize = args[0].from; 279 - int rc = kstrtoll(resize, 0, newLVSize); 280 - 281 - if (rc) 282 - goto cleanup; 283 - break; 286 + ctx->nls_map = nls_map; 284 287 } 285 - case Opt_resize_nosize: 286 - { 287 - *newLVSize = sb_bdev_nr_blocks(sb); 288 - if (*newLVSize == 0) 289 - pr_err("JFS: Cannot determine volume size\n"); 290 - break; 291 - } 292 - case Opt_errors: 293 - { 294 - char *errors = args[0].from; 295 - if (!errors || !*errors) 296 - goto cleanup; 297 - if (!strcmp(errors, "continue")) { 298 - *flag &= ~JFS_ERR_REMOUNT_RO; 299 - *flag &= ~JFS_ERR_PANIC; 300 - *flag |= JFS_ERR_CONTINUE; 301 - } else if (!strcmp(errors, "remount-ro")) { 302 - *flag &= ~JFS_ERR_CONTINUE; 303 - *flag &= ~JFS_ERR_PANIC; 304 - *flag |= JFS_ERR_REMOUNT_RO; 305 - } else if (!strcmp(errors, "panic")) { 306 - *flag &= ~JFS_ERR_CONTINUE; 307 - *flag &= ~JFS_ERR_REMOUNT_RO; 308 - *flag |= JFS_ERR_PANIC; 309 - } else { 310 - pr_err("JFS: %s is an invalid error handler\n", 311 - errors); 312 - goto cleanup; 313 - } 314 - break; 315 - } 288 + break; 289 + case Opt_resize: 290 + if (!reconfigure) 291 + return -EINVAL; 292 + ctx->resize = true; 293 + ctx->newLVSize = result.uint_64; 294 + break; 295 + case Opt_resize_nosize: 296 + if (!reconfigure) 297 + return -EINVAL; 298 + ctx->resize = true; 299 + break; 300 + case Opt_errors: 301 + ctx->flag &= ~JFS_ERR_MASK; 302 + ctx->flag |= result.uint_32; 303 + break; 316 304 317 305 #ifdef CONFIG_QUOTA 318 - case Opt_quota: 319 - case Opt_usrquota: 320 - *flag |= JFS_USRQUOTA; 321 - break; 322 - case Opt_grpquota: 323 - *flag |= JFS_GRPQUOTA; 324 - break; 306 + case Opt_quota: 307 + case Opt_usrquota: 308 + ctx->flag |= JFS_USRQUOTA; 309 + break; 310 + case Opt_grpquota: 311 + ctx->flag |= JFS_GRPQUOTA; 312 + break; 325 313 #else 326 - case Opt_usrquota: 327 - case Opt_grpquota: 328 - case Opt_quota: 329 - pr_err("JFS: quota operations not supported\n"); 330 - break; 314 + case Opt_usrquota: 315 + case Opt_grpquota: 316 + case Opt_quota: 317 + pr_err("JFS: quota operations not supported\n"); 318 + break; 331 319 #endif 332 - case Opt_uid: 333 - { 334 - char *uid = args[0].from; 335 - uid_t val; 336 - int rc = kstrtouint(uid, 0, &val); 320 + case Opt_uid: 321 + ctx->uid = result.uid; 322 + break; 337 323 338 - if (rc) 339 - goto cleanup; 340 - sbi->uid = make_kuid(current_user_ns(), val); 341 - if (!uid_valid(sbi->uid)) 342 - goto cleanup; 343 - break; 324 + case Opt_gid: 325 + ctx->gid = result.gid; 326 + break; 327 + 328 + case Opt_umask: 329 + if (result.uint_32 & ~0777) { 330 + pr_err("JFS: Invalid value of umask\n"); 331 + return -EINVAL; 344 332 } 333 + ctx->umask = result.uint_32; 334 + break; 345 335 346 - case Opt_gid: 347 - { 348 - char *gid = args[0].from; 349 - gid_t val; 350 - int rc = kstrtouint(gid, 0, &val); 336 + case Opt_discard: 337 + /* if set to 1, even copying files will cause 338 + * trimming :O 339 + * -> user has more control over the online trimming 340 + */ 341 + ctx->minblks_trim = 64; 342 + ctx->flag |= JFS_DISCARD; 343 + break; 351 344 352 - if (rc) 353 - goto cleanup; 354 - sbi->gid = make_kgid(current_user_ns(), val); 355 - if (!gid_valid(sbi->gid)) 356 - goto cleanup; 357 - break; 358 - } 345 + case Opt_nodiscard: 346 + ctx->flag &= ~JFS_DISCARD; 347 + break; 359 348 360 - case Opt_umask: 361 - { 362 - char *umask = args[0].from; 363 - int rc = kstrtouint(umask, 8, &sbi->umask); 349 + case Opt_discard_minblk: 350 + ctx->minblks_trim = result.uint_32; 351 + ctx->flag |= JFS_DISCARD; 352 + break; 364 353 365 - if (rc) 366 - goto cleanup; 367 - if (sbi->umask & ~0777) { 368 - pr_err("JFS: Invalid value of umask\n"); 369 - goto cleanup; 370 - } 371 - break; 372 - } 373 - 374 - case Opt_discard: 375 - /* if set to 1, even copying files will cause 376 - * trimming :O 377 - * -> user has more control over the online trimming 378 - */ 379 - sbi->minblks_trim = 64; 380 - if (bdev_max_discard_sectors(sb->s_bdev)) 381 - *flag |= JFS_DISCARD; 382 - else 383 - pr_err("JFS: discard option not supported on device\n"); 384 - break; 385 - 386 - case Opt_nodiscard: 387 - *flag &= ~JFS_DISCARD; 388 - break; 389 - 390 - case Opt_discard_minblk: 391 - { 392 - char *minblks_trim = args[0].from; 393 - int rc; 394 - if (bdev_max_discard_sectors(sb->s_bdev)) { 395 - *flag |= JFS_DISCARD; 396 - rc = kstrtouint(minblks_trim, 0, 397 - &sbi->minblks_trim); 398 - if (rc) 399 - goto cleanup; 400 - } else 401 - pr_err("JFS: discard option not supported on device\n"); 402 - break; 403 - } 404 - 405 - default: 406 - printk("jfs: Unrecognized mount option \"%s\" or missing value\n", 407 - p); 408 - goto cleanup; 409 - } 354 + default: 355 + return -EINVAL; 410 356 } 411 357 412 - if (nls_map != (void *) -1) { 413 - /* Discard old (if remount) */ 414 - unload_nls(sbi->nls_tab); 415 - sbi->nls_tab = nls_map; 416 - } 417 - return 1; 418 - 419 - cleanup: 420 - if (nls_map && nls_map != (void *) -1) 421 - unload_nls(nls_map); 422 358 return 0; 423 359 } 424 360 425 - static int jfs_remount(struct super_block *sb, int *flags, char *data) 361 + static int jfs_reconfigure(struct fs_context *fc) 426 362 { 427 - s64 newLVSize = 0; 363 + struct jfs_context *ctx = fc->fs_private; 364 + struct super_block *sb = fc->root->d_sb; 365 + int readonly = fc->sb_flags & SB_RDONLY; 428 366 int rc = 0; 429 - int flag = JFS_SBI(sb)->flag; 367 + int flag = ctx->flag; 430 368 int ret; 431 369 432 370 sync_filesystem(sb); 433 - if (!parse_options(data, sb, &newLVSize, &flag)) 434 - return -EINVAL; 435 371 436 - if (newLVSize) { 372 + /* Transfer results of parsing to the sbi */ 373 + JFS_SBI(sb)->flag = ctx->flag; 374 + JFS_SBI(sb)->uid = ctx->uid; 375 + JFS_SBI(sb)->gid = ctx->gid; 376 + JFS_SBI(sb)->umask = ctx->umask; 377 + JFS_SBI(sb)->minblks_trim = ctx->minblks_trim; 378 + if (ctx->nls_map != (void *) -1) { 379 + unload_nls(JFS_SBI(sb)->nls_tab); 380 + JFS_SBI(sb)->nls_tab = ctx->nls_map; 381 + } 382 + ctx->nls_map = NULL; 383 + 384 + if (ctx->resize) { 437 385 if (sb_rdonly(sb)) { 438 386 pr_err("JFS: resize requires volume to be mounted read-write\n"); 439 387 return -EROFS; 440 388 } 441 - rc = jfs_extendfs(sb, newLVSize, 0); 389 + 390 + if (!ctx->newLVSize) { 391 + ctx->newLVSize = sb_bdev_nr_blocks(sb); 392 + if (ctx->newLVSize == 0) 393 + pr_err("JFS: Cannot determine volume size\n"); 394 + } 395 + 396 + rc = jfs_extendfs(sb, ctx->newLVSize, 0); 442 397 if (rc) 443 398 return rc; 444 399 } 445 400 446 - if (sb_rdonly(sb) && !(*flags & SB_RDONLY)) { 401 + if (sb_rdonly(sb) && !readonly) { 447 402 /* 448 403 * Invalidate any previously read metadata. fsck may have 449 404 * changed the on-disk data since we mounted r/o ··· 414 459 dquot_resume(sb, -1); 415 460 return ret; 416 461 } 417 - if (!sb_rdonly(sb) && (*flags & SB_RDONLY)) { 462 + if (!sb_rdonly(sb) && readonly) { 418 463 rc = dquot_suspend(sb, -1); 419 464 if (rc < 0) 420 465 return rc; ··· 422 467 JFS_SBI(sb)->flag = flag; 423 468 return rc; 424 469 } 425 - if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY)) 470 + if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY)) { 426 471 if (!sb_rdonly(sb)) { 427 472 rc = jfs_umount_rw(sb); 428 473 if (rc) ··· 432 477 ret = jfs_mount_rw(sb, 1); 433 478 return ret; 434 479 } 480 + } 435 481 JFS_SBI(sb)->flag = flag; 436 482 437 483 return 0; 438 484 } 439 485 440 - static int jfs_fill_super(struct super_block *sb, void *data, int silent) 486 + static int jfs_fill_super(struct super_block *sb, struct fs_context *fc) 441 487 { 488 + struct jfs_context *ctx = fc->fs_private; 489 + int silent = fc->sb_flags & SB_SILENT; 442 490 struct jfs_sb_info *sbi; 443 491 struct inode *inode; 444 492 int rc; 445 - s64 newLVSize = 0; 446 - int flag, ret = -EINVAL; 493 + int ret = -EINVAL; 447 494 448 495 jfs_info("In jfs_read_super: s_flags=0x%lx", sb->s_flags); 449 496 ··· 458 501 sb->s_time_min = 0; 459 502 sb->s_time_max = U32_MAX; 460 503 sbi->sb = sb; 461 - sbi->uid = INVALID_UID; 462 - sbi->gid = INVALID_GID; 463 - sbi->umask = -1; 464 504 465 - /* initialize the mount flag and determine the default error handler */ 466 - flag = JFS_ERR_REMOUNT_RO; 505 + /* Transfer results of parsing to the sbi */ 506 + sbi->flag = ctx->flag; 507 + sbi->uid = ctx->uid; 508 + sbi->gid = ctx->gid; 509 + sbi->umask = ctx->umask; 510 + if (ctx->nls_map != (void *) -1) { 511 + unload_nls(sbi->nls_tab); 512 + sbi->nls_tab = ctx->nls_map; 513 + } 514 + ctx->nls_map = NULL; 467 515 468 - if (!parse_options((char *) data, sb, &newLVSize, &flag)) 469 - goto out_kfree; 470 - sbi->flag = flag; 516 + if (sbi->flag & JFS_DISCARD) { 517 + if (!bdev_max_discard_sectors(sb->s_bdev)) { 518 + pr_err("JFS: discard option not supported on device\n"); 519 + sbi->flag &= ~JFS_DISCARD; 520 + } else { 521 + sbi->minblks_trim = ctx->minblks_trim; 522 + } 523 + } 471 524 472 525 #ifdef CONFIG_JFS_POSIX_ACL 473 526 sb->s_flags |= SB_POSIXACL; 474 527 #endif 475 528 476 - if (newLVSize) { 529 + if (ctx->resize) { 477 530 pr_err("resize option for remount only\n"); 478 - goto out_kfree; 531 + goto out_unload; 479 532 } 480 533 481 534 /* ··· 575 608 sbi->direct_inode = NULL; 576 609 out_unload: 577 610 unload_nls(sbi->nls_tab); 578 - out_kfree: 579 611 kfree(sbi); 580 612 return ret; 581 613 } ··· 630 664 return rc; 631 665 } 632 666 633 - static struct dentry *jfs_do_mount(struct file_system_type *fs_type, 634 - int flags, const char *dev_name, void *data) 667 + static int jfs_get_tree(struct fs_context *fc) 635 668 { 636 - return mount_bdev(fs_type, flags, dev_name, data, jfs_fill_super); 669 + return get_tree_bdev(fc, jfs_fill_super); 637 670 } 638 671 639 672 static int jfs_sync_fs(struct super_block *sb, int wait) ··· 851 886 .freeze_fs = jfs_freeze, 852 887 .unfreeze_fs = jfs_unfreeze, 853 888 .statfs = jfs_statfs, 854 - .remount_fs = jfs_remount, 855 889 .show_options = jfs_show_options, 856 890 #ifdef CONFIG_QUOTA 857 891 .quota_read = jfs_quota_read, ··· 866 902 .get_parent = jfs_get_parent, 867 903 }; 868 904 905 + static void jfs_init_options(struct fs_context *fc, struct jfs_context *ctx) 906 + { 907 + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) { 908 + struct super_block *sb = fc->root->d_sb; 909 + 910 + /* Copy over current option values and mount flags */ 911 + ctx->uid = JFS_SBI(sb)->uid; 912 + ctx->gid = JFS_SBI(sb)->gid; 913 + ctx->umask = JFS_SBI(sb)->umask; 914 + ctx->nls_map = (void *)-1; 915 + ctx->minblks_trim = JFS_SBI(sb)->minblks_trim; 916 + ctx->flag = JFS_SBI(sb)->flag; 917 + 918 + } else { 919 + /* 920 + * Initialize the mount flag and determine the default 921 + * error handler 922 + */ 923 + ctx->flag = JFS_ERR_REMOUNT_RO; 924 + ctx->uid = INVALID_UID; 925 + ctx->gid = INVALID_GID; 926 + ctx->umask = -1; 927 + ctx->nls_map = (void *)-1; 928 + } 929 + } 930 + 931 + static void jfs_free_fc(struct fs_context *fc) 932 + { 933 + struct jfs_context *ctx = fc->fs_private; 934 + 935 + if (ctx->nls_map != (void *) -1) 936 + unload_nls(ctx->nls_map); 937 + kfree(ctx); 938 + } 939 + 940 + static const struct fs_context_operations jfs_context_ops = { 941 + .parse_param = jfs_parse_param, 942 + .get_tree = jfs_get_tree, 943 + .reconfigure = jfs_reconfigure, 944 + .free = jfs_free_fc, 945 + }; 946 + 947 + static int jfs_init_fs_context(struct fs_context *fc) 948 + { 949 + struct jfs_context *ctx; 950 + 951 + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 952 + if (!ctx) 953 + return -ENOMEM; 954 + 955 + jfs_init_options(fc, ctx); 956 + 957 + fc->fs_private = ctx; 958 + fc->ops = &jfs_context_ops; 959 + 960 + return 0; 961 + } 962 + 869 963 static struct file_system_type jfs_fs_type = { 870 964 .owner = THIS_MODULE, 871 965 .name = "jfs", 872 - .mount = jfs_do_mount, 873 966 .kill_sb = kill_block_super, 874 967 .fs_flags = FS_REQUIRES_DEV, 968 + .init_fs_context = jfs_init_fs_context, 969 + .parameters = jfs_param_spec, 875 970 }; 876 971 MODULE_ALIAS_FS("jfs"); 877 972