shmem.c (923e2f0e7c30db5c1ee5d680050ab781e6c114fb) shmem.c (36f05cab0a2c97bda288c3b6a557ec5fb8d9bba6)
1/*
2 * Resizable virtual memory filesystem for Linux.
3 *
4 * Copyright (C) 2000 Linus Torvalds.
5 * 2000 Transmeta Corp.
6 * 2000-2001 Christoph Rohland
7 * 2000-2001 SAP AG
8 * 2002 Red Hat Inc.

--- 24 unchanged lines hidden (view full) ---

33#include <linux/random.h>
34#include <linux/sched/signal.h>
35#include <linux/export.h>
36#include <linux/swap.h>
37#include <linux/uio.h>
38#include <linux/hugetlb.h>
39#include <linux/fs_parser.h>
40#include <linux/swapfile.h>
1/*
2 * Resizable virtual memory filesystem for Linux.
3 *
4 * Copyright (C) 2000 Linus Torvalds.
5 * 2000 Transmeta Corp.
6 * 2000-2001 Christoph Rohland
7 * 2000-2001 SAP AG
8 * 2002 Red Hat Inc.

--- 24 unchanged lines hidden (view full) ---

33#include <linux/random.h>
34#include <linux/sched/signal.h>
35#include <linux/export.h>
36#include <linux/swap.h>
37#include <linux/uio.h>
38#include <linux/hugetlb.h>
39#include <linux/fs_parser.h>
40#include <linux/swapfile.h>
41#include <linux/iversion.h>
41#include "swap.h"
42
43static struct vfsmount *shm_mnt;
44
45#ifdef CONFIG_SHMEM
46/*
47 * This virtual memory filesystem is heavily based on the ramfs. It
48 * extends ramfs by the ability to use swap and honor resource limits

--- 976 unchanged lines hidden (view full) ---

1025 shmem_recalc_inode(inode);
1026 spin_unlock_irq(&info->lock);
1027}
1028
1029void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
1030{
1031 shmem_undo_range(inode, lstart, lend, false);
1032 inode->i_ctime = inode->i_mtime = current_time(inode);
42#include "swap.h"
43
44static struct vfsmount *shm_mnt;
45
46#ifdef CONFIG_SHMEM
47/*
48 * This virtual memory filesystem is heavily based on the ramfs. It
49 * extends ramfs by the ability to use swap and honor resource limits

--- 976 unchanged lines hidden (view full) ---

1026 shmem_recalc_inode(inode);
1027 spin_unlock_irq(&info->lock);
1028}
1029
1030void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
1031{
1032 shmem_undo_range(inode, lstart, lend, false);
1033 inode->i_ctime = inode->i_mtime = current_time(inode);
1034 inode_inc_iversion(inode);
1033}
1034EXPORT_SYMBOL_GPL(shmem_truncate_range);
1035
1036static int shmem_getattr(struct user_namespace *mnt_userns,
1037 const struct path *path, struct kstat *stat,
1038 u32 request_mask, unsigned int query_flags)
1039{
1040 struct inode *inode = path->dentry->d_inode;

--- 28 unchanged lines hidden (view full) ---

1069}
1070
1071static int shmem_setattr(struct user_namespace *mnt_userns,
1072 struct dentry *dentry, struct iattr *attr)
1073{
1074 struct inode *inode = d_inode(dentry);
1075 struct shmem_inode_info *info = SHMEM_I(inode);
1076 int error;
1035}
1036EXPORT_SYMBOL_GPL(shmem_truncate_range);
1037
1038static int shmem_getattr(struct user_namespace *mnt_userns,
1039 const struct path *path, struct kstat *stat,
1040 u32 request_mask, unsigned int query_flags)
1041{
1042 struct inode *inode = path->dentry->d_inode;

--- 28 unchanged lines hidden (view full) ---

1071}
1072
1073static int shmem_setattr(struct user_namespace *mnt_userns,
1074 struct dentry *dentry, struct iattr *attr)
1075{
1076 struct inode *inode = d_inode(dentry);
1077 struct shmem_inode_info *info = SHMEM_I(inode);
1078 int error;
1079 bool update_mtime = false;
1080 bool update_ctime = true;
1077
1078 error = setattr_prepare(&init_user_ns, dentry, attr);
1079 if (error)
1080 return error;
1081
1082 if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
1083 loff_t oldsize = inode->i_size;
1084 loff_t newsize = attr->ia_size;

--- 4 unchanged lines hidden (view full) ---

1089 return -EPERM;
1090
1091 if (newsize != oldsize) {
1092 error = shmem_reacct_size(SHMEM_I(inode)->flags,
1093 oldsize, newsize);
1094 if (error)
1095 return error;
1096 i_size_write(inode, newsize);
1081
1082 error = setattr_prepare(&init_user_ns, dentry, attr);
1083 if (error)
1084 return error;
1085
1086 if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
1087 loff_t oldsize = inode->i_size;
1088 loff_t newsize = attr->ia_size;

--- 4 unchanged lines hidden (view full) ---

1093 return -EPERM;
1094
1095 if (newsize != oldsize) {
1096 error = shmem_reacct_size(SHMEM_I(inode)->flags,
1097 oldsize, newsize);
1098 if (error)
1099 return error;
1100 i_size_write(inode, newsize);
1097 inode->i_ctime = inode->i_mtime = current_time(inode);
1101 update_mtime = true;
1102 } else {
1103 update_ctime = false;
1098 }
1099 if (newsize <= oldsize) {
1100 loff_t holebegin = round_up(newsize, PAGE_SIZE);
1101 if (oldsize > holebegin)
1102 unmap_mapping_range(inode->i_mapping,
1103 holebegin, 0, 1);
1104 if (info->alloced)
1105 shmem_truncate_range(inode,
1106 newsize, (loff_t)-1);
1107 /* unmap again to remove racily COWed private pages */
1108 if (oldsize > holebegin)
1109 unmap_mapping_range(inode->i_mapping,
1110 holebegin, 0, 1);
1111 }
1112 }
1113
1114 setattr_copy(&init_user_ns, inode, attr);
1115 if (attr->ia_valid & ATTR_MODE)
1116 error = posix_acl_chmod(&init_user_ns, inode, inode->i_mode);
1104 }
1105 if (newsize <= oldsize) {
1106 loff_t holebegin = round_up(newsize, PAGE_SIZE);
1107 if (oldsize > holebegin)
1108 unmap_mapping_range(inode->i_mapping,
1109 holebegin, 0, 1);
1110 if (info->alloced)
1111 shmem_truncate_range(inode,
1112 newsize, (loff_t)-1);
1113 /* unmap again to remove racily COWed private pages */
1114 if (oldsize > holebegin)
1115 unmap_mapping_range(inode->i_mapping,
1116 holebegin, 0, 1);
1117 }
1118 }
1119
1120 setattr_copy(&init_user_ns, inode, attr);
1121 if (attr->ia_valid & ATTR_MODE)
1122 error = posix_acl_chmod(&init_user_ns, inode, inode->i_mode);
1123 if (!error && update_ctime) {
1124 inode->i_ctime = current_time(inode);
1125 if (update_mtime)
1126 inode->i_mtime = inode->i_ctime;
1127 inode_inc_iversion(inode);
1128 }
1117 return error;
1118}
1119
1120static void shmem_evict_inode(struct inode *inode)
1121{
1122 struct shmem_inode_info *info = SHMEM_I(inode);
1123 struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
1124

--- 1760 unchanged lines hidden (view full) ---

2885 &dentry->d_name,
2886 shmem_initxattrs, NULL);
2887 if (error && error != -EOPNOTSUPP)
2888 goto out_iput;
2889
2890 error = 0;
2891 dir->i_size += BOGO_DIRENT_SIZE;
2892 dir->i_ctime = dir->i_mtime = current_time(dir);
1129 return error;
1130}
1131
1132static void shmem_evict_inode(struct inode *inode)
1133{
1134 struct shmem_inode_info *info = SHMEM_I(inode);
1135 struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
1136

--- 1760 unchanged lines hidden (view full) ---

2897 &dentry->d_name,
2898 shmem_initxattrs, NULL);
2899 if (error && error != -EOPNOTSUPP)
2900 goto out_iput;
2901
2902 error = 0;
2903 dir->i_size += BOGO_DIRENT_SIZE;
2904 dir->i_ctime = dir->i_mtime = current_time(dir);
2905 inode_inc_iversion(dir);
2893 d_instantiate(dentry, inode);
2894 dget(dentry); /* Extra count - pin the dentry in core */
2895 }
2896 return error;
2897out_iput:
2898 iput(inode);
2899 return error;
2900}

