Merge tag '5.8-rc-smb3-fixes-part-1' of git://git.samba.org/sfrench/cifs-2.6
[linux-2.6-microblaze.git] / fs / erofs / super.c
index b514c67..7a13ffb 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/parser.h>
 #include <linux/seq_file.h>
 #include <linux/crc32c.h>
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
 #include "xattr.h"
 
 #define CREATE_TRACE_POINTS
@@ -192,53 +194,18 @@ out:
        return ret;
 }
 
-#ifdef CONFIG_EROFS_FS_ZIP
-static int erofs_build_cache_strategy(struct super_block *sb,
-                                     substring_t *args)
-{
-       struct erofs_sb_info *sbi = EROFS_SB(sb);
-       const char *cs = match_strdup(args);
-       int err = 0;
-
-       if (!cs) {
-               erofs_err(sb, "Not enough memory to store cache strategy");
-               return -ENOMEM;
-       }
-
-       if (!strcmp(cs, "disabled")) {
-               sbi->cache_strategy = EROFS_ZIP_CACHE_DISABLED;
-       } else if (!strcmp(cs, "readahead")) {
-               sbi->cache_strategy = EROFS_ZIP_CACHE_READAHEAD;
-       } else if (!strcmp(cs, "readaround")) {
-               sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND;
-       } else {
-               erofs_err(sb, "Unrecognized cache strategy \"%s\"", cs);
-               err = -EINVAL;
-       }
-       kfree(cs);
-       return err;
-}
-#else
-static int erofs_build_cache_strategy(struct super_block *sb,
-                                     substring_t *args)
-{
-       erofs_info(sb, "EROFS compression is disabled, so cache strategy is ignored");
-       return 0;
-}
-#endif
-
 /* set up default EROFS parameters */
-static void erofs_default_options(struct erofs_sb_info *sbi)
+static void erofs_default_options(struct erofs_fs_context *ctx)
 {
 #ifdef CONFIG_EROFS_FS_ZIP
-       sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND;
-       sbi->max_sync_decompress_pages = 3;
+       ctx->cache_strategy = EROFS_ZIP_CACHE_READAROUND;
+       ctx->max_sync_decompress_pages = 3;
 #endif
 #ifdef CONFIG_EROFS_FS_XATTR
-       set_opt(sbi, XATTR_USER);
+       set_opt(ctx, XATTR_USER);
 #endif
 #ifdef CONFIG_EROFS_FS_POSIX_ACL
-       set_opt(sbi, POSIX_ACL);
+       set_opt(ctx, POSIX_ACL);
 #endif
 }
 
@@ -251,73 +218,62 @@ enum {
        Opt_err
 };
 
