|
9 | 9 | #include <linux/fs.h>
|
10 | 10 | #include <linux/vfs.h>
|
11 | 11 | #include <linux/cred.h>
|
12 |
| -#include <linux/parser.h> |
13 | 12 | #include <linux/buffer_head.h>
|
14 | 13 | #include <linux/vmalloc.h>
|
15 | 14 | #include <linux/writeback.h>
|
16 | 15 | #include <linux/seq_file.h>
|
17 | 16 | #include <linux/crc-itu-t.h>
|
| 17 | +#include <linux/fs_context.h> |
| 18 | +#include <linux/fs_parser.h> |
18 | 19 | #include "omfs.h"
|
19 | 20 |
|
20 | 21 | MODULE_AUTHOR( "Bob Copeland <[email protected]>");
|
@@ -384,92 +385,91 @@ static int omfs_get_imap(struct super_block *sb)
|
384 | 385 | return -ENOMEM;
|
385 | 386 | }
|
386 | 387 |
|
| 388 | +struct omfs_mount_options { |
| 389 | + kuid_t s_uid; |
| 390 | + kgid_t s_gid; |
| 391 | + int s_dmask; |
| 392 | + int s_fmask; |
| 393 | +}; |
| 394 | + |
387 | 395 | enum {
|
388 |
| - Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask, Opt_err |
| 396 | + Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask, |
389 | 397 | };
|
390 | 398 |
|
391 |
| -static const match_table_t tokens = { |
392 |
| - {Opt_uid, "uid=%u"}, |
393 |
| - {Opt_gid, "gid=%u"}, |
394 |
| - {Opt_umask, "umask=%o"}, |
395 |
| - {Opt_dmask, "dmask=%o"}, |
396 |
| - {Opt_fmask, "fmask=%o"}, |
397 |
| - {Opt_err, NULL}, |
| 399 | +static const struct fs_parameter_spec omfs_param_spec[] = { |
| 400 | + fsparam_uid ("uid", Opt_uid), |
| 401 | + fsparam_gid ("gid", Opt_gid), |
| 402 | + fsparam_u32oct ("umask", Opt_umask), |
| 403 | + fsparam_u32oct ("dmask", Opt_dmask), |
| 404 | + fsparam_u32oct ("fmask", Opt_fmask), |
| 405 | + {} |
398 | 406 | };
|
399 | 407 |
|
400 |
| -static int parse_options(char *options, struct omfs_sb_info *sbi) |
| 408 | +static int |
| 409 | +omfs_parse_param(struct fs_context *fc, struct fs_parameter *param) |
401 | 410 | {
|
402 |
| - char *p; |
403 |
| - substring_t args[MAX_OPT_ARGS]; |
404 |
| - int option; |
405 |
| - |
406 |
| - if (!options) |
407 |
| - return 1; |
408 |
| - |
409 |
| - while ((p = strsep(&options, ",")) != NULL) { |
410 |
| - int token; |
411 |
| - if (!*p) |
412 |
| - continue; |
413 |
| - |
414 |
| - token = match_token(p, tokens, args); |
415 |
| - switch (token) { |
416 |
| - case Opt_uid: |
417 |
| - if (match_int(&args[0], &option)) |
418 |
| - return 0; |
419 |
| - sbi->s_uid = make_kuid(current_user_ns(), option); |
420 |
| - if (!uid_valid(sbi->s_uid)) |
421 |
| - return 0; |
422 |
| - break; |
423 |
| - case Opt_gid: |
424 |
| - if (match_int(&args[0], &option)) |
425 |
| - return 0; |
426 |
| - sbi->s_gid = make_kgid(current_user_ns(), option); |
427 |
| - if (!gid_valid(sbi->s_gid)) |
428 |
| - return 0; |
429 |
| - break; |
430 |
| - case Opt_umask: |
431 |
| - if (match_octal(&args[0], &option)) |
432 |
| - return 0; |
433 |
| - sbi->s_fmask = sbi->s_dmask = option; |
434 |
| - break; |
435 |
| - case Opt_dmask: |
436 |
| - if (match_octal(&args[0], &option)) |
437 |
| - return 0; |
438 |
| - sbi->s_dmask = option; |
439 |
| - break; |
440 |
| - case Opt_fmask: |
441 |
| - if (match_octal(&args[0], &option)) |
442 |
| - return 0; |
443 |
| - sbi->s_fmask = option; |
444 |
| - break; |
445 |
| - default: |
446 |
| - return 0; |
447 |
| - } |
| 411 | + struct omfs_mount_options *opts = fc->fs_private; |
| 412 | + int token; |
| 413 | + struct fs_parse_result result; |
| 414 | + |
| 415 | + /* All options are ignored on remount */ |
| 416 | + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) |
| 417 | + return 0; |
| 418 | + |
| 419 | + token = fs_parse(fc, omfs_param_spec, param, &result); |
| 420 | + if (token < 0) |
| 421 | + return token; |
| 422 | + |
| 423 | + switch (token) { |
| 424 | + case Opt_uid: |
| 425 | + opts->s_uid = result.uid; |
| 426 | + break; |
| 427 | + case Opt_gid: |
| 428 | + opts->s_gid = result.gid; |
| 429 | + break; |
| 430 | + case Opt_umask: |
| 431 | + opts->s_fmask = opts->s_dmask = result.uint_32; |
| 432 | + break; |
| 433 | + case Opt_dmask: |
| 434 | + opts->s_dmask = result.uint_32; |
| 435 | + break; |
| 436 | + case Opt_fmask: |
| 437 | + opts->s_fmask = result.uint_32; |
| 438 | + break; |
| 439 | + default: |
| 440 | + return -EINVAL; |
448 | 441 | }
|
449 |
| - return 1; |
| 442 | + |
| 443 | + return 0; |
450 | 444 | }
|
451 | 445 |
|
452 |
| -static int omfs_fill_super(struct super_block *sb, void *data, int silent) |
| 446 | +static void |
| 447 | +omfs_set_options(struct omfs_sb_info *sbi, struct omfs_mount_options *opts) |
| 448 | +{ |
| 449 | + sbi->s_uid = opts->s_uid; |
| 450 | + sbi->s_gid = opts->s_gid; |
| 451 | + sbi->s_dmask = opts->s_dmask; |
| 452 | + sbi->s_fmask = opts->s_fmask; |
| 453 | +} |
| 454 | + |
| 455 | +static int omfs_fill_super(struct super_block *sb, struct fs_context *fc) |
453 | 456 | {
|
454 | 457 | struct buffer_head *bh, *bh2;
|
455 | 458 | struct omfs_super_block *omfs_sb;
|
456 | 459 | struct omfs_root_block *omfs_rb;
|
457 | 460 | struct omfs_sb_info *sbi;
|
458 | 461 | struct inode *root;
|
| 462 | + struct omfs_mount_options *parsed_opts = fc->fs_private; |
459 | 463 | int ret = -EINVAL;
|
| 464 | + int silent = fc->sb_flags & SB_SILENT; |
460 | 465 |
|
461 | 466 | sbi = kzalloc(sizeof(struct omfs_sb_info), GFP_KERNEL);
|
462 | 467 | if (!sbi)
|
463 | 468 | return -ENOMEM;
|
464 | 469 |
|
465 | 470 | sb->s_fs_info = sbi;
|
466 | 471 |
|
467 |
| - sbi->s_uid = current_uid(); |
468 |
| - sbi->s_gid = current_gid(); |
469 |
| - sbi->s_dmask = sbi->s_fmask = current_umask(); |
470 |
| - |
471 |
| - if (!parse_options((char *) data, sbi)) |
472 |
| - goto end; |
| 472 | + omfs_set_options(sbi, parsed_opts); |
473 | 473 |
|
474 | 474 | sb->s_maxbytes = 0xffffffff;
|
475 | 475 |
|
@@ -594,18 +594,50 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent)
|
594 | 594 | return ret;
|
595 | 595 | }
|
596 | 596 |
|
597 |
| -static struct dentry *omfs_mount(struct file_system_type *fs_type, |
598 |
| - int flags, const char *dev_name, void *data) |
| 597 | +static int omfs_get_tree(struct fs_context *fc) |
| 598 | +{ |
| 599 | + return get_tree_bdev(fc, omfs_fill_super); |
| 600 | +} |
| 601 | + |
| 602 | +static void omfs_free_fc(struct fs_context *fc); |
| 603 | + |
| 604 | +static const struct fs_context_operations omfs_context_ops = { |
| 605 | + .parse_param = omfs_parse_param, |
| 606 | + .get_tree = omfs_get_tree, |
| 607 | + .free = omfs_free_fc, |
| 608 | +}; |
| 609 | + |
| 610 | +static int omfs_init_fs_context(struct fs_context *fc) |
| 611 | +{ |
| 612 | + struct omfs_mount_options *opts; |
| 613 | + |
| 614 | + opts = kzalloc(sizeof(*opts), GFP_KERNEL); |
| 615 | + if (!opts) |
| 616 | + return -ENOMEM; |
| 617 | + |
| 618 | + /* Set mount options defaults */ |
| 619 | + opts->s_uid = current_uid(); |
| 620 | + opts->s_gid = current_gid(); |
| 621 | + opts->s_dmask = opts->s_fmask = current_umask(); |
| 622 | + |
| 623 | + fc->fs_private = opts; |
| 624 | + fc->ops = &omfs_context_ops; |
| 625 | + |
| 626 | + return 0; |
| 627 | +} |
| 628 | + |
| 629 | +static void omfs_free_fc(struct fs_context *fc) |
599 | 630 | {
|
600 |
| - return mount_bdev(fs_type, flags, dev_name, data, omfs_fill_super); |
| 631 | + kfree(fc->fs_private); |
601 | 632 | }
|
602 | 633 |
|
603 | 634 | static struct file_system_type omfs_fs_type = {
|
604 |
| - .owner = THIS_MODULE, |
605 |
| - .name = "omfs", |
606 |
| - .mount = omfs_mount, |
607 |
| - .kill_sb = kill_block_super, |
608 |
| - .fs_flags = FS_REQUIRES_DEV, |
| 635 | + .owner = THIS_MODULE, |
| 636 | + .name = "omfs", |
| 637 | + .kill_sb = kill_block_super, |
| 638 | + .fs_flags = FS_REQUIRES_DEV, |
| 639 | + .init_fs_context = omfs_init_fs_context, |
| 640 | + .parameters = omfs_param_spec, |
609 | 641 | };
|
610 | 642 | MODULE_ALIAS_FS("omfs");
|
611 | 643 |
|
|
0 commit comments