--- 59 unchanged lines hidden (view full) ---

2960 if (inode->i_nlink) {
2961 ret = shmem_reserve_inode(inode->i_sb, NULL);
2962 if (ret)
2963 goto out;
2964 }
2965
2966 dir->i_size += BOGO_DIRENT_SIZE;
2967 inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
2906 d_instantiate(dentry, inode);
2907 dget(dentry); /* Extra count - pin the dentry in core */
2908 }
2909 return error;
2910out_iput:
2911 iput(inode);
2912 return error;
2913}

--- 59 unchanged lines hidden (view full) ---

2973 if (inode->i_nlink) {
2974 ret = shmem_reserve_inode(inode->i_sb, NULL);
2975 if (ret)
2976 goto out;
2977 }
2978
2979 dir->i_size += BOGO_DIRENT_SIZE;
2980 inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
2981 inode_inc_iversion(dir);
2968 inc_nlink(inode);
2969 ihold(inode); /* New dentry reference */
2970 dget(dentry); /* Extra pinning count for the created dentry */
2971 d_instantiate(dentry, inode);
2972out:
2973 return ret;
2974}
2975
2976static int shmem_unlink(struct inode *dir, struct dentry *dentry)
2977{
2978 struct inode *inode = d_inode(dentry);
2979
2980 if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))
2981 shmem_free_inode(inode->i_sb);
2982
2983 dir->i_size -= BOGO_DIRENT_SIZE;
2984 inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
2982 inc_nlink(inode);
2983 ihold(inode); /* New dentry reference */
2984 dget(dentry); /* Extra pinning count for the created dentry */
2985 d_instantiate(dentry, inode);
2986out:
2987 return ret;
2988}
2989
2990static int shmem_unlink(struct inode *dir, struct dentry *dentry)
2991{
2992 struct inode *inode = d_inode(dentry);
2993
2994 if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))
2995 shmem_free_inode(inode->i_sb);
2996
2997 dir->i_size -= BOGO_DIRENT_SIZE;
2998 inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
2999 inode_inc_iversion(dir);
2985 drop_nlink(inode);
2986 dput(dentry); /* Undo the count from "create" - this does all the work */
2987 return 0;
2988}
2989
2990static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
2991{
2992 if (!simple_empty(dentry))

--- 73 unchanged lines hidden (view full) ---

3066 inc_nlink(new_dir);
3067 }
3068
3069 old_dir->i_size -= BOGO_DIRENT_SIZE;
3070 new_dir->i_size += BOGO_DIRENT_SIZE;
3071 old_dir->i_ctime = old_dir->i_mtime =
3072 new_dir->i_ctime = new_dir->i_mtime =
3073 inode->i_ctime = current_time(old_dir);
3000 drop_nlink(inode);
3001 dput(dentry); /* Undo the count from "create" - this does all the work */
3002 return 0;
3003}
3004
3005static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
3006{
3007 if (!simple_empty(dentry))

--- 73 unchanged lines hidden (view full) ---

3081 inc_nlink(new_dir);
3082 }
3083
3084 old_dir->i_size -= BOGO_DIRENT_SIZE;
3085 new_dir->i_size += BOGO_DIRENT_SIZE;
3086 old_dir->i_ctime = old_dir->i_mtime =
3087 new_dir->i_ctime = new_dir->i_mtime =
3088 inode->i_ctime = current_time(old_dir);
3089 inode_inc_iversion(old_dir);
3090 inode_inc_iversion(new_dir);
3074 return 0;
3075}
3076
3077static int shmem_symlink(struct user_namespace *mnt_userns, struct inode *dir,
3078 struct dentry *dentry, const char *symname)
3079{
3080 int error;
3081 int len;

--- 36 unchanged lines hidden (view full) ---

3118 memcpy(folio_address(folio), symname, len);
3119 folio_mark_uptodate(folio);
3120 folio_mark_dirty(folio);
3121 folio_unlock(folio);
3122 folio_put(folio);
3123 }
3124 dir->i_size += BOGO_DIRENT_SIZE;
3125 dir->i_ctime = dir->i_mtime = current_time(dir);
3091 return 0;
3092}
3093
3094static int shmem_symlink(struct user_namespace *mnt_userns, struct inode *dir,
3095 struct dentry *dentry, const char *symname)
3096{
3097 int error;
3098 int len;

--- 36 unchanged lines hidden (view full) ---

3135 memcpy(folio_address(folio), symname, len);
3136 folio_mark_uptodate(folio);
3137 folio_mark_dirty(folio);
3138 folio_unlock(folio);
3139 folio_put(folio);
3140 }
3141 dir->i_size += BOGO_DIRENT_SIZE;
3142 dir->i_ctime = dir->i_mtime = current_time(dir);
3143 inode_inc_iversion(dir);
3126 d_instantiate(dentry, inode);
3127 dget(dentry);
3128 return 0;
3129}
3130
3131static void shmem_put_link(void *arg)
3132{
3133 folio_mark_accessed(arg);

--- 55 unchanged lines hidden (view full) ---

3189 if (fa->flags & ~SHMEM_FL_USER_MODIFIABLE)
3190 return -EOPNOTSUPP;
3191
3192 info->fsflags = (info->fsflags & ~SHMEM_FL_USER_MODIFIABLE) |
3193 (fa->flags & SHMEM_FL_USER_MODIFIABLE);
3194
3195 shmem_set_inode_flags(inode, info->fsflags);
3196 inode->i_ctime = current_time(inode);
3144 d_instantiate(dentry, inode);
3145 dget(dentry);
3146 return 0;
3147}
3148
3149static void shmem_put_link(void *arg)
3150{
3151 folio_mark_accessed(arg);

--- 55 unchanged lines hidden (view full) ---

3207 if (fa->flags & ~SHMEM_FL_USER_MODIFIABLE)
3208 return -EOPNOTSUPP;
3209
3210 info->fsflags = (info->fsflags & ~SHMEM_FL_USER_MODIFIABLE) |
3211 (fa->flags & SHMEM_FL_USER_MODIFIABLE);
3212
3213 shmem_set_inode_flags(inode, info->fsflags);
3214 inode->i_ctime = current_time(inode);
3215 inode_inc_iversion(inode);
3197 return 0;
3198}
3199
3200/*
3201 * Superblocks without xattr inode operations may get some security.* xattr
3202 * support from the LSM "for free". As soon as we have any other xattrs
3203 * like ACLs, we also need to implement the security.* handlers at
3204 * filesystem level, though.

--- 47 unchanged lines hidden (view full) ---

3252
3253static int shmem_xattr_handler_set(const struct xattr_handler *handler,
3254 struct user_namespace *mnt_userns,
3255 struct dentry *unused, struct inode *inode,
3256 const char *name, const void *value,
3257 size_t size, int flags)
3258{
3259 struct shmem_inode_info *info = SHMEM_I(inode);
3216 return 0;
3217}
3218
3219/*
3220 * Superblocks without xattr inode operations may get some security.* xattr
3221 * support from the LSM "for free". As soon as we have any other xattrs
3222 * like ACLs, we also need to implement the security.* handlers at
3223 * filesystem level, though.

--- 47 unchanged lines hidden (view full) ---

3271
3272static int shmem_xattr_handler_set(const struct xattr_handler *handler,
3273 struct user_namespace *mnt_userns,
3274 struct dentry *unused, struct inode *inode,
3275 const char *name, const void *value,
3276 size_t size, int flags)
3277{
3278 struct shmem_inode_info *info = SHMEM_I(inode);
3279 int err;
3260
3261 name = xattr_full_name(handler, name);
3280
3281 name = xattr_full_name(handler, name);
3262 return simple_xattr_set(&info->xattrs, name, value, size, flags, NULL);
3282 err = simple_xattr_set(&info->xattrs, name, value, size, flags, NULL);
3283 if (!err) {
3284 inode->i_ctime = current_time(inode);
3285 inode_inc_iversion(inode);
3286 }
3287 return err;
3263}
3264
3265static const struct xattr_handler shmem_security_xattr_handler = {
3266 .prefix = XATTR_SECURITY_PREFIX,
3267 .get = shmem_xattr_handler_get,
3268 .set = shmem_xattr_handler_set,
3269};
3270

--- 446 unchanged lines hidden (view full) ---

3717 if (!(ctx->seen & SHMEM_SEEN_INODES))
3718 ctx->inodes = shmem_default_max_inodes();
3719 if (!(ctx->seen & SHMEM_SEEN_INUMS))
3720 ctx->full_inums = IS_ENABLED(CONFIG_TMPFS_INODE64);
3721 } else {
3722 sb->s_flags |= SB_NOUSER;
3723 }
3724 sb->s_export_op = &shmem_export_ops;
3288}
3289
3290static const struct xattr_handler shmem_security_xattr_handler = {
3291 .prefix = XATTR_SECURITY_PREFIX,
3292 .get = shmem_xattr_handler_get,
3293 .set = shmem_xattr_handler_set,
3294};
3295

--- 446 unchanged lines hidden (view full) ---

3742 if (!(ctx->seen & SHMEM_SEEN_INODES))
3743 ctx->inodes = shmem_default_max_inodes();
3744 if (!(ctx->seen & SHMEM_SEEN_INUMS))
3745 ctx->full_inums = IS_ENABLED(CONFIG_TMPFS_INODE64);
3746 } else {
3747 sb->s_flags |= SB_NOUSER;
3748 }
3749 sb->s_export_op = &shmem_export_ops;
3725 sb->s_flags |= SB_NOSEC;
3750 sb->s_flags |= SB_NOSEC | SB_I_VERSION;
3726#else
3727 sb->s_flags |= SB_NOUSER;
3728#endif
3729 sbinfo->max_blocks = ctx->blocks;
3730 sbinfo->free_inodes = sbinfo->max_inodes = ctx->inodes;
3731 if (sb->s_flags & SB_KERNMOUNT) {
3732 sbinfo->ino_batch = alloc_percpu(ino_t);
3733 if (!sbinfo->ino_batch)

--- 551 unchanged lines hidden ---
3751#else
3752 sb->s_flags |= SB_NOUSER;
3753#endif
3754 sbinfo->max_blocks = ctx->blocks;
3755 sbinfo->free_inodes = sbinfo->max_inodes = ctx->inodes;
3756 if (sb->s_flags & SB_KERNMOUNT) {
3757 sbinfo->ino_batch = alloc_percpu(ino_t);
3758 if (!sbinfo->ino_batch)

--- 551 unchanged lines hidden ---