-static match_table_t erofs_tokens = {
-       {Opt_user_xattr, "user_xattr"},
-       {Opt_nouser_xattr, "nouser_xattr"},
-       {Opt_acl, "acl"},
-       {Opt_noacl, "noacl"},
-       {Opt_cache_strategy, "cache_strategy=%s"},
-       {Opt_err, NULL}
+static const struct constant_table erofs_param_cache_strategy[] = {
+       {"disabled",    EROFS_ZIP_CACHE_DISABLED},
+       {"readahead",   EROFS_ZIP_CACHE_READAHEAD},
+       {"readaround",  EROFS_ZIP_CACHE_READAROUND},
+       {}
 };
 
-static int erofs_parse_options(struct super_block *sb, char *options)
-{
-       substring_t args[MAX_OPT_ARGS];
-       char *p;
-       int err;
-
-       if (!options)
-               return 0;
-
-       while ((p = strsep(&options, ","))) {
-               int token;
+static const struct fs_parameter_spec erofs_fs_parameters[] = {
+       fsparam_flag_no("user_xattr",   Opt_user_xattr),
+       fsparam_flag_no("acl",          Opt_acl),
+       fsparam_enum("cache_strategy",  Opt_cache_strategy,
+                    erofs_param_cache_strategy),
+       {}
+};
 
-               if (!*p)
-                       continue;
+static int erofs_fc_parse_param(struct fs_context *fc,
+                               struct fs_parameter *param)
+{
+       struct erofs_fs_context *ctx __maybe_unused = fc->fs_private;
+       struct fs_parse_result result;
+       int opt;
 
-               args[0].to = args[0].from = NULL;
-               token = match_token(p, erofs_tokens, args);
+       opt = fs_parse(fc, erofs_fs_parameters, param, &result);
+       if (opt < 0)
+               return opt;
 
-               switch (token) {
+       switch (opt) {
+       case Opt_user_xattr:
 #ifdef CONFIG_EROFS_FS_XATTR
-               case Opt_user_xattr:
-                       set_opt(EROFS_SB(sb), XATTR_USER);
-                       break;
-               case Opt_nouser_xattr:
-                       clear_opt(EROFS_SB(sb), XATTR_USER);
-                       break;
+               if (result.boolean)
+                       set_opt(ctx, XATTR_USER);
+               else
+                       clear_opt(ctx, XATTR_USER);
 #else
-               case Opt_user_xattr:
-                       erofs_info(sb, "user_xattr options not supported");
-                       break;
-               case Opt_nouser_xattr:
-                       erofs_info(sb, "nouser_xattr options not supported");
-                       break;
+               errorfc(fc, "{,no}user_xattr options not supported");
 #endif
+               break;
+       case Opt_acl:
 #ifdef CONFIG_EROFS_FS_POSIX_ACL
-               case Opt_acl:
-                       set_opt(EROFS_SB(sb), POSIX_ACL);
-                       break;
-               case Opt_noacl:
-                       clear_opt(EROFS_SB(sb), POSIX_ACL);
-                       break;
+               if (result.boolean)
+                       set_opt(ctx, POSIX_ACL);
+               else
+                       clear_opt(ctx, POSIX_ACL);
 #else
-               case Opt_acl:
-                       erofs_info(sb, "acl options not supported");
-                       break;
-               case Opt_noacl:
-                       erofs_info(sb, "noacl options not supported");
-                       break;
+               errorfc(fc, "{,no}acl options not supported");
 #endif
-               case Opt_cache_strategy:
-                       err = erofs_build_cache_strategy(sb, args);
-                       if (err)
-                               return err;
-                       break;
-               default:
-                       erofs_err(sb, "Unrecognized mount option \"%s\" or missing value", p);
-                       return -EINVAL;
-               }
+               break;
+       case Opt_cache_strategy:
+#ifdef CONFIG_EROFS_FS_ZIP
+               ctx->cache_strategy = result.uint_32;
+#else
+               errorfc(fc, "compression not supported, cache_strategy ignored");
+#endif
+               break;
+       default:
+               return -ENOPARAM;
        }
        return 0;
 }
@@ -381,10 +337,11 @@ static int erofs_init_managed_cache(struct super_block *sb)
 static int erofs_init_managed_cache(struct super_block *sb) { return 0; }
 #endif
 
-static int erofs_fill_super(struct super_block *sb, void *data, int silent)
+static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 {
        struct inode *inode;
        struct erofs_sb_info *sbi;
+       struct erofs_fs_context *ctx = fc->fs_private;
        int err;
 
        sb->s_magic = EROFS_SUPER_MAGIC;
@@ -408,22 +365,15 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_time_gran = 1;
 
        sb->s_op = &erofs_sops;
-
-#ifdef CONFIG_EROFS_FS_XATTR
        sb->s_xattr = erofs_xattr_handlers;
-#endif
-       /* set erofs default mount options */
-       erofs_default_options(sbi);
 
-       err = erofs_parse_options(sb, data);
-       if (err)
-               return err;
-
-       if (test_opt(sbi, POSIX_ACL))
+       if (test_opt(ctx, POSIX_ACL))
                sb->s_flags |= SB_POSIXACL;
        else
                sb->s_flags &= ~SB_POSIXACL;
 
+       sbi->ctx = *ctx;
+
 #ifdef CONFIG_EROFS_FS_ZIP
        xa_init(&sbi->managed_pslots);
 #endif
@@ -450,15 +400,58 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent)
        if (err)
                return err;
 
-       erofs_info(sb, "mounted with opts: %s, root inode @ nid %llu.",
-                  (char *)data, ROOT_NID(sbi));
+       erofs_info(sb, "mounted with root inode @ nid %llu.", ROOT_NID(sbi));
+       return 0;
+}
+
+static int erofs_fc_get_tree(struct fs_context *fc)
+{
+       return get_tree_bdev(fc, erofs_fc_fill_super);
+}
+
+static int erofs_fc_reconfigure(struct fs_context *fc)
+{
+       struct super_block *sb = fc->root->d_sb;
+       struct erofs_sb_info *sbi = EROFS_SB(sb);
+       struct erofs_fs_context *ctx = fc->fs_private;
+
+       DBG_BUGON(!sb_rdonly(sb));
+
+       if (test_opt(ctx, POSIX_ACL))
+               fc->sb_flags |= SB_POSIXACL;
+       else
+               fc->sb_flags &= ~SB_POSIXACL;
+
+       sbi->ctx = *ctx;
+
+       fc->sb_flags |= SB_RDONLY;
        return 0;
 }
 
-static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags,
-                                 const char *dev_name, void *data)
+static void erofs_fc_free(struct fs_context *fc)
 {
-       return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super);
+       kfree(fc->fs_private);
+}
+
+static const struct fs_context_operations erofs_context_ops = {
+       .parse_param    = erofs_fc_parse_param,
+       .get_tree       = erofs_fc_get_tree,
+       .reconfigure    = erofs_fc_reconfigure,
+       .free           = erofs_fc_free,
+};
+
+static int erofs_init_fs_context(struct fs_context *fc)
+{
+       fc->fs_private = kzalloc(sizeof(struct erofs_fs_context), GFP_KERNEL);
+       if (!fc->fs_private)
+               return -ENOMEM;
+
+       /* set default mount options */
+       erofs_default_options(fc->fs_private);
+
+       fc->ops = &erofs_context_ops;
+
+       return 0;
 }
 
 /*
@@ -497,7 +490,7 @@ static void erofs_put_super(struct super_block *sb)
 static struct file_system_type erofs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "erofs",
-       .mount          = erofs_mount,
+       .init_fs_context = erofs_init_fs_context,
        .kill_sb        = erofs_kill_sb,
        .fs_flags       = FS_REQUIRES_DEV,
 };
@@ -578,61 +571,37 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf)
 static int erofs_show_options(struct seq_file *seq, struct dentry *root)
 {
        struct erofs_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb);
+       struct erofs_fs_context *ctx __maybe_unused = &sbi->ctx;
 
 #ifdef CONFIG_EROFS_FS_XATTR
-       if (test_opt(sbi, XATTR_USER))
+       if (test_opt(ctx, XATTR_USER))
                seq_puts(seq, ",user_xattr");
        else
                seq_puts(seq, ",nouser_xattr");
 #endif
 #ifdef CONFIG_EROFS_FS_POSIX_ACL
-       if (test_opt(sbi, POSIX_ACL))
+       if (test_opt(ctx, POSIX_ACL))
                seq_puts(seq, ",acl");
        else
                seq_puts(seq, ",noacl");
 #endif
 #ifdef CONFIG_EROFS_FS_ZIP
-       if (sbi->cache_strategy == EROFS_ZIP_CACHE_DISABLED) {
+       if (ctx->cache_strategy == EROFS_ZIP_CACHE_DISABLED)
                seq_puts(seq, ",cache_strategy=disabled");
-       } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) {
+       else if (ctx->cache_strategy == EROFS_ZIP_CACHE_READAHEAD)
                seq_puts(seq, ",cache_strategy=readahead");
-       } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAROUND) {
+       else if (ctx->cache_strategy == EROFS_ZIP_CACHE_READAROUND)
                seq_puts(seq, ",cache_strategy=readaround");
-       }
 #endif
        return 0;
 }
 
-static int erofs_remount(struct super_block *sb, int *flags, char *data)
-{
-       struct erofs_sb_info *sbi = EROFS_SB(sb);
-       unsigned int org_mnt_opt = sbi->mount_opt;
-       int err;
-
-       DBG_BUGON(!sb_rdonly(sb));
-       err = erofs_parse_options(sb, data);
-       if (err)
-               goto out;
-
-       if (test_opt(sbi, POSIX_ACL))
-               sb->s_flags |= SB_POSIXACL;
-       else
-               sb->s_flags &= ~SB_POSIXACL;
-
-       *flags |= SB_RDONLY;
-       return 0;
-out:
-       sbi->mount_opt = org_mnt_opt;
-       return err;
-}
-
 const struct super_operations erofs_sops = {
        .put_super = erofs_put_super,
        .alloc_inode = erofs_alloc_inode,
        .free_inode = erofs_free_inode,
        .statfs = erofs_statfs,
        .show_options = erofs_show_options,
-       .remount_fs = erofs_remount,
 };
 
 module_init(erofs_module_init);