The current representation of inode times in struct inode, struct iattr, struct kstat: struct timespec are not y2038 safe.
Add provision to convert them to use 64 bit times in the future.
struct inode uses struct inode time to maintain same size for times across 32 bit and 64 bit architectures. structs iattr and kstat have no such requirement since these data types are only used to pass values in and out of vfs layer.
In addition, inode_time is defined as packed and aligned to a 4 byte boundary to make the structure use 12 bytes each instead of 16 bytes. This will help save RAM space as inode structure is cached in memory. The other structures are transient and such a change would not be beneficial.
Signed-off-by: Deepa Dinamani deepa.kernel@gmail.com --- include/linux/fs.h | 33 ++++++++++++++++++++++++++------- include/linux/stat.h | 12 +++++++++--- 2 files changed, 35 insertions(+), 10 deletions(-)
diff --git a/include/linux/fs.h b/include/linux/fs.h index ab8799c..a7d4657 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -245,13 +245,19 @@ typedef void (dax_iodone_t)(struct buffer_head *bh_map, int uptodate); */ struct iattr { unsigned int ia_valid; - umode_t ia_mode; - kuid_t ia_uid; - kgid_t ia_gid; - loff_t ia_size; - struct timespec ia_atime; - struct timespec ia_mtime; - struct timespec ia_ctime; + umode_t ia_mode; + kuid_t ia_uid; + kgid_t ia_gid; + loff_t ia_size; +#ifdef CONFIG_FS_USES_64BIT_TIME + struct timespec64 ia_atime; + struct timespec64 ia_mtime; + struct timespec64 ia_ctime; +#else + struct timespec ia_atime; + struct timespec ia_mtime; + struct timespec ia_ctime; +#endif
/* * Not an attribute, but an auxiliary info for filesystems wanting to @@ -616,9 +622,15 @@ struct inode { }; dev_t i_rdev; loff_t i_size; +#ifdef CONFIG_FS_USES_64BIT_TIME + struct inode_time i_atime; + struct inode_time i_mtime; + struct inode_time i_ctime; +#else struct timespec i_atime; struct timespec i_mtime; struct timespec i_ctime; +#endif spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned short i_bytes; unsigned int i_blkbits; @@ -679,10 +691,17 @@ struct inode { void *i_private; /* fs or device private pointer */ };
+#ifdef CONFIG_64BIT_INODE_TIME +#define FS_INODE_SET_XTIME(xtime, inode, ts64) \ + ((inode)->i_##xtime = timespec64_to_inode_time(ts64)) +#define FS_INODE_GET_XTIME(xtime, inode) \ + (inode_time_to_timespec64((inode)->i_##xtime)) +#else #define FS_INODE_SET_XTIME(xtime, inode, ts) \ ((inode)->i_##xtime = (ts)) #define FS_INODE_GET_XTIME(xtime, inode) \ ((inode)->i_##xtime) +#endif
static inline int inode_unhashed(struct inode *inode) { diff --git a/include/linux/stat.h b/include/linux/stat.h index 075cb0c..e3443a9 100644 --- a/include/linux/stat.h +++ b/include/linux/stat.h @@ -27,9 +27,15 @@ struct kstat { kgid_t gid; dev_t rdev; loff_t size; - struct timespec atime; - struct timespec mtime; - struct timespec ctime; +#ifdef CONFIG_FS_USES_64BIT_TIME + struct timespec64 atime; + struct timespec64 mtime; + struct timespec64 ctime; +#else + struct timespec atime; + struct timespec mtime; + struct timespec ctime; +#endif unsigned long blksize; unsigned long long blocks; };