summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2019-09-08 20:28:06 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2019-09-12 21:01:32 -0400
commit626c3920aeb4575f53c96b0d4ad4e651a21cbb66 (patch)
treeb49fe10845e92e8515f9c2a1f8599ac9f5757e2d
parente04dc423ae2c0fc862fef6b43ed9083226375e98 (diff)
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>
-rw-r--r--mm/shmem.c183
1 files changed, 116 insertions, 67 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index b392a8263329..6a41595dd1b3 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -37,6 +37,7 @@
37#include <linux/khugepaged.h> 37#include <linux/khugepaged.h>
38#include <linux/hugetlb.h> 38#include <linux/hugetlb.h>
39#include <linux/frontswap.h> 39#include <linux/frontswap.h>
40#include <linux/fs_parser.h>
40 41
41#include <asm/tlbflush.h> /* for arch/microblaze update_mmu_cache() */ 42#include <asm/tlbflush.h> /* for arch/microblaze update_mmu_cache() */
42 43
@@ -3363,15 +3364,63 @@ static const struct export_operations shmem_export_ops = {
3363 .fh_to_dentry = shmem_fh_to_dentry, 3364 .fh_to_dentry = shmem_fh_to_dentry,
3364}; 3365};
3365 3366
3366static int shmem_parse_one(struct shmem_options *ctx, char *opt, char *value) 3367enum shmem_param {
3368 Opt_gid,
3369 Opt_huge,
3370 Opt_mode,
3371 Opt_mpol,
3372 Opt_nr_blocks,
3373 Opt_nr_inodes,
3374 Opt_size,
3375 Opt_uid,
3376};
3377
3378static const struct fs_parameter_spec shmem_param_specs[] = {
3379 fsparam_u32 ("gid", Opt_gid),
3380 fsparam_enum ("huge", Opt_huge),
3381 fsparam_u32oct("mode", Opt_mode),
3382 fsparam_string("mpol", Opt_mpol),
3383 fsparam_string("nr_blocks", Opt_nr_blocks),
3384 fsparam_string("nr_inodes", Opt_nr_inodes),
3385 fsparam_string("size", Opt_size),
3386 fsparam_u32 ("uid", Opt_uid),
3387 {}
3388};
3389
3390static const struct fs_parameter_enum shmem_param_enums[] = {
3391 { Opt_huge, "never", SHMEM_HUGE_NEVER },
3392 { Opt_huge, "always", SHMEM_HUGE_ALWAYS },
3393 { Opt_huge, "within_size", SHMEM_HUGE_WITHIN_SIZE },
3394 { Opt_huge, "advise", SHMEM_HUGE_ADVISE },
3395 {}
3396};
3397
3398const struct fs_parameter_description shmem_fs_parameters = {
3399 .name = "tmpfs",
3400 .specs = shmem_param_specs,
3401 .enums = shmem_param_enums,
3402};
3403
3404static int shmem_parse_one(struct shmem_options *ctx,
3405 struct fs_parameter *param)
3367{ 3406{
3407 struct fs_context *fc = NULL;
3408 struct fs_parse_result result;
3409 unsigned long long size;
3368 char *rest; 3410 char *rest;
3369 uid_t uid; 3411 int opt;
3370 gid_t gid; 3412
3413 opt = fs_parse(fc, &shmem_fs_parameters, param, &result);
3414 if (opt < 0) {
3415 if (opt == -ENOPARAM)
3416 return invalf(fc, "tmpfs: Unknown parameter '%s'",
3417 param->key);
3418 return opt;
3419 }
3371 3420
3372 if (!strcmp(opt, "size")) { 3421 switch (opt) {
3373 unsigned long long size; 3422 case Opt_size:
3374 size = memparse(value,&rest); 3423 size = memparse(param->string, &rest);
3375 if (*rest == '%') { 3424 if (*rest == '%') {
3376 size <<= PAGE_SHIFT; 3425 size <<= PAGE_SHIFT;
3377 size *= totalram_pages(); 3426 size *= totalram_pages();
@@ -3379,74 +3428,65 @@ static int shmem_parse_one(struct shmem_options *ctx, char *opt, char *value)
3379 rest++; 3428 rest++;
3380 } 3429 }
3381 if (*rest) 3430 if (*rest)
3382 goto bad_val; 3431 goto bad_value;
3383 ctx->blocks = DIV_ROUND_UP(size, PAGE_SIZE); 3432 ctx->blocks = DIV_ROUND_UP(size, PAGE_SIZE);
3384 ctx->seen |= SHMEM_SEEN_BLOCKS; 3433 ctx->seen |= SHMEM_SEEN_BLOCKS;
3385 } else if (!strcmp(opt, "nr_blocks")) { 3434 break;
3386 ctx->blocks = memparse(value, &rest); 3435 case Opt_nr_blocks:
3436 ctx->blocks = memparse(param->string, &rest);
3387 if (*rest) 3437 if (*rest)
3388 goto bad_val; 3438 goto bad_value;
3389 ctx->seen |= SHMEM_SEEN_BLOCKS; 3439 ctx->seen |= SHMEM_SEEN_BLOCKS;
3390 } else if (!strcmp(opt, "nr_inodes")) { 3440 break;
3391 ctx->inodes = memparse(value, &rest); 3441 case Opt_nr_inodes:
3442 ctx->inodes = memparse(param->string, &rest);
3392 if (*rest) 3443 if (*rest)
3393 goto bad_val; 3444 goto bad_value;
3394 ctx->seen |= SHMEM_SEEN_INODES; 3445 ctx->seen |= SHMEM_SEEN_INODES;
3395 } else if (!strcmp(opt, "mode")) { 3446 break;
3396 ctx->mode = simple_strtoul(value, &rest, 8) & 07777; 3447 case Opt_mode:
3397 if (*rest) 3448 ctx->mode = result.uint_32 & 07777;
3398 goto bad_val; 3449 break;
3399 } else if (!strcmp(opt, "uid")) { 3450 case Opt_uid:
3400 uid = simple_strtoul(value, &rest, 0); 3451 ctx->uid = make_kuid(current_user_ns(), result.uint_32);
3401 if (*rest)
3402 goto bad_val;
3403 ctx->uid = make_kuid(current_user_ns(), uid);
3404 if (!uid_valid(ctx->uid)) 3452 if (!uid_valid(ctx->uid))
3405 goto bad_val; 3453 goto bad_value;
3406 } else if (!strcmp(opt, "gid")) { 3454 break;
3407 gid = simple_strtoul(value, &rest, 0); 3455 case Opt_gid:
3408 if (*rest) 3456 ctx->gid = make_kgid(current_user_ns(), result.uint_32);
3409 goto bad_val;
3410 ctx->gid = make_kgid(current_user_ns(), gid);
3411 if (!gid_valid(ctx->gid)) 3457 if (!gid_valid(ctx->gid))
3412 goto bad_val; 3458 goto bad_value;
3413#ifdef CONFIG_TRANSPARENT_HUGE_PAGECACHE 3459 break;
3414 } else if (!strcmp(opt, "huge")) { 3460 case Opt_huge:
3415 int huge; 3461 ctx->huge = result.uint_32;
3416 huge = shmem_parse_huge(value); 3462 if (ctx->huge != SHMEM_HUGE_NEVER &&
3417 if (huge < 0) 3463 !(IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE) &&
3418 goto bad_val; 3464 has_transparent_hugepage()))
3419 if (!has_transparent_hugepage() && 3465 goto unsupported_parameter;
3420 huge != SHMEM_HUGE_NEVER)
3421 goto bad_val;
3422 ctx->huge = huge;
3423 ctx->seen |= SHMEM_SEEN_HUGE; 3466 ctx->seen |= SHMEM_SEEN_HUGE;
3424#endif 3467 break;
3425#ifdef CONFIG_NUMA 3468 case Opt_mpol:
3426 } else if (!strcmp(opt, "mpol")) { 3469 if (IS_ENABLED(CONFIG_NUMA)) {
3427 mpol_put(ctx->mpol); 3470 mpol_put(ctx->mpol);
3428 ctx->mpol = NULL; 3471 ctx->mpol = NULL;
3429 if (mpol_parse_str(value, &ctx->mpol)) 3472 if (mpol_parse_str(param->string, &ctx->mpol))
3430 goto bad_val; 3473 goto bad_value;
3431#endif 3474 break;
3432 } else { 3475 }
3433 pr_err("tmpfs: Bad mount option %s\n", opt); 3476 goto unsupported_parameter;
3434 return -EINVAL;
3435 } 3477 }
3436 return 0; 3478 return 0;
3437 3479
3438bad_val: 3480unsupported_parameter:
3439 pr_err("tmpfs: Bad value '%s' for mount option '%s'\n", 3481 return invalf(fc, "tmpfs: Unsupported parameter '%s'", param->key);
3440 value, opt); 3482bad_value:
3441 return -EINVAL; 3483 return invalf(fc, "tmpfs: Bad value for '%s'", param->key);
3442} 3484}
3443 3485
3444static int shmem_parse_options(char *options, struct shmem_options *ctx) 3486static int shmem_parse_options(char *options, struct shmem_options *ctx)
3445{ 3487{
3446 char *this_char, *value;
3447
3448 while (options != NULL) { 3488 while (options != NULL) {
3449 this_char = options; 3489 char *this_char = options;
3450 for (;;) { 3490 for (;;) {
3451 /* 3491 /*
3452 * NUL-terminate this option: unfortunately, 3492 * NUL-terminate this option: unfortunately,
@@ -3462,17 +3502,26 @@ static int shmem_parse_options(char *options, struct shmem_options *ctx)
3462 break; 3502 break;
3463 } 3503 }
3464 } 3504 }
3465 if (!*this_char) 3505 if (*this_char) {
3466 continue; 3506 char *value = strchr(this_char,'=');
3467 if ((value = strchr(this_char,'=')) != NULL) { 3507 struct fs_parameter param = {
3468 *value++ = 0; 3508 .key = this_char,
3469 } else { 3509 .type = fs_value_is_string,
3470 pr_err("tmpfs: No value for mount option '%s'\n", 3510 };
3471 this_char); 3511 int err;
3472 goto error; 3512
3513 if (value) {
3514 *value++ = '\0';
3515 param.size = strlen(value);
3516 param.string = kstrdup(value, GFP_KERNEL);
3517 if (!param.string)
3518 goto error;
3519 }
3520 err = shmem_parse_one(ctx, &param);
3521 kfree(param.string);
3522 if (err)
3523 goto error;
3473 } 3524 }
3474 if (shmem_parse_one(ctx, this_char, value) < 0)
3475 goto error;
3476 } 3525 }
3477 return 0; 3526 return 0;
3478 3527