From ac7b3db4bd4e49dcbbc511747e7a8e94f4db272c Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Tue, 23 Jun 2026 21:08:42 -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. 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 3a67cdb5..2e1bb251 100644 --- a/kmod/src/Makefile.kernelcompat +++ b/kmod/src/Makefile.kernelcompat @@ -222,6 +222,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 fa3066ed..50201fc2 100644 --- a/kmod/src/acl.c +++ b/kmod/src/acl.c @@ -184,7 +184,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 44ca4c9d..cfda5618 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -1529,12 +1529,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 622320c5..f708c3d9 100644 --- a/kmod/src/dir.c +++ b/kmod/src/dir.c @@ -751,6 +751,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 timespec64 cur_time; LIST_HEAD(ind_locks); u64 hash; u64 pos; @@ -782,9 +783,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); @@ -837,6 +842,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 timespec64 cur_time; LIST_HEAD(ind_locks); bool del_orphan = false; u64 dir_size; @@ -911,8 +917,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); @@ -1022,13 +1030,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); @@ -1212,6 +1220,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 timespec64 cur_time; LIST_HEAD(ind_locks); u64 hash; u64 pos; @@ -1251,11 +1260,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); @@ -1780,15 +1791,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); @@ -1886,6 +1897,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 timespec64 cur_time; LIST_HEAD(ind_locks); int ret; @@ -1902,8 +1914,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 3b536a86..87491eb3 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -258,12 +258,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); @@ -388,6 +385,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 timespec64 cur_time; SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_ent); LIST_HEAD(ind_locks); int ret; @@ -412,7 +410,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); @@ -880,14 +880,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)); @@ -1545,6 +1545,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 timespec64 cur_time; int inode_bytes; int ret; @@ -1574,7 +1575,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 6457728f..74c8a851 100644 --- a/kmod/src/kernelcompat.c +++ b/kmod/src/kernelcompat.c @@ -36,3 +36,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 55e23fdf..d236c654 100644 --- a/kmod/src/kernelcompat.h +++ b/kmod/src/kernelcompat.h @@ -211,6 +211,101 @@ unsigned long kc_list_lru_shrink_walk(struct list_lru *lru, struct shrink_contro #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 4ac83cad..34402f5a 100644 --- a/kmod/src/xattr.c +++ b/kmod/src/xattr.c @@ -908,7 +908,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: