Commit ac519625 authored by Amir Goldstein's avatar Amir Goldstein

ovl: factor out ovl_parse_options() helper

For parsing a single mount option.
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
parent af5f2396
...@@ -70,6 +70,14 @@ enum { ...@@ -70,6 +70,14 @@ enum {
OVL_XINO_ON, 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, * The tuple (fh,uuid) is a universal unique identifier for a copy up origin,
* where: * where:
......
...@@ -514,131 +514,142 @@ static char *ovl_next_opt(char **s) ...@@ -514,131 +514,142 @@ static char *ovl_next_opt(char **s)
return sbegin; 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; int err = 0;
bool metacopy_opt = false, redirect_opt = false; int token;
bool nfs_export_opt = false, index_opt = false; substring_t args[MAX_OPT_ARGS];
while ((p = ovl_next_opt(&opt)) != NULL) {
int token;
substring_t args[MAX_OPT_ARGS];
if (!*p)
continue;
token = match_token(p, ovl_tokens, args); if (!*opt)
switch (token) { return 0;
case OPT_UPPERDIR:
kfree(config->upperdir);
config->upperdir = match_strdup(&args[0]);
if (!config->upperdir)
return -ENOMEM;
break;
case OPT_LOWERDIR: token = match_token(opt, ovl_tokens, args);
kfree(config->lowerdir); switch (token) {
config->lowerdir = match_strdup(&args[0]); case OPT_UPPERDIR:
if (!config->lowerdir) kfree(config->upperdir);
return -ENOMEM; config->upperdir = match_strdup(&args[0]);
break; if (!config->upperdir)
return -ENOMEM;
break;
case OPT_LOWERDIR:
kfree(config->lowerdir);
config->lowerdir = match_strdup(&args[0]);
if (!config->lowerdir)
return -ENOMEM;
break;
case OPT_WORKDIR:
kfree(config->workdir);
config->workdir = match_strdup(&args[0]);
if (!config->workdir)
return -ENOMEM;
break;
case OPT_DEFAULT_PERMISSIONS:
config->default_permissions = true;
break;
case OPT_REDIRECT_DIR_ON:
config->redirect_mode = OVL_REDIRECT_ON;
set->redirect = true;
break;
case OPT_REDIRECT_DIR_OFF:
config->redirect_mode = ovl_redirect_always_follow ?
OVL_REDIRECT_FOLLOW :
OVL_REDIRECT_NOFOLLOW;
set->redirect = true;
break;
case OPT_REDIRECT_DIR_FOLLOW:
config->redirect_mode = OVL_REDIRECT_FOLLOW;
set->redirect = true;
break;
case OPT_REDIRECT_DIR_NOFOLLOW:
config->redirect_mode = OVL_REDIRECT_NOFOLLOW;
set->redirect = true;
break;
case OPT_WORKDIR: case OPT_INDEX_ON:
kfree(config->workdir); config->index = true;
config->workdir = match_strdup(&args[0]); set->index = true;
if (!config->workdir) break;
return -ENOMEM;
break;
case OPT_DEFAULT_PERMISSIONS: case OPT_INDEX_OFF:
config->default_permissions = true; config->index = false;
break; set->index = true;
break;
case OPT_REDIRECT_DIR_ON: case OPT_UUID_ON:
config->redirect_mode = OVL_REDIRECT_ON; config->uuid = true;
redirect_opt = true; break;
break;
case OPT_REDIRECT_DIR_OFF: case OPT_UUID_OFF:
config->redirect_mode = ovl_redirect_always_follow ? config->uuid = false;
OVL_REDIRECT_FOLLOW : break;
OVL_REDIRECT_NOFOLLOW;
redirect_opt = true;
break;
case OPT_REDIRECT_DIR_FOLLOW: case OPT_NFS_EXPORT_ON:
config->redirect_mode = OVL_REDIRECT_FOLLOW; config->nfs_export = true;
redirect_opt = true; set->nfs_export = true;
break; break;
case OPT_REDIRECT_DIR_NOFOLLOW: case OPT_NFS_EXPORT_OFF:
config->redirect_mode = OVL_REDIRECT_NOFOLLOW; config->nfs_export = false;
redirect_opt = true; set->nfs_export = true;
break; break;
case OPT_INDEX_ON: case OPT_XINO_ON:
config->index = true; config->xino = OVL_XINO_ON;
index_opt = true; break;
break;
case OPT_INDEX_OFF: case OPT_XINO_OFF:
config->index = false; config->xino = OVL_XINO_OFF;
index_opt = true; break;
break;
case OPT_UUID_ON: case OPT_XINO_AUTO:
config->uuid = true; config->xino = OVL_XINO_AUTO;
break; break;
case OPT_UUID_OFF: case OPT_METACOPY_ON:
config->uuid = false; config->metacopy = true;
break; set->metacopy = true;
break;
case OPT_NFS_EXPORT_ON: case OPT_METACOPY_OFF:
config->nfs_export = true; config->metacopy = false;
nfs_export_opt = true; set->metacopy = true;
break; break;
case OPT_NFS_EXPORT_OFF:
config->nfs_export = false;
nfs_export_opt = true;
break;
case OPT_XINO_ON:
config->xino = OVL_XINO_ON;
break;
case OPT_XINO_OFF:
config->xino = OVL_XINO_OFF;
break;
case OPT_XINO_AUTO: case OPT_VOLATILE:
config->xino = OVL_XINO_AUTO; config->ovl_volatile = true;
break; break;
case OPT_METACOPY_ON: case OPT_USERXATTR:
config->metacopy = true; config->userxattr = true;
metacopy_opt = true; break;
break;
case OPT_METACOPY_OFF: default:
config->metacopy = false; pr_err("unrecognized mount option \"%s\" or missing value\n",
metacopy_opt = true; opt);
break; return -EINVAL;
}
case OPT_VOLATILE: return err;
config->ovl_volatile = true; }
break;
case OPT_USERXATTR: static int ovl_parse_options(char *opt, struct ovl_config *config)
config->userxattr = true; {
break; char *p;
int err;
struct ovl_opt_set set = {};
default: while ((p = ovl_next_opt(&opt)) != NULL) {
pr_err("unrecognized mount option \"%s\" or missing value\n", err = ovl_parse_opt(p, config, &set);
p); if (err)
return -EINVAL; return err;
}
} }
/* Workdir/index are useless in non-upper mount */ /* Workdir/index are useless in non-upper mount */
...@@ -649,9 +660,9 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) ...@@ -649,9 +660,9 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
kfree(config->workdir); kfree(config->workdir);
config->workdir = NULL; 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"); pr_info("option \"index=on\" is useless in a non-upper mount, ignore\n");
index_opt = false; set.index = false;
} }
config->index = false; config->index = false;
} }
...@@ -670,12 +681,12 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) ...@@ -670,12 +681,12 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
/* Resolve metacopy -> redirect_dir dependency */ /* Resolve metacopy -> redirect_dir dependency */
if (config->metacopy && config->redirect_mode != OVL_REDIRECT_ON) { 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", pr_err("conflicting options: metacopy=on,redirect_dir=%s\n",
ovl_redirect_mode(config)); ovl_redirect_mode(config));
return -EINVAL; return -EINVAL;
} }
if (redirect_opt) { if (set.redirect) {
/* /*
* There was an explicit redirect_dir=... that resulted * There was an explicit redirect_dir=... that resulted
* in this conflict. * in this conflict.
...@@ -695,10 +706,10 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) ...@@ -695,10 +706,10 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
config->redirect_mode != OVL_REDIRECT_NOFOLLOW) { 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"); pr_info("NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n");
config->nfs_export = false; 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"); pr_err("conflicting options: nfs_export=on,index=off\n");
return -EINVAL; return -EINVAL;
} else if (index_opt) { } else if (set.index) {
/* /*
* There was an explicit index=off that resulted * There was an explicit index=off that resulted
* in this conflict. * in this conflict.
...@@ -713,11 +724,11 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) ...@@ -713,11 +724,11 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
/* Resolve nfs_export -> !metacopy dependency */ /* Resolve nfs_export -> !metacopy dependency */
if (config->nfs_export && config->metacopy) { 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"); pr_err("conflicting options: nfs_export=on,metacopy=on\n");
return -EINVAL; return -EINVAL;
} }
if (metacopy_opt) { if (set.metacopy) {
/* /*
* There was an explicit metacopy=on that resulted * There was an explicit metacopy=on that resulted
* in this conflict. * in this conflict.
...@@ -737,13 +748,13 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) ...@@ -737,13 +748,13 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
/* Resolve userxattr -> !redirect && !metacopy dependency */ /* Resolve userxattr -> !redirect && !metacopy dependency */
if (config->userxattr) { if (config->userxattr) {
if (redirect_opt && if (set.redirect &&
config->redirect_mode != OVL_REDIRECT_NOFOLLOW) { config->redirect_mode != OVL_REDIRECT_NOFOLLOW) {
pr_err("conflicting options: userxattr,redirect_dir=%s\n", pr_err("conflicting options: userxattr,redirect_dir=%s\n",
ovl_redirect_mode(config)); ovl_redirect_mode(config));
return -EINVAL; return -EINVAL;
} }
if (config->metacopy && metacopy_opt) { if (config->metacopy && set.metacopy) {
pr_err("conflicting options: userxattr,metacopy=on\n"); pr_err("conflicting options: userxattr,metacopy=on\n");
return -EINVAL; return -EINVAL;
} }
...@@ -1981,7 +1992,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) ...@@ -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.nfs_export = ovl_nfs_export_def;
ofs->config.xino = ovl_xino_def(); ofs->config.xino = ovl_xino_def();
ofs->config.metacopy = ovl_metacopy_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) if (err)
goto out_err; goto out_err;
......
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