mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
shmem_parse_one(): switch to use of fs_parse()
This thing will eventually become our ->parse_param(), while shmem_parse_options() - ->parse_monolithic(). At that point shmem_parse_options() will start calling vfs_parse_fs_string(), rather than calling shmem_parse_one() directly. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
e04dc423ae
commit
626c3920ae
1 changed files with 118 additions and 69 deletions
187
mm/shmem.c
187
mm/shmem.c
|
@ -37,6 +37,7 @@
|
||||||
#include <linux/khugepaged.h>
|
#include <linux/khugepaged.h>
|
||||||
#include <linux/hugetlb.h>
|
#include <linux/hugetlb.h>
|
||||||
#include <linux/frontswap.h>
|
#include <linux/frontswap.h>
|
||||||
|
#include <linux/fs_parser.h>
|
||||||
|
|
||||||
#include <asm/tlbflush.h> /* for arch/microblaze update_mmu_cache() */
|
#include <asm/tlbflush.h> /* for arch/microblaze update_mmu_cache() */
|
||||||
|
|
||||||
|
@ -3363,15 +3364,63 @@ static const struct export_operations shmem_export_ops = {
|
||||||
.fh_to_dentry = shmem_fh_to_dentry,
|
.fh_to_dentry = shmem_fh_to_dentry,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int shmem_parse_one(struct shmem_options *ctx, char *opt, char *value)
|
enum shmem_param {
|
||||||
{
|
Opt_gid,
|
||||||
char *rest;
|
Opt_huge,
|
||||||
uid_t uid;
|
Opt_mode,
|
||||||
gid_t gid;
|
Opt_mpol,
|
||||||
|
Opt_nr_blocks,
|
||||||
|
Opt_nr_inodes,
|
||||||
|
Opt_size,
|
||||||
|
Opt_uid,
|
||||||
|
};
|
||||||
|
|
||||||
if (!strcmp(opt, "size")) {
|
static const struct fs_parameter_spec shmem_param_specs[] = {
|
||||||
unsigned long long size;
|
fsparam_u32 ("gid", Opt_gid),
|
||||||
size = memparse(value,&rest);
|
fsparam_enum ("huge", Opt_huge),
|
||||||
|
fsparam_u32oct("mode", Opt_mode),
|
||||||
|
fsparam_string("mpol", Opt_mpol),
|
||||||
|
fsparam_string("nr_blocks", Opt_nr_blocks),
|
||||||
|
fsparam_string("nr_inodes", Opt_nr_inodes),
|
||||||
|
fsparam_string("size", Opt_size),
|
||||||
|
fsparam_u32 ("uid", Opt_uid),
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct fs_parameter_enum shmem_param_enums[] = {
|
||||||
|
{ Opt_huge, "never", SHMEM_HUGE_NEVER },
|
||||||
|
{ Opt_huge, "always", SHMEM_HUGE_ALWAYS },
|
||||||
|
{ Opt_huge, "within_size", SHMEM_HUGE_WITHIN_SIZE },
|
||||||
|
{ Opt_huge, "advise", SHMEM_HUGE_ADVISE },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct fs_parameter_description shmem_fs_parameters = {
|
||||||
|
.name = "tmpfs",
|
||||||
|
.specs = shmem_param_specs,
|
||||||
|
.enums = shmem_param_enums,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int shmem_parse_one(struct shmem_options *ctx,
|
||||||
|
struct fs_parameter *param)
|
||||||
|
{
|
||||||
|
struct fs_context *fc = NULL;
|
||||||
|
struct fs_parse_result result;
|
||||||
|
unsigned long long size;
|
||||||
|
char *rest;
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
opt = fs_parse(fc, &shmem_fs_parameters, param, &result);
|
||||||
|
if (opt < 0) {
|
||||||
|
if (opt == -ENOPARAM)
|
||||||
|
return invalf(fc, "tmpfs: Unknown parameter '%s'",
|
||||||
|
param->key);
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opt) {
|
||||||
|
case Opt_size:
|
||||||
|
size = memparse(param->string, &rest);
|
||||||
if (*rest == '%') {
|
if (*rest == '%') {
|
||||||
size <<= PAGE_SHIFT;
|
size <<= PAGE_SHIFT;
|
||||||
size *= totalram_pages();
|
size *= totalram_pages();
|
||||||
|
@ -3379,74 +3428,65 @@ static int shmem_parse_one(struct shmem_options *ctx, char *opt, char *value)
|
||||||
rest++;
|
rest++;
|
||||||
}
|
}
|
||||||
if (*rest)
|
if (*rest)
|
||||||
goto bad_val;
|
goto bad_value;
|
||||||
ctx->blocks = DIV_ROUND_UP(size, PAGE_SIZE);
|
ctx->blocks = DIV_ROUND_UP(size, PAGE_SIZE);
|
||||||
ctx->seen |= SHMEM_SEEN_BLOCKS;
|
ctx->seen |= SHMEM_SEEN_BLOCKS;
|
||||||
} else if (!strcmp(opt, "nr_blocks")) {
|
break;
|
||||||
ctx->blocks = memparse(value, &rest);
|
case Opt_nr_blocks:
|
||||||
|
ctx->blocks = memparse(param->string, &rest);
|
||||||
if (*rest)
|
if (*rest)
|
||||||
goto bad_val;
|
goto bad_value;
|
||||||
ctx->seen |= SHMEM_SEEN_BLOCKS;
|
ctx->seen |= SHMEM_SEEN_BLOCKS;
|
||||||
} else if (!strcmp(opt, "nr_inodes")) {
|
break;
|
||||||
ctx->inodes = memparse(value, &rest);
|
case Opt_nr_inodes:
|
||||||
|
ctx->inodes = memparse(param->string, &rest);
|
||||||
if (*rest)
|
if (*rest)
|
||||||
goto bad_val;
|
goto bad_value;
|
||||||
ctx->seen |= SHMEM_SEEN_INODES;
|
ctx->seen |= SHMEM_SEEN_INODES;
|
||||||
} else if (!strcmp(opt, "mode")) {
|
break;
|
||||||
ctx->mode = simple_strtoul(value, &rest, 8) & 07777;
|
case Opt_mode:
|
||||||
if (*rest)
|
ctx->mode = result.uint_32 & 07777;
|
||||||
goto bad_val;
|
break;
|
||||||
} else if (!strcmp(opt, "uid")) {
|
case Opt_uid:
|
||||||
uid = simple_strtoul(value, &rest, 0);
|
ctx->uid = make_kuid(current_user_ns(), result.uint_32);
|
||||||
if (*rest)
|
|
||||||
goto bad_val;
|
|
||||||
ctx->uid = make_kuid(current_user_ns(), uid);
|
|
||||||
if (!uid_valid(ctx->uid))
|
if (!uid_valid(ctx->uid))
|
||||||
goto bad_val;
|
goto bad_value;
|
||||||
} else if (!strcmp(opt, "gid")) {
|
break;
|
||||||
gid = simple_strtoul(value, &rest, 0);
|
case Opt_gid:
|
||||||
if (*rest)
|
ctx->gid = make_kgid(current_user_ns(), result.uint_32);
|
||||||
goto bad_val;
|
|
||||||
ctx->gid = make_kgid(current_user_ns(), gid);
|
|
||||||
if (!gid_valid(ctx->gid))
|
if (!gid_valid(ctx->gid))
|
||||||
goto bad_val;
|
goto bad_value;
|
||||||
#ifdef CONFIG_TRANSPARENT_HUGE_PAGECACHE
|
break;
|
||||||
} else if (!strcmp(opt, "huge")) {
|
case Opt_huge:
|
||||||
int huge;
|
ctx->huge = result.uint_32;
|
||||||
huge = shmem_parse_huge(value);
|
if (ctx->huge != SHMEM_HUGE_NEVER &&
|
||||||
if (huge < 0)
|
!(IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE) &&
|
||||||
goto bad_val;
|
has_transparent_hugepage()))
|
||||||
if (!has_transparent_hugepage() &&
|
goto unsupported_parameter;
|
||||||
huge != SHMEM_HUGE_NEVER)
|
|
||||||
goto bad_val;
|
|
||||||
ctx->huge = huge;
|
|
||||||
ctx->seen |= SHMEM_SEEN_HUGE;
|
ctx->seen |= SHMEM_SEEN_HUGE;
|
||||||
#endif
|
break;
|
||||||
#ifdef CONFIG_NUMA
|
case Opt_mpol:
|
||||||
} else if (!strcmp(opt, "mpol")) {
|
if (IS_ENABLED(CONFIG_NUMA)) {
|
||||||
mpol_put(ctx->mpol);
|
mpol_put(ctx->mpol);
|
||||||
ctx->mpol = NULL;
|
ctx->mpol = NULL;
|
||||||
if (mpol_parse_str(value, &ctx->mpol))
|
if (mpol_parse_str(param->string, &ctx->mpol))
|
||||||
goto bad_val;
|
goto bad_value;
|
||||||
#endif
|
break;
|
||||||
} else {
|
}
|
||||||
pr_err("tmpfs: Bad mount option %s\n", opt);
|
goto unsupported_parameter;
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bad_val:
|
unsupported_parameter:
|
||||||
pr_err("tmpfs: Bad value '%s' for mount option '%s'\n",
|
return invalf(fc, "tmpfs: Unsupported parameter '%s'", param->key);
|
||||||
value, opt);
|
bad_value:
|
||||||
return -EINVAL;
|
return invalf(fc, "tmpfs: Bad value for '%s'", param->key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int shmem_parse_options(char *options, struct shmem_options *ctx)
|
static int shmem_parse_options(char *options, struct shmem_options *ctx)
|
||||||
{
|
{
|
||||||
char *this_char, *value;
|
|
||||||
|
|
||||||
while (options != NULL) {
|
while (options != NULL) {
|
||||||
this_char = options;
|
char *this_char = options;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/*
|
/*
|
||||||
* NUL-terminate this option: unfortunately,
|
* NUL-terminate this option: unfortunately,
|
||||||
|
@ -3462,17 +3502,26 @@ static int shmem_parse_options(char *options, struct shmem_options *ctx)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!*this_char)
|
if (*this_char) {
|
||||||
continue;
|
char *value = strchr(this_char,'=');
|
||||||
if ((value = strchr(this_char,'=')) != NULL) {
|
struct fs_parameter param = {
|
||||||
*value++ = 0;
|
.key = this_char,
|
||||||
} else {
|
.type = fs_value_is_string,
|
||||||
pr_err("tmpfs: No value for mount option '%s'\n",
|
};
|
||||||
this_char);
|
int err;
|
||||||
goto error;
|
|
||||||
|
if (value) {
|
||||||
|
*value++ = '\0';
|
||||||
|
param.size = strlen(value);
|
||||||
|
param.string = kstrdup(value, GFP_KERNEL);
|
||||||
|
if (!param.string)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
err = shmem_parse_one(ctx, ¶m);
|
||||||
|
kfree(param.string);
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
if (shmem_parse_one(ctx, this_char, value) < 0)
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue