From 65f08190ed43fbd9fc88aba3e2c794dd30db0fbf Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Mon, 21 Apr 2025 10:33:56 -0700 Subject: [PATCH] Use a/m/c_time accessor functions In v6.6-rc5-1-g077c212f0344, one can no longer directly access the inode m_time and a_time etc. We have to go through these static inline functions to get to them. The compat is matched closely to mimic the new functions. Further back, ctime accessors were added in v6.5-rc1-7-g9b6304c1d537, and need to be applied as well. Signed-off-by: Auke Kok --- kmod/src/Makefile.kernelcompat | 16 ++++++ kmod/src/acl.c | 2 +- kmod/src/attr_x.c | 10 ++-- kmod/src/data.c | 6 ++- kmod/src/dir.c | 53 ++++++++++++------- kmod/src/inode.c | 32 +++++++----- kmod/src/kernelcompat.c | 10 ++++ kmod/src/kernelcompat.h | 95 ++++++++++++++++++++++++++++++++++ kmod/src/xattr.c | 2 +- 9 files changed, 183 insertions(+), 43 deletions(-) diff --git a/kmod/src/Makefile.kernelcompat b/kmod/src/Makefile.kernelcompat index 22788168..7d9ee9cd 100644 --- a/kmod/src/Makefile.kernelcompat +++ b/kmod/src/Makefile.kernelcompat @@ -505,6 +505,22 @@ 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 + # # v6.15-13744-g41cb08555c41 # diff --git a/kmod/src/acl.c b/kmod/src/acl.c index 356e3107..be1aed4e 100644 --- a/kmod/src/acl.c +++ b/kmod/src/acl.c @@ -197,7 +197,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 b6ca5eb1..d8696c14 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -1493,12 +1493,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 efcdef24..4d7a9268 100644 --- a/kmod/src/dir.c +++ b/kmod/src/dir.c @@ -761,6 +761,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; @@ -792,9 +793,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); @@ -847,6 +852,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; @@ -921,8 +927,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); @@ -1032,13 +1040,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); @@ -1241,6 +1249,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; @@ -1280,11 +1289,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); @@ -1806,15 +1817,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); @@ -1941,6 +1952,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; @@ -1957,8 +1969,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 cb7ccb50..fad8dc57 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -275,12 +275,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); @@ -412,6 +409,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; @@ -434,7 +432,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); @@ -902,14 +902,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)); @@ -1567,6 +1567,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; @@ -1596,7 +1597,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 2463d134..fc5e895c 100644 --- a/kmod/src/kernelcompat.c +++ b/kmod/src/kernelcompat.c @@ -147,3 +147,13 @@ unsigned long kc_list_lru_shrink_walk(struct list_lru *lru, struct shrink_contro } #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 f15b89d5..e624fb9e 100644 --- a/kmod/src/kernelcompat.h +++ b/kmod/src/kernelcompat.h @@ -493,6 +493,101 @@ static inline void stack_trace_print(unsigned long *entries, unsigned int nr_ent #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 + #ifndef KC_TIMER_CONTAINER_OF #define timer_container_of(var, callback_timer, timer_fieldname) \ from_timer(var, callback_timer, timer_fieldname) diff --git a/kmod/src/xattr.c b/kmod/src/xattr.c index d8c468e3..39f55302 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: