summaryrefslogtreecommitdiffstats
path: root/mm/shmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/shmem.c')
-rw-r--r--mm/shmem.c385
1 files changed, 248 insertions, 137 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index 2bed4761f279..0f7fd4a85db6 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
@@ -107,6 +108,20 @@ struct shmem_falloc {
107 pgoff_t nr_unswapped; /* how often writepage refused to swap out */ 108 pgoff_t nr_unswapped; /* how often writepage refused to swap out */
108}; 109};
109 110
111struct shmem_options {
112 unsigned long long blocks;
113 unsigned long long inodes;
114 struct mempolicy *mpol;
115 kuid_t uid;
116 kgid_t gid;
117 umode_t mode;
118 int huge;
119 int seen;
120#define SHMEM_SEEN_BLOCKS 1
121#define SHMEM_SEEN_INODES 2
122#define SHMEM_SEEN_HUGE 4
123};
124
110#ifdef CONFIG_TMPFS 125#ifdef CONFIG_TMPFS
111static unsigned long shmem_default_max_blocks(void) 126static unsigned long shmem_default_max_blocks(void)
112{ 127{
@@ -3349,16 +3364,126 @@ static const struct export_operations shmem_export_ops = {
3349 .fh_to_dentry = shmem_fh_to_dentry, 3364 .fh_to_dentry = shmem_fh_to_dentry,
3350}; 3365};
3351 3366
3352static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo, 3367enum shmem_param {
3353 bool remount) 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 fs_context *fc, struct fs_parameter *param)
3354{ 3405{
3355 char *this_char, *value, *rest; 3406 struct shmem_options *ctx = fc->fs_private;
3356 struct mempolicy *mpol = NULL; 3407 struct fs_parse_result result;
3357 uid_t uid; 3408 unsigned long long size;
3358 gid_t gid; 3409 char *rest;
3410 int opt;
3411
3412 opt = fs_parse(fc, &shmem_fs_parameters, param, &result);
3413 if (opt < 0)
3414 return opt;
3415
3416 switch (opt) {
3417 case Opt_size:
3418 size = memparse(param->string, &rest);
3419 if (*rest == '%') {
3420 size <<= PAGE_SHIFT;
3421 size *= totalram_pages();
3422 do_div(size, 100);
3423 rest++;
3424 }
3425 if (*rest)
3426 goto bad_value;
3427 ctx->blocks = DIV_ROUND_UP(size, PAGE_SIZE);
3428 ctx->seen |= SHMEM_SEEN_BLOCKS;
3429 break;
3430 case Opt_nr_blocks:
3431 ctx->blocks = memparse(param->string, &rest);
3432 if (*rest)
3433 goto bad_value;
3434 ctx->seen |= SHMEM_SEEN_BLOCKS;
3435 break;
3436 case Opt_nr_inodes:
3437 ctx->inodes = memparse(param->string, &rest);
3438 if (*rest)
3439 goto bad_value;
3440 ctx->seen |= SHMEM_SEEN_INODES;
3441 break;
3442 case Opt_mode:
3443 ctx->mode = result.uint_32 & 07777;
3444 break;
3445 case Opt_uid:
3446 ctx->uid = make_kuid(current_user_ns(), result.uint_32);
3447 if (!uid_valid(ctx->uid))
3448 goto bad_value;
3449 break;
3450 case Opt_gid:
3451 ctx->gid = make_kgid(current_user_ns(), result.uint_32);
3452 if (!gid_valid(ctx->gid))
3453 goto bad_value;
3454 break;
3455 case Opt_huge:
3456 ctx->huge = result.uint_32;
3457 if (ctx->huge != SHMEM_HUGE_NEVER &&
3458 !(IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE) &&
3459 has_transparent_hugepage()))
3460 goto unsupported_parameter;
3461 ctx->seen |= SHMEM_SEEN_HUGE;
3462 break;
3463 case Opt_mpol:
3464 if (IS_ENABLED(CONFIG_NUMA)) {
3465 mpol_put(ctx->mpol);
3466 ctx->mpol = NULL;
3467 if (mpol_parse_str(param->string, &ctx->mpol))
3468 goto bad_value;
3469 break;
3470 }
3471 goto unsupported_parameter;
3472 }
3473 return 0;
3474
3475unsupported_parameter:
3476 return invalf(fc, "tmpfs: Unsupported parameter '%s'", param->key);
3477bad_value:
3478 return invalf(fc, "tmpfs: Bad value for '%s'", param->key);
3479}
3480
3481static int shmem_parse_options(struct fs_context *fc, void *data)
3482{
3483 char *options = data;
3359 3484
3360 while (options != NULL) { 3485 while (options != NULL) {
3361 this_char = options; 3486 char *this_char = options;
3362 for (;;) { 3487 for (;;) {
3363 /* 3488 /*
3364 * NUL-terminate this option: unfortunately, 3489 * NUL-terminate this option: unfortunately,
@@ -3374,139 +3499,83 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
3374 break; 3499 break;
3375 } 3500 }
3376 } 3501 }
3377 if (!*this_char) 3502 if (*this_char) {
3378 continue; 3503 char *value = strchr(this_char,'=');
3379 if ((value = strchr(this_char,'=')) != NULL) { 3504 size_t len = 0;
3380 *value++ = 0; 3505 int err;
3381 } else { 3506
3382 pr_err("tmpfs: No value for mount option '%s'\n", 3507 if (value) {
3383 this_char); 3508 *value++ = '\0';
3384 goto error; 3509 len = strlen(value);
3385 }
3386
3387 if (!strcmp(this_char,"size")) {
3388 unsigned long long size;
3389 size = memparse(value,&rest);
3390 if (*rest == '%') {
3391 size <<= PAGE_SHIFT;
3392 size *= totalram_pages();
3393 do_div(size, 100);
3394 rest++;
3395 } 3510 }
3396 if (*rest) 3511 err = vfs_parse_fs_string(fc, this_char, value, len);
3397 goto bad_val; 3512 if (err < 0)
3398 sbinfo->max_blocks = 3513 return err;
3399 DIV_ROUND_UP(size, PAGE_SIZE);
3400 } else if (!strcmp(this_char,"nr_blocks")) {
3401 sbinfo->max_blocks = memparse(value, &rest);
3402 if (*rest)
3403 goto bad_val;
3404 } else if (!strcmp(this_char,"nr_inodes")) {
3405 sbinfo->max_inodes = memparse(value, &rest);
3406 if (*rest)
3407 goto bad_val;
3408 } else if (!strcmp(this_char,"mode")) {
3409 if (remount)
3410 continue;
3411 sbinfo->mode = simple_strtoul(value, &rest, 8) & 07777;
3412 if (*rest)
3413 goto bad_val;
3414 } else if (!strcmp(this_char,"uid")) {
3415 if (remount)
3416 continue;
3417 uid = simple_strtoul(value, &rest, 0);
3418 if (*rest)
3419 goto bad_val;
3420 sbinfo->uid = make_kuid(current_user_ns(), uid);
3421 if (!uid_valid(sbinfo->uid))
3422 goto bad_val;
3423 } else if (!strcmp(this_char,"gid")) {
3424 if (remount)
3425 continue;
3426 gid = simple_strtoul(value, &rest, 0);
3427 if (*rest)
3428 goto bad_val;
3429 sbinfo->gid = make_kgid(current_user_ns(), gid);
3430 if (!gid_valid(sbinfo->gid))
3431 goto bad_val;
3432#ifdef CONFIG_TRANSPARENT_HUGE_PAGECACHE
3433 } else if (!strcmp(this_char, "huge")) {
3434 int huge;
3435 huge = shmem_parse_huge(value);
3436 if (huge < 0)
3437 goto bad_val;
3438 if (!has_transparent_hugepage() &&
3439 huge != SHMEM_HUGE_NEVER)
3440 goto bad_val;
3441 sbinfo->huge = huge;
3442#endif
3443#ifdef CONFIG_NUMA
3444 } else if (!strcmp(this_char,"mpol")) {
3445 mpol_put(mpol);
3446 mpol = NULL;
3447 if (mpol_parse_str(value, &mpol))
3448 goto bad_val;
3449#endif
3450 } else {
3451 pr_err("tmpfs: Bad mount option %s\n", this_char);
3452 goto error;
3453 } 3514 }
3454 } 3515 }
3455 sbinfo->mpol = mpol;
3456 return 0; 3516 return 0;
3457
3458bad_val:
3459 pr_err("tmpfs: Bad value '%s' for mount option '%s'\n",
3460 value, this_char);
3461error:
3462 mpol_put(mpol);
3463 return 1;
3464
3465} 3517}
3466 3518
3467static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) 3519/*
3520 * Reconfigure a shmem filesystem.
3521 *
3522 * Note that we disallow change from limited->unlimited blocks/inodes while any
3523 * are in use; but we must separately disallow unlimited->limited, because in
3524 * that case we have no record of how much is already in use.
3525 */
3526static int shmem_reconfigure(struct fs_context *fc)
3468{ 3527{
3469 struct shmem_sb_info *sbinfo = SHMEM_SB(sb); 3528 struct shmem_options *ctx = fc->fs_private;
3470 struct shmem_sb_info config = *sbinfo; 3529 struct shmem_sb_info *sbinfo = SHMEM_SB(fc->root->d_sb);
3471 unsigned long inodes; 3530 unsigned long inodes;
3472 int error = -EINVAL; 3531 const char *err;
3473
3474 config.mpol = NULL;
3475 if (shmem_parse_options(data, &config, true))
3476 return error;
3477 3532
3478 spin_lock(&sbinfo->stat_lock); 3533 spin_lock(&sbinfo->stat_lock);
3479 inodes = sbinfo->max_inodes - sbinfo->free_inodes; 3534 inodes = sbinfo->max_inodes - sbinfo->free_inodes;
3480 if (percpu_counter_compare(&sbinfo->used_blocks, config.max_blocks) > 0) 3535 if ((ctx->seen & SHMEM_SEEN_BLOCKS) && ctx->blocks) {
3481 goto out; 3536 if (!sbinfo->max_blocks) {
3482 if (config.max_inodes < inodes) 3537 err = "Cannot retroactively limit size";
3483 goto out; 3538 goto out;
3484 /* 3539 }
3485 * Those tests disallow limited->unlimited while any are in use; 3540 if (percpu_counter_compare(&sbinfo->used_blocks,
3486 * but we must separately disallow unlimited->limited, because 3541 ctx->blocks) > 0) {
3487 * in that case we have no record of how much is already in use. 3542 err = "Too small a size for current use";
3488 */ 3543 goto out;
3489 if (config.max_blocks && !sbinfo->max_blocks) 3544 }
3490 goto out; 3545 }
3491 if (config.max_inodes && !sbinfo->max_inodes) 3546 if ((ctx->seen & SHMEM_SEEN_INODES) && ctx->inodes) {
3492 goto out; 3547 if (!sbinfo->max_inodes) {
3548 err = "Cannot retroactively limit inodes";
3549 goto out;
3550 }
3551 if (ctx->inodes < inodes) {
3552 err = "Too few inodes for current use";
3553 goto out;
3554 }
3555 }
3493 3556
3494 error = 0; 3557 if (ctx->seen & SHMEM_SEEN_HUGE)
3495 sbinfo->huge = config.huge; 3558 sbinfo->huge = ctx->huge;
3496 sbinfo->max_blocks = config.max_blocks; 3559 if (ctx->seen & SHMEM_SEEN_BLOCKS)
3497 sbinfo->max_inodes = config.max_inodes; 3560 sbinfo->max_blocks = ctx->blocks;
3498 sbinfo->free_inodes = config.max_inodes - inodes; 3561 if (ctx->seen & SHMEM_SEEN_INODES) {
3562 sbinfo->max_inodes = ctx->inodes;
3563 sbinfo->free_inodes = ctx->inodes - inodes;
3564 }
3499 3565
3500 /* 3566 /*
3501 * Preserve previous mempolicy unless mpol remount option was specified. 3567 * Preserve previous mempolicy unless mpol remount option was specified.
3502 */ 3568 */
3503 if (config.mpol) { 3569 if (ctx->mpol) {
3504 mpol_put(sbinfo->mpol); 3570 mpol_put(sbinfo->mpol);
3505 sbinfo->mpol = config.mpol; /* transfers initial ref */ 3571 sbinfo->mpol = ctx->mpol; /* transfers initial ref */
3572 ctx->mpol = NULL;
3506 } 3573 }
3574 spin_unlock(&sbinfo->stat_lock);
3575 return 0;
3507out: 3576out:
3508 spin_unlock(&sbinfo->stat_lock); 3577 spin_unlock(&sbinfo->stat_lock);
3509 return error; 3578 return invalf(fc, "tmpfs: %s", err);
3510} 3579}
3511 3580
3512static int shmem_show_options(struct seq_file *seq, struct dentry *root) 3581static int shmem_show_options(struct seq_file *seq, struct dentry *root)
@@ -3547,8 +3616,9 @@ static void shmem_put_super(struct super_block *sb)
3547 sb->s_fs_info = NULL; 3616 sb->s_fs_info = NULL;
3548} 3617}
3549 3618
3550int shmem_fill_super(struct super_block *sb, void *data, int silent) 3619static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
3551{ 3620{
3621 struct shmem_options *ctx = fc->fs_private;
3552 struct inode *inode; 3622 struct inode *inode;
3553 struct shmem_sb_info *sbinfo; 3623 struct shmem_sb_info *sbinfo;
3554 int err = -ENOMEM; 3624 int err = -ENOMEM;
@@ -3559,9 +3629,6 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
3559 if (!sbinfo) 3629 if (!sbinfo)
3560 return -ENOMEM; 3630 return -ENOMEM;
3561 3631
3562 sbinfo->mode = 0777 | S_ISVTX;
3563 sbinfo->uid = current_fsuid();
3564 sbinfo->gid = current_fsgid();
3565 sb->s_fs_info = sbinfo; 3632 sb->s_fs_info = sbinfo;
3566 3633
3567#ifdef CONFIG_TMPFS 3634#ifdef CONFIG_TMPFS
@@ -3571,12 +3638,10 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
3571 * but the internal instance is left unlimited. 3638 * but the internal instance is left unlimited.
3572 */ 3639 */
3573 if (!(sb->s_flags & SB_KERNMOUNT)) { 3640 if (!(sb->s_flags & SB_KERNMOUNT)) {
3574 sbinfo->max_blocks = shmem_default_max_blocks(); 3641 if (!(ctx->seen & SHMEM_SEEN_BLOCKS))
3575 sbinfo->max_inodes = shmem_default_max_inodes(); 3642 ctx->blocks = shmem_default_max_blocks();
3576 if (shmem_parse_options(data, sbinfo, false)) { 3643 if (!(ctx->seen & SHMEM_SEEN_INODES))
3577 err = -EINVAL; 3644 ctx->inodes = shmem_default_max_inodes();
3578 goto failed;
3579 }
3580 } else { 3645 } else {
3581 sb->s_flags |= SB_NOUSER; 3646 sb->s_flags |= SB_NOUSER;
3582 } 3647 }
@@ -3585,11 +3650,18 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
3585#else 3650#else
3586 sb->s_flags |= SB_NOUSER; 3651 sb->s_flags |= SB_NOUSER;
3587#endif 3652#endif
3653 sbinfo->max_blocks = ctx->blocks;
3654 sbinfo->free_inodes = sbinfo->max_inodes = ctx->inodes;
3655 sbinfo->uid = ctx->uid;
3656 sbinfo->gid = ctx->gid;
3657 sbinfo->mode = ctx->mode;
3658 sbinfo->huge = ctx->huge;
3659 sbinfo->mpol = ctx->mpol;
3660 ctx->mpol = NULL;
3588 3661
3589 spin_lock_init(&sbinfo->stat_lock); 3662 spin_lock_init(&sbinfo->stat_lock);
3590 if (percpu_counter_init(&sbinfo->used_blocks, 0, GFP_KERNEL)) 3663 if (percpu_counter_init(&sbinfo->used_blocks, 0, GFP_KERNEL))
3591 goto failed; 3664 goto failed;
3592 sbinfo->free_inodes = sbinfo->max_inodes;
3593 spin_lock_init(&sbinfo->shrinklist_lock); 3665 spin_lock_init(&sbinfo->shrinklist_lock);
3594 INIT_LIST_HEAD(&sbinfo->shrinklist); 3666 INIT_LIST_HEAD(&sbinfo->shrinklist);
3595 3667
@@ -3622,6 +3694,31 @@ failed:
3622 return err; 3694 return err;
3623} 3695}
3624 3696
3697static int shmem_get_tree(struct fs_context *fc)
3698{
3699 return get_tree_nodev(fc, shmem_fill_super);
3700}
3701
3702static void shmem_free_fc(struct fs_context *fc)
3703{
3704 struct shmem_options *ctx = fc->fs_private;
3705
3706 if (ctx) {
3707 mpol_put(ctx->mpol);
3708 kfree(ctx);
3709 }
3710}
3711
3712static const struct fs_context_operations shmem_fs_context_ops = {
3713 .free = shmem_free_fc,
3714 .get_tree = shmem_get_tree,
3715#ifdef CONFIG_TMPFS
3716 .parse_monolithic = shmem_parse_options,
3717 .parse_param = shmem_parse_one,
3718 .reconfigure = shmem_reconfigure,
3719#endif
3720};
3721
3625static struct kmem_cache *shmem_inode_cachep; 3722static struct kmem_cache *shmem_inode_cachep;
3626 3723
3627static struct inode *shmem_alloc_inode(struct super_block *sb) 3724static struct inode *shmem_alloc_inode(struct super_block *sb)
@@ -3738,7 +3835,6 @@ static const struct super_operations shmem_ops = {
3738 .destroy_inode = shmem_destroy_inode, 3835 .destroy_inode = shmem_destroy_inode,
3739#ifdef CONFIG_TMPFS 3836#ifdef CONFIG_TMPFS
3740 .statfs = shmem_statfs, 3837 .statfs = shmem_statfs,
3741 .remount_fs = shmem_remount_fs,
3742 .show_options = shmem_show_options, 3838 .show_options = shmem_show_options,
3743#endif 3839#endif
3744 .evict_inode = shmem_evict_inode, 3840 .evict_inode = shmem_evict_inode,
@@ -3759,16 +3855,30 @@ static const struct vm_operations_struct shmem_vm_ops = {
3759#endif 3855#endif
3760}; 3856};
3761 3857
3762static struct dentry *shmem_mount(struct file_system_type *fs_type, 3858int shmem_init_fs_context(struct fs_context *fc)
3763 int flags, const char *dev_name, void *data)
3764{ 3859{
3765 return mount_nodev(fs_type, flags, data, shmem_fill_super); 3860 struct shmem_options *ctx;
3861
3862 ctx = kzalloc(sizeof(struct shmem_options), GFP_KERNEL);
3863 if (!ctx)
3864 return -ENOMEM;
3865
3866 ctx->mode = 0777 | S_ISVTX;
3867 ctx->uid = current_fsuid();
3868 ctx->gid = current_fsgid();
3869
3870 fc->fs_private = ctx;
3871 fc->ops = &shmem_fs_context_ops;
3872 return 0;
3766} 3873}
3767 3874
3768static struct file_system_type shmem_fs_type = { 3875static struct file_system_type shmem_fs_type = {
3769 .owner = THIS_MODULE, 3876 .owner = THIS_MODULE,
3770 .name = "tmpfs", 3877 .name = "tmpfs",
3771 .mount = shmem_mount, 3878 .init_fs_context = shmem_init_fs_context,
3879#ifdef CONFIG_TMPFS
3880 .parameters = &shmem_fs_parameters,
3881#endif
3772 .kill_sb = kill_litter_super, 3882 .kill_sb = kill_litter_super,
3773 .fs_flags = FS_USERNS_MOUNT, 3883 .fs_flags = FS_USERNS_MOUNT,
3774}; 3884};
@@ -3912,7 +4022,8 @@ bool shmem_huge_enabled(struct vm_area_struct *vma)
3912 4022
3913static struct file_system_type shmem_fs_type = { 4023static struct file_system_type shmem_fs_type = {
3914 .name = "tmpfs", 4024 .name = "tmpfs",
3915 .mount = ramfs_mount, 4025 .init_fs_context = ramfs_init_fs_context,
4026 .parameters = &ramfs_fs_parameters,
3916 .kill_sb = kill_litter_super, 4027 .kill_sb = kill_litter_super,
3917 .fs_flags = FS_USERNS_MOUNT, 4028 .fs_flags = FS_USERNS_MOUNT,
3918}; 4029};