Loading fs/overlayfs/overlayfs.h +8 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,14 @@ enum { OVL_XINO_ON, }; /* The set of options that user requested explicitly via mount options */ struct ovl_opt_set { bool metacopy; bool redirect; bool nfs_export; bool index; }; /* * The tuple (fh,uuid) is a universal unique identifier for a copy up origin, * where: Loading fs/overlayfs/super.c +127 −116 Original line number Diff line number Diff line Loading @@ -514,20 +514,17 @@ static char *ovl_next_opt(char **s) return sbegin; } static int ovl_parse_opt(char *opt, struct ovl_config *config) static int ovl_parse_opt(char *opt, struct ovl_config *config, struct ovl_opt_set *set) { char *p; bool metacopy_opt = false, redirect_opt = false; bool nfs_export_opt = false, index_opt = false; while ((p = ovl_next_opt(&opt)) != NULL) { int err = 0; int token; substring_t args[MAX_OPT_ARGS]; if (!*p) continue; if (!*opt) return 0; token = match_token(p, ovl_tokens, args); token = match_token(opt, ovl_tokens, args); switch (token) { case OPT_UPPERDIR: kfree(config->upperdir); Loading Loading @@ -556,34 +553,34 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) case OPT_REDIRECT_DIR_ON: config->redirect_mode = OVL_REDIRECT_ON; redirect_opt = true; set->redirect = true; break; case OPT_REDIRECT_DIR_OFF: config->redirect_mode = ovl_redirect_always_follow ? OVL_REDIRECT_FOLLOW : OVL_REDIRECT_NOFOLLOW; redirect_opt = true; set->redirect = true; break; case OPT_REDIRECT_DIR_FOLLOW: config->redirect_mode = OVL_REDIRECT_FOLLOW; redirect_opt = true; set->redirect = true; break; case OPT_REDIRECT_DIR_NOFOLLOW: config->redirect_mode = OVL_REDIRECT_NOFOLLOW; redirect_opt = true; set->redirect = true; break; case OPT_INDEX_ON: config->index = true; index_opt = true; set->index = true; break; case OPT_INDEX_OFF: config->index = false; index_opt = true; set->index = true; break; case OPT_UUID_ON: Loading @@ -596,12 +593,12 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) case OPT_NFS_EXPORT_ON: config->nfs_export = true; nfs_export_opt = true; set->nfs_export = true; break; case OPT_NFS_EXPORT_OFF: config->nfs_export = false; nfs_export_opt = true; set->nfs_export = true; break; case OPT_XINO_ON: Loading @@ -618,12 +615,12 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) case OPT_METACOPY_ON: config->metacopy = true; metacopy_opt = true; set->metacopy = true; break; case OPT_METACOPY_OFF: config->metacopy = false; metacopy_opt = true; set->metacopy = true; break; case OPT_VOLATILE: Loading @@ -636,9 +633,23 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) default: pr_err("unrecognized mount option \"%s\" or missing value\n", p); opt); return -EINVAL; } return err; } static int ovl_parse_options(char *opt, struct ovl_config *config) { char *p; int err; struct ovl_opt_set set = {}; while ((p = ovl_next_opt(&opt)) != NULL) { err = ovl_parse_opt(p, config, &set); if (err) return err; } /* Workdir/index are useless in non-upper mount */ Loading @@ -649,9 +660,9 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) kfree(config->workdir); config->workdir = NULL; } if (config->index && index_opt) { if (config->index && set.index) { pr_info("option \"index=on\" is useless in a non-upper mount, ignore\n"); index_opt = false; set.index = false; } config->index = false; } Loading @@ -670,12 +681,12 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) /* Resolve metacopy -> redirect_dir dependency */ if (config->metacopy && config->redirect_mode != OVL_REDIRECT_ON) { if (metacopy_opt && redirect_opt) { if (set.metacopy && set.redirect) { pr_err("conflicting options: metacopy=on,redirect_dir=%s\n", ovl_redirect_mode(config)); return -EINVAL; } if (redirect_opt) { if (set.redirect) { /* * There was an explicit redirect_dir=... that resulted * in this conflict. Loading @@ -695,10 +706,10 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) config->redirect_mode != OVL_REDIRECT_NOFOLLOW) { pr_info("NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n"); config->nfs_export = false; } else if (nfs_export_opt && index_opt) { } else if (set.nfs_export && set.index) { pr_err("conflicting options: nfs_export=on,index=off\n"); return -EINVAL; } else if (index_opt) { } else if (set.index) { /* * There was an explicit index=off that resulted * in this conflict. Loading @@ -713,11 +724,11 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) /* Resolve nfs_export -> !metacopy dependency */ if (config->nfs_export && config->metacopy) { if (nfs_export_opt && metacopy_opt) { if (set.nfs_export && set.metacopy) { pr_err("conflicting options: nfs_export=on,metacopy=on\n"); return -EINVAL; } if (metacopy_opt) { if (set.metacopy) { /* * There was an explicit metacopy=on that resulted * in this conflict. Loading @@ -737,13 +748,13 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) /* Resolve userxattr -> !redirect && !metacopy dependency */ if (config->userxattr) { if (redirect_opt && if (set.redirect && config->redirect_mode != OVL_REDIRECT_NOFOLLOW) { pr_err("conflicting options: userxattr,redirect_dir=%s\n", ovl_redirect_mode(config)); return -EINVAL; } if (config->metacopy && metacopy_opt) { if (config->metacopy && set.metacopy) { pr_err("conflicting options: userxattr,metacopy=on\n"); return -EINVAL; } Loading Loading @@ -1981,7 +1992,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) ofs->config.nfs_export = ovl_nfs_export_def; ofs->config.xino = ovl_xino_def(); ofs->config.metacopy = ovl_metacopy_def; err = ovl_parse_opt((char *) data, &ofs->config); err = ovl_parse_options((char *) data, &ofs->config); if (err) goto out_err; Loading Loading
fs/overlayfs/overlayfs.h +8 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,14 @@ enum { OVL_XINO_ON, }; /* The set of options that user requested explicitly via mount options */ struct ovl_opt_set { bool metacopy; bool redirect; bool nfs_export; bool index; }; /* * The tuple (fh,uuid) is a universal unique identifier for a copy up origin, * where: Loading
fs/overlayfs/super.c +127 −116 Original line number Diff line number Diff line Loading @@ -514,20 +514,17 @@ static char *ovl_next_opt(char **s) return sbegin; } static int ovl_parse_opt(char *opt, struct ovl_config *config) static int ovl_parse_opt(char *opt, struct ovl_config *config, struct ovl_opt_set *set) { char *p; bool metacopy_opt = false, redirect_opt = false; bool nfs_export_opt = false, index_opt = false; while ((p = ovl_next_opt(&opt)) != NULL) { int err = 0; int token; substring_t args[MAX_OPT_ARGS]; if (!*p) continue; if (!*opt) return 0; token = match_token(p, ovl_tokens, args); token = match_token(opt, ovl_tokens, args); switch (token) { case OPT_UPPERDIR: kfree(config->upperdir); Loading Loading @@ -556,34 +553,34 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) case OPT_REDIRECT_DIR_ON: config->redirect_mode = OVL_REDIRECT_ON; redirect_opt = true; set->redirect = true; break; case OPT_REDIRECT_DIR_OFF: config->redirect_mode = ovl_redirect_always_follow ? OVL_REDIRECT_FOLLOW : OVL_REDIRECT_NOFOLLOW; redirect_opt = true; set->redirect = true; break; case OPT_REDIRECT_DIR_FOLLOW: config->redirect_mode = OVL_REDIRECT_FOLLOW; redirect_opt = true; set->redirect = true; break; case OPT_REDIRECT_DIR_NOFOLLOW: config->redirect_mode = OVL_REDIRECT_NOFOLLOW; redirect_opt = true; set->redirect = true; break; case OPT_INDEX_ON: config->index = true; index_opt = true; set->index = true; break; case OPT_INDEX_OFF: config->index = false; index_opt = true; set->index = true; break; case OPT_UUID_ON: Loading @@ -596,12 +593,12 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) case OPT_NFS_EXPORT_ON: config->nfs_export = true; nfs_export_opt = true; set->nfs_export = true; break; case OPT_NFS_EXPORT_OFF: config->nfs_export = false; nfs_export_opt = true; set->nfs_export = true; break; case OPT_XINO_ON: Loading @@ -618,12 +615,12 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) case OPT_METACOPY_ON: config->metacopy = true; metacopy_opt = true; set->metacopy = true; break; case OPT_METACOPY_OFF: config->metacopy = false; metacopy_opt = true; set->metacopy = true; break; case OPT_VOLATILE: Loading @@ -636,9 +633,23 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) default: pr_err("unrecognized mount option \"%s\" or missing value\n", p); opt); return -EINVAL; } return err; } static int ovl_parse_options(char *opt, struct ovl_config *config) { char *p; int err; struct ovl_opt_set set = {}; while ((p = ovl_next_opt(&opt)) != NULL) { err = ovl_parse_opt(p, config, &set); if (err) return err; } /* Workdir/index are useless in non-upper mount */ Loading @@ -649,9 +660,9 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) kfree(config->workdir); config->workdir = NULL; } if (config->index && index_opt) { if (config->index && set.index) { pr_info("option \"index=on\" is useless in a non-upper mount, ignore\n"); index_opt = false; set.index = false; } config->index = false; } Loading @@ -670,12 +681,12 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) /* Resolve metacopy -> redirect_dir dependency */ if (config->metacopy && config->redirect_mode != OVL_REDIRECT_ON) { if (metacopy_opt && redirect_opt) { if (set.metacopy && set.redirect) { pr_err("conflicting options: metacopy=on,redirect_dir=%s\n", ovl_redirect_mode(config)); return -EINVAL; } if (redirect_opt) { if (set.redirect) { /* * There was an explicit redirect_dir=... that resulted * in this conflict. Loading @@ -695,10 +706,10 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) config->redirect_mode != OVL_REDIRECT_NOFOLLOW) { pr_info("NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n"); config->nfs_export = false; } else if (nfs_export_opt && index_opt) { } else if (set.nfs_export && set.index) { pr_err("conflicting options: nfs_export=on,index=off\n"); return -EINVAL; } else if (index_opt) { } else if (set.index) { /* * There was an explicit index=off that resulted * in this conflict. Loading @@ -713,11 +724,11 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) /* Resolve nfs_export -> !metacopy dependency */ if (config->nfs_export && config->metacopy) { if (nfs_export_opt && metacopy_opt) { if (set.nfs_export && set.metacopy) { pr_err("conflicting options: nfs_export=on,metacopy=on\n"); return -EINVAL; } if (metacopy_opt) { if (set.metacopy) { /* * There was an explicit metacopy=on that resulted * in this conflict. Loading @@ -737,13 +748,13 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) /* Resolve userxattr -> !redirect && !metacopy dependency */ if (config->userxattr) { if (redirect_opt && if (set.redirect && config->redirect_mode != OVL_REDIRECT_NOFOLLOW) { pr_err("conflicting options: userxattr,redirect_dir=%s\n", ovl_redirect_mode(config)); return -EINVAL; } if (config->metacopy && metacopy_opt) { if (config->metacopy && set.metacopy) { pr_err("conflicting options: userxattr,metacopy=on\n"); return -EINVAL; } Loading Loading @@ -1981,7 +1992,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) ofs->config.nfs_export = ovl_nfs_export_def; ofs->config.xino = ovl_xino_def(); ofs->config.metacopy = ovl_metacopy_def; err = ovl_parse_opt((char *) data, &ofs->config); err = ovl_parse_options((char *) data, &ofs->config); if (err) goto out_err; Loading