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 --- |