diff --git a/kmod/src/Makefile.kernelcompat b/kmod/src/Makefile.kernelcompat index 84b05969..170ddab7 100644 --- a/kmod/src/Makefile.kernelcompat +++ b/kmod/src/Makefile.kernelcompat @@ -442,3 +442,18 @@ endif ifneq (,$(shell grep 'u32 get_random_u32_below' include/linux/random.h)) ccflags-y += -DKC_HAVE_GET_RANDOM_U32_BELOW endif + +# v6.5-rc1-7-g9b6304c1d537 +# +# ctime accessor methods +ifneq (,$(shell grep 'timespec64 inode_set_ctime_current' include/linux/fs.h)) +ccflags-y += -DKC_FS_INODE_C_TIME_ACCESSOR +endif + +# +# v6.6-rc5-1-g077c212f0344 +# +# Must use access methods from fs.h to get to inode ctime/mtime/atime +ifneq (,$(shell grep 'inline time64_t inode_get_atime_sec' include/linux/fs.h)) +ccflags-y += -DKC_FS_INODE_AM_TIME_ACCESSOR +endif diff --git a/kmod/src/acl.c b/kmod/src/acl.c index 0fdb9d93..f51239ef 100644 --- a/kmod/src/acl.c +++ b/kmod/src/acl.c @@ -188,7 +188,7 @@ int scoutfs_set_acl_locked(struct inode *inode, struct posix_acl *acl, int type, if (!value) { /* can be setting an acl that only affects mode, didn't need xattr */ inode_inc_iversion(inode); - inode->i_ctime = current_time(inode); + inode_set_ctime_current(inode); } } diff --git a/kmod/src/attr_x.c b/kmod/src/attr_x.c index 39e84a36..409c9c79 100644 --- a/kmod/src/attr_x.c +++ b/kmod/src/attr_x.c @@ -103,8 +103,8 @@ int scoutfs_get_attr_x(struct inode *inode, struct scoutfs_ioctl_inode_attr_x *i size = fill_attr(size, iax, SCOUTFS_IOC_IAX_OFFLINE_BLOCKS, offline_blocks, offline); } - size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CTIME, ctime_sec, inode->i_ctime.tv_sec); - size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CTIME, ctime_nsec, inode->i_ctime.tv_nsec); + size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CTIME, ctime_sec, inode_get_ctime_sec(inode)); + size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CTIME, ctime_nsec, inode_get_ctime_nsec(inode)); size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CRTIME, crtime_sec, si->crtime.tv_sec); size = fill_attr(size, iax, SCOUTFS_IOC_IAX_CRTIME, crtime_nsec, si->crtime.tv_nsec); size = fill_attr(size, iax, SCOUTFS_IOC_IAX_SIZE, size, i_size_read(inode)); @@ -223,10 +223,8 @@ int scoutfs_set_attr_x(struct inode *inode, struct scoutfs_ioctl_inode_attr_x *i scoutfs_inode_set_data_version(inode, iax->data_version); if (iax->x_mask & SCOUTFS_IOC_IAX_SIZE) i_size_write(inode, iax->size); - if (iax->x_mask & SCOUTFS_IOC_IAX_CTIME) { - inode->i_ctime.tv_sec = iax->ctime_sec; - inode->i_ctime.tv_nsec = iax->ctime_nsec; - } + if (iax->x_mask & SCOUTFS_IOC_IAX_CTIME) + inode_set_ctime(inode, iax->ctime_sec, iax->ctime_nsec); if (iax->x_mask & SCOUTFS_IOC_IAX_CRTIME) { si->crtime.tv_sec = iax->crtime_sec; si->crtime.tv_nsec = iax->crtime_nsec; diff --git a/kmod/src/data.c b/kmod/src/data.c index 7903e8d7..9c164542 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -1483,12 +1483,14 @@ int scoutfs_data_move_blocks(struct inode *from, u64 from_off, cur_time = current_time(from); if (!is_stage) { - to->i_ctime = to->i_mtime = cur_time; + inode_set_ctime_to_ts(to, cur_time); + inode_set_mtime_to_ts(to, cur_time); inode_inc_iversion(to); scoutfs_inode_inc_data_version(to); scoutfs_inode_set_data_seq(to); } - from->i_ctime = from->i_mtime = cur_time; + inode_set_ctime_to_ts(from, cur_time); + inode_set_mtime_to_ts(from, cur_time); inode_inc_iversion(from); scoutfs_inode_inc_data_version(from); scoutfs_inode_set_data_seq(from); diff --git a/kmod/src/dir.c b/kmod/src/dir.c index 8a95d6a4..a4fa61cd 100644 --- a/kmod/src/dir.c +++ b/kmod/src/dir.c @@ -759,6 +759,7 @@ static int scoutfs_mknod(KC_VFS_NS_DEF struct scoutfs_lock *dir_lock = NULL; struct scoutfs_lock *inode_lock = NULL; struct scoutfs_inode_info *si; + struct kc_timespec cur_time; LIST_HEAD(ind_locks); u64 hash; u64 pos; @@ -790,9 +791,13 @@ static int scoutfs_mknod(KC_VFS_NS_DEF set_dentry_fsdata(dentry, dir_lock); i_size_write(dir, i_size_read(dir) + dentry->d_name.len); - dir->i_mtime = dir->i_ctime = current_time(inode); - inode->i_mtime = inode->i_atime = inode->i_ctime = dir->i_mtime; - si->crtime = inode->i_mtime; + cur_time = current_time(inode); + inode_set_mtime_to_ts(dir, cur_time); + inode_set_ctime_to_ts(dir, cur_time); + inode_set_mtime_to_ts(inode, cur_time); + inode_set_atime_to_ts(inode, cur_time); + inode_set_ctime_to_ts(inode, cur_time); + si->crtime = inode_get_mtime(inode); inode_inc_iversion(dir); inode_inc_iversion(inode); scoutfs_forest_inc_inode_count(sb); @@ -845,6 +850,7 @@ static int scoutfs_link(struct dentry *old_dentry, struct scoutfs_lock *dir_lock; struct scoutfs_lock *inode_lock = NULL; struct scoutfs_lock *orph_lock = NULL; + struct kc_timespec cur_time; LIST_HEAD(ind_locks); bool del_orphan = false; u64 dir_size; @@ -919,8 +925,10 @@ retry: set_dentry_fsdata(dentry, dir_lock); i_size_write(dir, dir_size); - dir->i_mtime = dir->i_ctime = current_time(inode); - inode->i_ctime = dir->i_mtime; + cur_time = current_time(inode); + inode_set_mtime_to_ts(dir, cur_time); + inode_set_ctime_to_ts(dir, cur_time); + inode_set_ctime_to_ts(inode, inode_get_mtime(dir)); inc_nlink(inode); inode_inc_iversion(dir); inode_inc_iversion(inode); @@ -1030,13 +1038,13 @@ retry: set_dentry_fsdata(dentry, dir_lock); - dir->i_ctime = ts; - dir->i_mtime = ts; + inode_set_ctime_to_ts(dir, ts); + inode_set_mtime_to_ts(dir, ts); i_size_write(dir, i_size_read(dir) - dentry->d_name.len); inode_inc_iversion(dir); inode_inc_iversion(inode); - inode->i_ctime = ts; + inode_set_ctime_to_ts(inode, ts); drop_nlink(inode); if (S_ISDIR(inode->i_mode)) { drop_nlink(dir); @@ -1239,6 +1247,7 @@ static int scoutfs_symlink(KC_VFS_NS_DEF struct scoutfs_lock *dir_lock = NULL; struct scoutfs_lock *inode_lock = NULL; struct scoutfs_inode_info *si; + struct kc_timespec cur_time; LIST_HEAD(ind_locks); u64 hash; u64 pos; @@ -1278,11 +1287,13 @@ static int scoutfs_symlink(KC_VFS_NS_DEF set_dentry_fsdata(dentry, dir_lock); i_size_write(dir, i_size_read(dir) + dentry->d_name.len); - dir->i_mtime = dir->i_ctime = current_time(inode); + cur_time = current_time(inode); + inode_set_mtime_to_ts(dir, cur_time); + inode_set_ctime_to_ts(dir, cur_time); inode_inc_iversion(dir); - inode->i_ctime = dir->i_mtime; - si->crtime = inode->i_ctime; + inode_set_ctime_to_ts(inode, inode_get_mtime(dir)); + si->crtime = inode_get_ctime(inode); i_size_write(inode, name_len); inode_inc_iversion(inode); scoutfs_forest_inc_inode_count(sb); @@ -1804,15 +1815,15 @@ retry: } now = current_time(old_inode); - old_dir->i_ctime = now; - old_dir->i_mtime = now; + inode_set_ctime_to_ts(old_dir, now); + inode_set_mtime_to_ts(old_dir, now); if (new_dir != old_dir) { - new_dir->i_ctime = now; - new_dir->i_mtime = now; + inode_set_ctime_to_ts(new_dir, now); + inode_set_mtime_to_ts(new_dir, now); } - old_inode->i_ctime = now; + inode_set_ctime_to_ts(old_inode, now); if (new_inode) - new_inode->i_ctime = now; + inode_set_ctime_to_ts(new_inode, now); inode_inc_iversion(old_dir); inode_inc_iversion(old_inode); @@ -1939,6 +1950,7 @@ static int scoutfs_tmpfile(KC_VFS_NS_DEF struct scoutfs_lock *inode_lock = NULL; struct scoutfs_lock *orph_lock = NULL; struct scoutfs_inode_info *si; + struct kc_timespec cur_time; LIST_HEAD(ind_locks); int ret; @@ -1955,8 +1967,11 @@ static int scoutfs_tmpfile(KC_VFS_NS_DEF if (ret < 0) goto out; /* XXX returning error but items created */ - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); - si->crtime = inode->i_mtime; + cur_time = current_time(inode); + inode_set_mtime_to_ts(inode, cur_time); + inode_set_ctime_to_ts(inode, cur_time); + inode_set_atime_to_ts(inode, cur_time); + si->crtime = inode_get_mtime(inode); insert_inode_hash(inode); ihold(inode); /* need to update inode modifications in d_tmpfile */ #ifdef KC_D_TMPFILE_DENTRY diff --git a/kmod/src/inode.c b/kmod/src/inode.c index 544b0eaa..4cb6a0d8 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -261,12 +261,9 @@ static void load_inode(struct inode *inode, struct scoutfs_inode *cinode, int in i_gid_write(inode, le32_to_cpu(cinode->gid)); inode->i_mode = le32_to_cpu(cinode->mode); inode->i_rdev = le32_to_cpu(cinode->rdev); - inode->i_atime.tv_sec = le64_to_cpu(cinode->atime.sec); - inode->i_atime.tv_nsec = le32_to_cpu(cinode->atime.nsec); - inode->i_mtime.tv_sec = le64_to_cpu(cinode->mtime.sec); - inode->i_mtime.tv_nsec = le32_to_cpu(cinode->mtime.nsec); - inode->i_ctime.tv_sec = le64_to_cpu(cinode->ctime.sec); - inode->i_ctime.tv_nsec = le32_to_cpu(cinode->ctime.nsec); + inode_set_atime(inode, le64_to_cpu(cinode->atime.sec), le32_to_cpu(cinode->atime.nsec)); + inode_set_mtime(inode, le64_to_cpu(cinode->mtime.sec), le32_to_cpu(cinode->mtime.nsec)); + inode_set_ctime(inode, le64_to_cpu(cinode->ctime.sec), le32_to_cpu(cinode->ctime.nsec)); si->meta_seq = le64_to_cpu(cinode->meta_seq); si->data_seq = le64_to_cpu(cinode->data_seq); @@ -398,6 +395,7 @@ static int set_inode_size(struct inode *inode, struct scoutfs_lock *lock, { struct scoutfs_inode_info *si = SCOUTFS_I(inode); struct super_block *sb = inode->i_sb; + struct kc_timespec cur_time; SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_ent); LIST_HEAD(ind_locks); int ret; @@ -420,7 +418,9 @@ static int set_inode_size(struct inode *inode, struct scoutfs_lock *lock, scoutfs_inode_inc_data_version(inode); truncate_setsize(inode, new_size); - inode->i_ctime = inode->i_mtime = current_time(inode); + cur_time = current_time(inode); + inode_set_ctime_to_ts(inode, cur_time); + inode_set_mtime_to_ts(inode, cur_time); if (truncate) si->flags |= SCOUTFS_INO_FLAG_TRUNCATE; scoutfs_inode_set_data_seq(inode); @@ -887,14 +887,14 @@ static void store_inode(struct scoutfs_inode *cinode, struct inode *inode, int i cinode->gid = cpu_to_le32(i_gid_read(inode)); cinode->mode = cpu_to_le32(inode->i_mode); cinode->rdev = cpu_to_le32(inode->i_rdev); - cinode->atime.sec = cpu_to_le64(inode->i_atime.tv_sec); - cinode->atime.nsec = cpu_to_le32(inode->i_atime.tv_nsec); + cinode->atime.sec = cpu_to_le64(inode_get_atime_sec(inode)); + cinode->atime.nsec = cpu_to_le32(inode_get_atime_nsec(inode)); memset(cinode->atime.__pad, 0, sizeof(cinode->atime.__pad)); - cinode->ctime.sec = cpu_to_le64(inode->i_ctime.tv_sec); - cinode->ctime.nsec = cpu_to_le32(inode->i_ctime.tv_nsec); + cinode->ctime.sec = cpu_to_le64(inode_get_ctime_sec(inode)); + cinode->ctime.nsec = cpu_to_le32(inode_get_ctime_nsec(inode)); memset(cinode->ctime.__pad, 0, sizeof(cinode->ctime.__pad)); - cinode->mtime.sec = cpu_to_le64(inode->i_mtime.tv_sec); - cinode->mtime.nsec = cpu_to_le32(inode->i_mtime.tv_nsec); + cinode->mtime.sec = cpu_to_le64(inode_get_mtime_sec(inode)); + cinode->mtime.nsec = cpu_to_le32(inode_get_mtime_nsec(inode)); memset(cinode->mtime.__pad, 0, sizeof(cinode->mtime.__pad)); cinode->meta_seq = cpu_to_le64(scoutfs_inode_meta_seq(inode)); @@ -1541,6 +1541,7 @@ int scoutfs_new_inode(struct super_block *sb, struct inode *dir, umode_t mode, d struct scoutfs_inode sinode; struct scoutfs_key key; struct inode *inode; + struct kc_timespec cur_time; int inode_bytes; int ret; @@ -1570,7 +1571,10 @@ int scoutfs_new_inode(struct super_block *sb, struct inode *dir, umode_t mode, d inode_init_owner(KC_VFS_INIT_NS inode, dir, mode); inode_set_bytes(inode, 0); - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + cur_time = current_time(inode); + inode_set_mtime_to_ts(inode, cur_time); + inode_set_atime_to_ts(inode, cur_time); + inode_set_ctime_to_ts(inode, cur_time); inode->i_rdev = rdev; set_inode_ops(inode); diff --git a/kmod/src/kernelcompat.c b/kmod/src/kernelcompat.c index cf1de599..2289ab13 100644 --- a/kmod/src/kernelcompat.c +++ b/kmod/src/kernelcompat.c @@ -81,3 +81,13 @@ kc_generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, return written ? written : status; } #endif + +#ifndef KC_FS_INODE_C_TIME_ACCESSOR +struct timespec64 inode_set_ctime_current(struct inode *inode) +{ + struct timespec64 now = current_time(inode); + + inode_set_ctime(inode, now.tv_sec, now.tv_nsec); + return now; +} +#endif diff --git a/kmod/src/kernelcompat.h b/kmod/src/kernelcompat.h index 7d7c4519..8af0b5f8 100644 --- a/kmod/src/kernelcompat.h +++ b/kmod/src/kernelcompat.h @@ -414,4 +414,99 @@ static inline vm_fault_t vmf_error(int err) #define get_random_u32_below prandom_u32_max #endif +#ifndef KC_FS_INODE_C_TIME_ACCESSOR +struct timespec64 inode_set_ctime_current(struct inode *inode); +static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode, + struct timespec64 ts) +{ + inode->i_ctime.tv_sec = ts.tv_sec; + inode->i_ctime.tv_nsec = ts.tv_nsec; + return ts; +} + +static inline struct timespec64 inode_set_ctime(struct inode *inode, + time64_t sec, long nsec) +{ + struct timespec64 ts = { .tv_sec = sec, + .tv_nsec = nsec }; + + return inode_set_ctime_to_ts(inode, ts); +} + +static inline struct timespec64 inode_get_ctime(const struct inode *inode) +{ + struct timespec64 ts = { .tv_sec = inode->i_ctime.tv_sec, + .tv_nsec = inode->i_ctime.tv_nsec }; + return ts; +} +#endif + +#ifndef KC_FS_INODE_AM_TIME_ACCESSOR +static inline struct timespec64 inode_get_mtime(const struct inode *inode) +{ + struct timespec64 ts = { .tv_sec = inode->i_mtime.tv_sec, + .tv_nsec = inode->i_mtime.tv_nsec }; + return ts; +} + +static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode, + struct timespec64 ts) +{ + inode->i_mtime.tv_sec = ts.tv_sec; + inode->i_mtime.tv_nsec = ts.tv_nsec; + return ts; +} + +static inline struct timespec64 inode_set_mtime(struct inode *inode, + time64_t sec, long nsec) +{ + struct timespec64 ts = { .tv_sec = sec, + .tv_nsec = nsec }; + + return inode_set_mtime_to_ts(inode, ts); +} + +static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode, + struct timespec64 ts) +{ + inode->i_atime.tv_sec = ts.tv_sec; + inode->i_atime.tv_nsec = ts.tv_nsec; + return ts; +} + +static inline struct timespec64 inode_set_atime(struct inode *inode, + time64_t sec, long nsec) +{ + struct timespec64 ts = { .tv_sec = sec, + .tv_nsec = nsec }; + + return inode_set_atime_to_ts(inode, ts); +} + +static inline time64_t inode_get_ctime_sec(const struct inode *inode) +{ + return inode->i_ctime.tv_sec; +} +static inline long inode_get_ctime_nsec(const struct inode *inode) +{ + return inode->i_ctime.tv_nsec; +} +static inline time64_t inode_get_mtime_sec(const struct inode *inode) +{ + return inode->i_mtime.tv_sec; +} +static inline long inode_get_mtime_nsec(const struct inode *inode) +{ + return inode->i_mtime.tv_nsec; +} +static inline time64_t inode_get_atime_sec(const struct inode *inode) +{ + return inode->i_atime.tv_sec; +} +static inline long inode_get_atime_nsec(const struct inode *inode) +{ + return inode->i_atime.tv_nsec; +} +#endif + #endif diff --git a/kmod/src/xattr.c b/kmod/src/xattr.c index 09db9927..6217d2dc 100644 --- a/kmod/src/xattr.c +++ b/kmod/src/xattr.c @@ -907,7 +907,7 @@ int scoutfs_xattr_set_locked(struct inode *inode, const char *name, size_t name_ /* XXX do these want i_mutex or anything? */ inode_inc_iversion(inode); - inode->i_ctime = current_time(inode); + inode_set_ctime_to_ts(inode, current_time(inode)); ret = 0; out: