From: "J. R. Okajima" <hooanon...@gmail.com> commit 4fdd4d3893306b2a70f38a83c9b2e4d5b55a0796 aufs5-standalone upstream.
Adds parsing mount options as fs_context operations, which was started by the preceding commit. This "fs_context" series essentially moves some parts of opts.c to fsctx.c, and adjusts it to fit fs_context scheme. No enhancements, no bugfixes. Since some parts of opts.c are moved out, this commit makes aufs unusable but compilable. As a first step, we start it by "br" mount option. The other options will follow by the succeeding commits. Signed-off-by: J. R. Okajima <hooanon...@gmail.com> Signed-off-by: Paul Gortmaker <paul.gortma...@windriver.com> --- fs/aufs/fsctx.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++- fs/aufs/opts.c | 67 +++------------ fs/aufs/opts.h | 37 +++++++- 3 files changed, 268 insertions(+), 59 deletions(-) diff --git a/fs/aufs/fsctx.c b/fs/aufs/fsctx.c index f02cc9005d95..92ead39cbbaa 100644 --- a/fs/aufs/fsctx.c +++ b/fs/aufs/fsctx.c @@ -11,12 +11,227 @@ #include "aufs.h" struct au_fsctx_opts { + aufs_bindex_t bindex; + unsigned char skipped; struct au_opt *opt, *opt_tail; struct super_block *sb; struct au_sbinfo *sbinfo; struct au_opts opts; }; +static void au_fsctx_dump(struct au_opts *opts) +{ +#ifdef CONFIG_AUFS_DEBUG + /* reduce stack space */ + union { + struct au_opt_add *add; + } u; + struct au_opt *opt; + + opt = opts->opt; + while (opt->type != Opt_tail) { + switch (opt->type) { + case Opt_add: + u.add = &opt->add; + AuDbg("add {b%d, %s, 0x%x, %p}\n", + u.add->bindex, u.add->pathname, u.add->perm, + u.add->path.dentry); + break; + /* re-commit later */ + + default: + BUG(); + } + opt++; + } +#endif +} + +/* ---------------------------------------------------------------------- */ + +const struct fs_parameter_spec aufs_fsctx_paramspec[] = { + fsparam_string("br", Opt_br), + /* re-commit later */ + + {} +}; + +static int au_fsctx_parse_do_add(struct fs_context *fc, struct au_opt *opt, + char *brspec, size_t speclen, + aufs_bindex_t bindex) +{ + int err; + char *p; + + AuDbg("brspec %s\n", brspec); + + err = -ENOMEM; + if (!speclen) + speclen = strlen(brspec); + /* will be freed by au_fsctx_free() */ + p = kmemdup_nul(brspec, speclen, GFP_NOFS); + if (unlikely(!p)) { + errorfc(fc, "failed in %s", brspec); + goto out; + } + err = au_opt_add(opt, p, fc->sb_flags, bindex); + +out: + AuTraceErr(err); + return err; +} + +static int au_fsctx_parse_br(struct fs_context *fc, char *brspec) +{ + int err; + char *p; + struct au_fsctx_opts *a = fc->fs_private; + struct au_opt *opt = a->opt; + aufs_bindex_t bindex = a->bindex; + + AuDbg("brspec %s\n", brspec); + + err = -EINVAL; + while ((p = strsep(&brspec, ":")) && *p) { + err = au_fsctx_parse_do_add(fc, opt, p, /*len*/0, bindex); + AuTraceErr(err); + if (unlikely(err)) + break; + bindex++; + opt++; + if (unlikely(opt > a->opt_tail)) { + err = -E2BIG; + bindex--; + opt--; + break; + } + opt->type = Opt_tail; + a->skipped = 1; + } + a->bindex = bindex; + a->opt = opt; + + AuTraceErr(err); + return err; +} + +static int au_fsctx_parse_param(struct fs_context *fc, struct fs_parameter *param) +{ + int err, token; + struct fs_parse_result result; + struct au_fsctx_opts *a = fc->fs_private; + struct au_opt *opt = a->opt; + + AuDbg("fc %p, param {key %s, string %s}\n", + fc, param->key, param->string); + err = fs_parse(fc, aufs_fsctx_paramspec, param, &result); + if (unlikely(err < 0)) + goto out; + token = err; + AuDbg("token %d, res{negated %d, uint64 %llu}\n", + token, result.negated, result.uint_64); + + err = -EINVAL; + a->skipped = 0; + switch (token) { + case Opt_br: + err = au_fsctx_parse_br(fc, param->string); + break; + /* re-commit later */ + + default: + a->skipped = 1; + err = -ENOPARAM; + break; + } + if (unlikely(err)) + goto out; + if (a->skipped) + goto out; + + switch (token) { + case Opt_br: + break; + default: + opt->type = token; + break; + } + opt++; + if (unlikely(opt > a->opt_tail)) { + err = -E2BIG; + opt--; + } + opt->type = Opt_tail; + a->opt = opt; + +out: + return err; +} + +/* + * these options accept both 'name=val' and 'name:val' form. + * some accept optional '=' in its value. + * eg. br:/br1=rw:/br2=ro and br=/br1=rw:/br2=ro + */ +static inline unsigned int is_colonopt(char *str) +{ +#define do_test(name) \ + if (!strncmp(str, name ":", sizeof(name))) \ + return sizeof(name) - 1; + do_test("br"); + /* re-commit later */ +#undef do_test + + return 0; +} + +static int au_fsctx_parse_monolithic(struct fs_context *fc, void *data) +{ + int err; + unsigned int u; + char *str; + struct au_fsctx_opts *a = fc->fs_private; + + str = data; + AuDbg("str %s\n", str); + while (1) { + u = is_colonopt(str); + if (u) + str[u] = '='; + str = strchr(str, ','); + if (!str) + break; + str++; + } + str = data; + AuDbg("str %s\n", str); + + err = generic_parse_monolithic(fc, str); + AuTraceErr(err); + au_fsctx_dump(&a->opts); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +static void au_fsctx_opts_free(struct au_opts *opts) +{ + struct au_opt *opt; + + opt = opts->opt; + while (opt->type != Opt_tail) { + switch (opt->type) { + case Opt_add: + kfree(opt->add.pathname); + path_put(&opt->add.path); + break; + /* re-commit later */ + } + opt++; + } +} + static void au_fsctx_free(struct fs_context *fc) { struct au_fsctx_opts *a = fc->fs_private; @@ -26,12 +241,15 @@ static void au_fsctx_free(struct fs_context *fc) fc, fc->sb_flags, fc->sb_flags_mask, fc->purpose); kobject_put(&a->sbinfo->si_kobj); + au_fsctx_opts_free(&a->opts); free_page((unsigned long)a->opts.opt); au_kfree_rcu(a); } static const struct fs_context_operations au_fsctx_ops = { - .free = au_fsctx_free + .free = au_fsctx_free, + .parse_param = au_fsctx_parse_param, + .parse_monolithic = au_fsctx_parse_monolithic /* re-commit later */ }; @@ -49,11 +267,12 @@ int aufs_fsctx_init(struct fs_context *fc) a = kzalloc(sizeof(*a), GFP_NOFS); if (unlikely(!a)) goto out; + a->bindex = 0; a->opts.opt = (void *)__get_free_page(GFP_NOFS); if (unlikely(!a->opts.opt)) goto out_a; a->opt = a->opts.opt; - a->opt->type = 0; /* re-commit later */ + a->opt->type = Opt_tail; a->opts.max_opt = PAGE_SIZE / sizeof(*a->opts.opt); a->opt_tail = a->opt + a->opts.max_opt - 1; a->opts.sb_flags = fc->sb_flags; diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c index b5dde6856069..ab232e5b8c58 100644 --- a/fs/aufs/opts.c +++ b/fs/aufs/opts.c @@ -26,36 +26,7 @@ /* ---------------------------------------------------------------------- */ -enum { - Opt_br, - Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend, - Opt_idel, Opt_imod, - Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, - Opt_rdblk_def, Opt_rdhash_def, - Opt_xino, Opt_noxino, - Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, - Opt_trunc_xino_path, Opt_itrunc_xino, - Opt_trunc_xib, Opt_notrunc_xib, - Opt_shwh, Opt_noshwh, - Opt_plink, Opt_noplink, Opt_list_plink, - Opt_udba, - Opt_dio, Opt_nodio, - Opt_diropq_a, Opt_diropq_w, - Opt_warn_perm, Opt_nowarn_perm, - Opt_wbr_copyup, Opt_wbr_create, - Opt_fhsm_sec, - Opt_verbose, Opt_noverbose, - Opt_sum, Opt_nosum, Opt_wsum, - Opt_dirperm1, Opt_nodirperm1, - Opt_dirren, Opt_nodirren, - Opt_acl, Opt_noacl, - Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err -}; - static match_table_t options = { - {Opt_br, "br=%s"}, - {Opt_br, "br:%s"}, - {Opt_add, "add=%d:%s"}, {Opt_add, "add:%d:%s"}, {Opt_add, "ins=%d:%s"}, @@ -183,8 +154,6 @@ static match_table_t options = { {Opt_err, NULL} }; -/* ---------------------------------------------------------------------- */ - static const char *au_parser_pattern(int val, match_table_t tbl) { struct match_token *p; @@ -316,7 +285,7 @@ static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm) return q - str->a; } -static int noinline_for_stack br_perm_val(char *perm) +int au_br_perm_val(char *perm) { int val, bad, sz; char *p; @@ -776,8 +745,8 @@ void au_opts_free(struct au_opts *opts) } } -static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, - aufs_bindex_t bindex) +int au_opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, + aufs_bindex_t bindex) { int err; struct au_opt_add *add = &opt->add; @@ -790,7 +759,7 @@ static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, if (p) { *p++ = 0; if (*p) - add->perm = br_perm_val(p); + add->perm = au_br_perm_val(p); } err = vfsub_kern_path(add->pathname, AuOpt_LkupDirFlags, &add->path); @@ -873,7 +842,7 @@ au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[]) goto out; } - mod->perm = br_perm_val(p); + mod->perm = au_br_perm_val(p); AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p); mod->h_root = dget(path.dentry); path_put(&path); @@ -1007,40 +976,26 @@ int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) skipped = 0; token = match_token(opt_str, options, a->args); switch (token) { - case Opt_br: - err = 0; - while (!err && (opt_str = strsep(&a->args[0].from, ":")) - && *opt_str) { - err = opt_add(opt, opt_str, opts->sb_flags, - bindex++); - if (unlikely(!err && ++opt > opt_tail)) { - err = -E2BIG; - break; - } - opt->type = Opt_tail; - skipped = 1; - } - break; case Opt_add: if (unlikely(match_int(&a->args[0], &n))) { pr_err("bad integer in %s\n", opt_str); break; } bindex = n; - err = opt_add(opt, a->args[1].from, opts->sb_flags, - bindex); + err = au_opt_add(opt, a->args[1].from, opts->sb_flags, + bindex); if (!err) opt->type = token; break; case Opt_append: - err = opt_add(opt, a->args[0].from, opts->sb_flags, - /*dummy bindex*/1); + err = au_opt_add(opt, a->args[0].from, opts->sb_flags, + /*dummy bindex*/1); if (!err) opt->type = token; break; case Opt_prepend: - err = opt_add(opt, a->args[0].from, opts->sb_flags, - /*bindex*/0); + err = au_opt_add(opt, a->args[0].from, opts->sb_flags, + /*bindex*/0); if (!err) opt->type = token; break; diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h index 98486c6b6579..ba948bb05fad 100644 --- a/fs/aufs/opts.h +++ b/fs/aufs/opts.h @@ -25,10 +25,36 @@ #ifdef __KERNEL__ +#include <linux/fs_parser.h> #include <linux/namei.h> #include <linux/path.h> -struct file; +enum { + Opt_br, + /* re-commit later */ + Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend, + Opt_idel, Opt_imod, + Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, + Opt_rdblk_def, Opt_rdhash_def, + Opt_xino, Opt_noxino, + Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, + Opt_trunc_xino_path, Opt_itrunc_xino, + Opt_trunc_xib, Opt_notrunc_xib, + Opt_shwh, Opt_noshwh, + Opt_plink, Opt_noplink, Opt_list_plink, + Opt_udba, + Opt_dio, Opt_nodio, + Opt_diropq_a, Opt_diropq_w, + Opt_warn_perm, Opt_nowarn_perm, + Opt_wbr_copyup, Opt_wbr_create, + Opt_fhsm_sec, + Opt_verbose, Opt_noverbose, + Opt_sum, Opt_nosum, Opt_wsum, + Opt_dirperm1, Opt_nodirperm1, + Opt_dirren, Opt_nodirren, + Opt_acl, Opt_noacl, + Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err +}; /* ---------------------------------------------------------------------- */ @@ -127,6 +153,8 @@ enum { /* ---------------------------------------------------------------------- */ +struct file; + struct au_opt_add { aufs_bindex_t bindex; char *pathname; @@ -209,12 +237,15 @@ struct au_opts { /* ---------------------------------------------------------------------- */ /* opts.c */ +int au_br_perm_val(char *perm); void au_optstr_br_perm(au_br_perm_str_t *str, int perm); const char *au_optstr_udba(int udba); const char *au_optstr_wbr_copyup(int wbr_copyup); const char *au_optstr_wbr_create(int wbr_create); void au_opts_free(struct au_opts *opts); +int au_opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, + aufs_bindex_t bindex); struct super_block; int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts); int au_opts_verify(struct super_block *sb, unsigned long sb_flags, @@ -224,5 +255,9 @@ int au_opts_remount(struct super_block *sb, struct au_opts *opts); unsigned int au_opt_udba(struct super_block *sb); +/* fsctx.c */ +int aufs_fsctx_init(struct fs_context *fc); +extern const struct fs_parameter_spec aufs_fsctx_paramspec[]; + #endif /* __KERNEL__ */ #endif /* __AUFS_OPTS_H__ */ -- 2.17.1
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#11069): https://lists.yoctoproject.org/g/linux-yocto/message/11069 Mute This Topic: https://lists.yoctoproject.org/mt/90000699/21656 Group Owner: linux-yocto+ow...@lists.yoctoproject.org Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-