Commit f57a3fe4 authored by Chao Yu's avatar Chao Yu Committed by Gao Xiang

erofs: convert to use the new mount fs_context api

Convert the erofs to use new internal mount API as the old one will
be obsoleted and removed.  This allows greater flexibility in
communication of mount parameters between userspace, the VFS and the
filesystem.

See Documentation/filesystems/mount_api.txt for more information.

Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: David Howells <dhowells@redhat.com>
Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Link: https://lore.kernel.org/r/20200529104836.17843-1-hsiangkao@redhat.comSigned-off-by: default avatarGao Xiang <hsiangkao@redhat.com>
parent e7cda1ee
...@@ -46,6 +46,17 @@ typedef u64 erofs_off_t; ...@@ -46,6 +46,17 @@ typedef u64 erofs_off_t;
/* data type for filesystem-wide blocks number */ /* data type for filesystem-wide blocks number */
typedef u32 erofs_blk_t; typedef u32 erofs_blk_t;
struct erofs_fs_context {
#ifdef CONFIG_EROFS_FS_ZIP
/* current strategy of how to use managed cache */
unsigned char cache_strategy;
/* threshold for decompression synchronously */
unsigned int max_sync_decompress_pages;
#endif
unsigned int mount_opt;
};
struct erofs_sb_info { struct erofs_sb_info {
#ifdef CONFIG_EROFS_FS_ZIP #ifdef CONFIG_EROFS_FS_ZIP
/* list for all registered superblocks, mainly for shrinker */ /* list for all registered superblocks, mainly for shrinker */
...@@ -55,14 +66,8 @@ struct erofs_sb_info { ...@@ -55,14 +66,8 @@ struct erofs_sb_info {
/* managed XArray arranged in physical block number */ /* managed XArray arranged in physical block number */
struct xarray managed_pslots; struct xarray managed_pslots;
/* threshold for decompression synchronously */
unsigned int max_sync_decompress_pages;
unsigned int shrinker_run_no; unsigned int shrinker_run_no;
/* current strategy of how to use managed cache */
unsigned char cache_strategy;
/* pseudo inode to manage cached pages */ /* pseudo inode to manage cached pages */
struct inode *managed_cache; struct inode *managed_cache;
#endif /* CONFIG_EROFS_FS_ZIP */ #endif /* CONFIG_EROFS_FS_ZIP */
...@@ -88,7 +93,7 @@ struct erofs_sb_info { ...@@ -88,7 +93,7 @@ struct erofs_sb_info {
u32 feature_compat; u32 feature_compat;
u32 feature_incompat; u32 feature_incompat;
unsigned int mount_opt; struct erofs_fs_context ctx; /* options */
}; };
#define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) #define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info)
...@@ -98,17 +103,17 @@ struct erofs_sb_info { ...@@ -98,17 +103,17 @@ struct erofs_sb_info {
#define EROFS_MOUNT_XATTR_USER 0x00000010 #define EROFS_MOUNT_XATTR_USER 0x00000010
#define EROFS_MOUNT_POSIX_ACL 0x00000020 #define EROFS_MOUNT_POSIX_ACL 0x00000020
#define clear_opt(sbi, option) ((sbi)->mount_opt &= ~EROFS_MOUNT_##option) #define clear_opt(ctx, option) ((ctx)->mount_opt &= ~EROFS_MOUNT_##option)
#define set_opt(sbi, option) ((sbi)->mount_opt |= EROFS_MOUNT_##option) #define set_opt(ctx, option) ((ctx)->mount_opt |= EROFS_MOUNT_##option)
#define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) #define test_opt(ctx, option) ((ctx)->mount_opt & EROFS_MOUNT_##option)
#ifdef CONFIG_EROFS_FS_ZIP
enum { enum {
EROFS_ZIP_CACHE_DISABLED, EROFS_ZIP_CACHE_DISABLED,
EROFS_ZIP_CACHE_READAHEAD, EROFS_ZIP_CACHE_READAHEAD,
EROFS_ZIP_CACHE_READAROUND EROFS_ZIP_CACHE_READAROUND
}; };
#ifdef CONFIG_EROFS_FS_ZIP
#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) #define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL)
/* basic unit of the workstation of a super_block */ /* basic unit of the workstation of a super_block */
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <linux/parser.h> #include <linux/parser.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/crc32c.h> #include <linux/crc32c.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
#include "xattr.h" #include "xattr.h"
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
...@@ -192,53 +194,18 @@ static int erofs_read_superblock(struct super_block *sb) ...@@ -192,53 +194,18 @@ static int erofs_read_superblock(struct super_block *sb)
return ret; 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 */ /* 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 #ifdef CONFIG_EROFS_FS_ZIP
sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; ctx->cache_strategy = EROFS_ZIP_CACHE_READAROUND;
sbi->max_sync_decompress_pages = 3; ctx->max_sync_decompress_pages = 3;
#endif #endif
#ifdef CONFIG_EROFS_FS_XATTR #ifdef CONFIG_EROFS_FS_XATTR
set_opt(sbi, XATTR_USER); set_opt(ctx, XATTR_USER);
#endif #endif
#ifdef CONFIG_EROFS_FS_POSIX_ACL #ifdef CONFIG_EROFS_FS_POSIX_ACL
set_opt(sbi, POSIX_ACL); set_opt(ctx, POSIX_ACL);
#endif #endif
} }
...@@ -251,73 +218,62 @@ enum { ...@@ -251,73 +218,62 @@ enum {
Opt_err Opt_err
}; };
static match_table_t erofs_tokens = { static const struct constant_table erofs_param_cache_strategy[] = {
{Opt_user_xattr, "user_xattr"}, {"disabled", EROFS_ZIP_CACHE_DISABLED},
{Opt_nouser_xattr, "nouser_xattr"}, {"readahead", EROFS_ZIP_CACHE_READAHEAD},
{Opt_acl, "acl"}, {"readaround", EROFS_ZIP_CACHE_READAROUND},
{Opt_noacl, "noacl"}, {}
{Opt_cache_strategy, "cache_strategy=%s"},
{Opt_err, NULL}
}; };
static int erofs_parse_options(struct super_block *sb, char *options) static const struct fs_parameter_spec erofs_fs_parameters[] = {
{ fsparam_flag_no("user_xattr", Opt_user_xattr),
substring_t args[MAX_OPT_ARGS]; fsparam_flag_no("acl", Opt_acl),
char *p; fsparam_enum("cache_strategy", Opt_cache_strategy,
int err; erofs_param_cache_strategy),
{}
if (!options) };
return 0;
while ((p = strsep(&options, ","))) {
int token;
if (!*p) static int erofs_fc_parse_param(struct fs_context *fc,
continue; 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; opt = fs_parse(fc, erofs_fs_parameters, param, &result);
token = match_token(p, erofs_tokens, args); if (opt < 0)
return opt;
switch (token) { switch (opt) {
#ifdef CONFIG_EROFS_FS_XATTR
case Opt_user_xattr: case Opt_user_xattr:
set_opt(EROFS_SB(sb), XATTR_USER); #ifdef CONFIG_EROFS_FS_XATTR
break; if (result.boolean)
case Opt_nouser_xattr: set_opt(ctx, XATTR_USER);
clear_opt(EROFS_SB(sb), XATTR_USER); else
break; clear_opt(ctx, XATTR_USER);
#else #else
case Opt_user_xattr: errorfc(fc, "{,no}user_xattr options not supported");
erofs_info(sb, "user_xattr options not supported");
break;
case Opt_nouser_xattr:
erofs_info(sb, "nouser_xattr options not supported");
break;
#endif #endif
#ifdef CONFIG_EROFS_FS_POSIX_ACL
case Opt_acl:
set_opt(EROFS_SB(sb), POSIX_ACL);
break; break;
case Opt_noacl:
clear_opt(EROFS_SB(sb), POSIX_ACL);
break;
#else
case Opt_acl: case Opt_acl:
erofs_info(sb, "acl options not supported"); #ifdef CONFIG_EROFS_FS_POSIX_ACL
break; if (result.boolean)
case Opt_noacl: set_opt(ctx, POSIX_ACL);
erofs_info(sb, "noacl options not supported"); else
break; clear_opt(ctx, POSIX_ACL);
#else
errorfc(fc, "{,no}acl options not supported");
#endif #endif
break;
case Opt_cache_strategy: case Opt_cache_strategy:
err = erofs_build_cache_strategy(sb, args); #ifdef CONFIG_EROFS_FS_ZIP
if (err) ctx->cache_strategy = result.uint_32;
return err; #else
errorfc(fc, "compression not supported, cache_strategy ignored");
#endif
break; break;
default: default:
erofs_err(sb, "Unrecognized mount option \"%s\" or missing value", p); return -ENOPARAM;
return -EINVAL;
}
} }
return 0; return 0;
} }
...@@ -381,10 +337,11 @@ static int erofs_init_managed_cache(struct super_block *sb) ...@@ -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; } static int erofs_init_managed_cache(struct super_block *sb) { return 0; }
#endif #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 inode *inode;
struct erofs_sb_info *sbi; struct erofs_sb_info *sbi;
struct erofs_fs_context *ctx = fc->fs_private;
int err; int err;
sb->s_magic = EROFS_SUPER_MAGIC; sb->s_magic = EROFS_SUPER_MAGIC;
...@@ -410,18 +367,13 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -410,18 +367,13 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_op = &erofs_sops; sb->s_op = &erofs_sops;
sb->s_xattr = erofs_xattr_handlers; sb->s_xattr = erofs_xattr_handlers;
/* set erofs default mount options */ if (test_opt(ctx, POSIX_ACL))
erofs_default_options(sbi);
err = erofs_parse_options(sb, data);
if (err)
return err;
if (test_opt(sbi, POSIX_ACL))
sb->s_flags |= SB_POSIXACL; sb->s_flags |= SB_POSIXACL;
else else
sb->s_flags &= ~SB_POSIXACL; sb->s_flags &= ~SB_POSIXACL;
sbi->ctx = *ctx;
#ifdef CONFIG_EROFS_FS_ZIP #ifdef CONFIG_EROFS_FS_ZIP
xa_init(&sbi->managed_pslots); xa_init(&sbi->managed_pslots);
#endif #endif
...@@ -448,15 +400,58 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -448,15 +400,58 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent)
if (err) if (err)
return err; return err;
erofs_info(sb, "mounted with opts: %s, root inode @ nid %llu.", erofs_info(sb, "mounted with root inode @ nid %llu.", ROOT_NID(sbi));
(char *)data, 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; return 0;
} }
static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, static void erofs_fc_free(struct fs_context *fc)
const char *dev_name, void *data)
{ {
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;
} }
/* /*
...@@ -495,7 +490,7 @@ static void erofs_put_super(struct super_block *sb) ...@@ -495,7 +490,7 @@ static void erofs_put_super(struct super_block *sb)
static struct file_system_type erofs_fs_type = { static struct file_system_type erofs_fs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "erofs", .name = "erofs",
.mount = erofs_mount, .init_fs_context = erofs_init_fs_context,
.kill_sb = erofs_kill_sb, .kill_sb = erofs_kill_sb,
.fs_flags = FS_REQUIRES_DEV, .fs_flags = FS_REQUIRES_DEV,
}; };
...@@ -576,61 +571,37 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -576,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) 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_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb);
struct erofs_fs_context *ctx __maybe_unused = &sbi->ctx;
#ifdef CONFIG_EROFS_FS_XATTR #ifdef CONFIG_EROFS_FS_XATTR
if (test_opt(sbi, XATTR_USER)) if (test_opt(ctx, XATTR_USER))
seq_puts(seq, ",user_xattr"); seq_puts(seq, ",user_xattr");
else else
seq_puts(seq, ",nouser_xattr"); seq_puts(seq, ",nouser_xattr");
#endif #endif
#ifdef CONFIG_EROFS_FS_POSIX_ACL #ifdef CONFIG_EROFS_FS_POSIX_ACL
if (test_opt(sbi, POSIX_ACL)) if (test_opt(ctx, POSIX_ACL))
seq_puts(seq, ",acl"); seq_puts(seq, ",acl");
else else
seq_puts(seq, ",noacl"); seq_puts(seq, ",noacl");
#endif #endif
#ifdef CONFIG_EROFS_FS_ZIP #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"); 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"); 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"); seq_puts(seq, ",cache_strategy=readaround");
}
#endif #endif
return 0; 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 = { const struct super_operations erofs_sops = {
.put_super = erofs_put_super, .put_super = erofs_put_super,
.alloc_inode = erofs_alloc_inode, .alloc_inode = erofs_alloc_inode,
.free_inode = erofs_free_inode, .free_inode = erofs_free_inode,
.statfs = erofs_statfs, .statfs = erofs_statfs,
.show_options = erofs_show_options, .show_options = erofs_show_options,
.remount_fs = erofs_remount,
}; };
module_init(erofs_module_init); module_init(erofs_module_init);
......
...@@ -422,7 +422,7 @@ static int shared_getxattr(struct inode *inode, struct getxattr_iter *it) ...@@ -422,7 +422,7 @@ static int shared_getxattr(struct inode *inode, struct getxattr_iter *it)
static bool erofs_xattr_user_list(struct dentry *dentry) static bool erofs_xattr_user_list(struct dentry *dentry)
{ {
return test_opt(EROFS_SB(dentry->d_sb), XATTR_USER); return test_opt(&EROFS_SB(dentry->d_sb)->ctx, XATTR_USER);
} }
static bool erofs_xattr_trusted_list(struct dentry *dentry) static bool erofs_xattr_trusted_list(struct dentry *dentry)
...@@ -469,7 +469,7 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler, ...@@ -469,7 +469,7 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler,
switch (handler->flags) { switch (handler->flags) {
case EROFS_XATTR_INDEX_USER: case EROFS_XATTR_INDEX_USER:
if (!test_opt(sbi, XATTR_USER)) if (!test_opt(&sbi->ctx, XATTR_USER))
return -EOPNOTSUPP; return -EOPNOTSUPP;
break; break;
case EROFS_XATTR_INDEX_TRUSTED: case EROFS_XATTR_INDEX_TRUSTED:
......
...@@ -615,7 +615,7 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, ...@@ -615,7 +615,7 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe,
goto err_out; goto err_out;
/* preload all compressed pages (maybe downgrade role if necessary) */ /* preload all compressed pages (maybe downgrade role if necessary) */
if (should_alloc_managed_pages(fe, sbi->cache_strategy, map->m_la)) if (should_alloc_managed_pages(fe, sbi->ctx.cache_strategy, map->m_la))
cache_strategy = DELAYEDALLOC; cache_strategy = DELAYEDALLOC;
else else
cache_strategy = DONTALLOC; cache_strategy = DONTALLOC;
...@@ -1302,7 +1302,7 @@ static int z_erofs_readpage(struct file *file, struct page *page) ...@@ -1302,7 +1302,7 @@ static int z_erofs_readpage(struct file *file, struct page *page)
static bool should_decompress_synchronously(struct erofs_sb_info *sbi, static bool should_decompress_synchronously(struct erofs_sb_info *sbi,
unsigned int nr) unsigned int nr)
{ {
return nr <= sbi->max_sync_decompress_pages; return nr <= sbi->ctx.max_sync_decompress_pages;
} }
static int z_erofs_readpages(struct file *filp, struct address_space *mapping, static int z_erofs_readpages(struct file *filp, struct address_space *mapping,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment