]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fs: switch timespec64 fields in inode to discrete integers
authorJeff Layton <jlayton@kernel.org>
Sat, 18 May 2024 00:08:40 +0000 (20:08 -0400)
committerChristian Brauner <brauner@kernel.org>
Mon, 27 May 2024 13:58:46 +0000 (15:58 +0200)
Adjacent struct timespec64's pack poorly. Switch them to discrete
integer fields for the seconds and nanoseconds. This shaves 8 bytes off
struct inode with a garden-variety Fedora Kconfig on x86_64, but that
also moves the i_lock into the previous cacheline, away from the fields
it protects.

To remedy that, move i_generation above the i_lock, which moves the new
4-byte hole to just after the i_fsnotify_mask in my setup. Amir has
plans to use that to expand the i_fsnotify_mask, so add a comment to
that effect as well.

Cc: Amir Goldstein <amir73il@gmail.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://lore.kernel.org/r/20240517-amtime-v1-1-7b804ca4be8f@kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
include/linux/fs.h

index 0283cf366c2a93fd0799e7acf14973b93fb64301..63988562160841971c0d6f60f4daaf6861173016 100644 (file)
@@ -660,9 +660,13 @@ struct inode {
        };
        dev_t                   i_rdev;
        loff_t                  i_size;
-       struct timespec64       __i_atime;
-       struct timespec64       __i_mtime;
-       struct timespec64       __i_ctime; /* use inode_*_ctime accessors! */
+       time64_t                i_atime_sec;
+       time64_t                i_mtime_sec;
+       time64_t                i_ctime_sec;
+       u32                     i_atime_nsec;
+       u32                     i_mtime_nsec;
+       u32                     i_ctime_nsec;
+       u32                     i_generation;
        spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
        unsigned short          i_bytes;
        u8                      i_blkbits;
@@ -719,10 +723,10 @@ struct inode {
                unsigned                i_dir_seq;
        };
 
-       __u32                   i_generation;
 
 #ifdef CONFIG_FSNOTIFY
        __u32                   i_fsnotify_mask; /* all events this inode cares about */
+       /* 32-bit hole reserved for expanding i_fsnotify_mask */
        struct fsnotify_mark_connector __rcu    *i_fsnotify_marks;
 #endif
 
@@ -1538,23 +1542,27 @@ struct timespec64 inode_set_ctime_current(struct inode *inode);
 
 static inline time64_t inode_get_atime_sec(const struct inode *inode)
 {
-       return inode->__i_atime.tv_sec;
+       return inode->i_atime_sec;
 }
 
 static inline long inode_get_atime_nsec(const struct inode *inode)
 {
-       return inode->__i_atime.tv_nsec;
+       return inode->i_atime_nsec;
 }
 
 static inline struct timespec64 inode_get_atime(const struct inode *inode)
 {
-       return inode->__i_atime;
+       struct timespec64 ts = { .tv_sec  = inode_get_atime_sec(inode),
+                                .tv_nsec = inode_get_atime_nsec(inode) };
+
+       return ts;
 }
 
 static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode,
                                                      struct timespec64 ts)
 {
-       inode->__i_atime = ts;
+       inode->i_atime_sec = ts.tv_sec;
+       inode->i_atime_nsec = ts.tv_nsec;
        return ts;
 }
 
@@ -1563,28 +1571,32 @@ static inline struct timespec64 inode_set_atime(struct inode *inode,
 {
        struct timespec64 ts = { .tv_sec  = sec,
                                 .tv_nsec = nsec };
+
        return inode_set_atime_to_ts(inode, ts);
 }
 
 static inline time64_t inode_get_mtime_sec(const struct inode *inode)
 {
-       return inode->__i_mtime.tv_sec;
+       return inode->i_mtime_sec;
 }
 
 static inline long inode_get_mtime_nsec(const struct inode *inode)
 {
-       return inode->__i_mtime.tv_nsec;
+       return inode->i_mtime_nsec;
 }
 
 static inline struct timespec64 inode_get_mtime(const struct inode *inode)
 {
-       return inode->__i_mtime;
+       struct timespec64 ts = { .tv_sec  = inode_get_mtime_sec(inode),
+                                .tv_nsec = inode_get_mtime_nsec(inode) };
+       return ts;
 }
 
 static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode,
                                                      struct timespec64 ts)
 {
-       inode->__i_mtime = ts;
+       inode->i_mtime_sec = ts.tv_sec;
+       inode->i_mtime_nsec = ts.tv_nsec;
        return ts;
 }
 
@@ -1598,23 +1610,27 @@ static inline struct timespec64 inode_set_mtime(struct inode *inode,
 
 static inline time64_t inode_get_ctime_sec(const struct inode *inode)
 {
-       return inode->__i_ctime.tv_sec;
+       return inode->i_ctime_sec;
 }
 
 static inline long inode_get_ctime_nsec(const struct inode *inode)
 {
-       return inode->__i_ctime.tv_nsec;
+       return inode->i_ctime_nsec;
 }
 
 static inline struct timespec64 inode_get_ctime(const struct inode *inode)
 {
-       return inode->__i_ctime;
+       struct timespec64 ts = { .tv_sec  = inode_get_ctime_sec(inode),
+                                .tv_nsec = inode_get_ctime_nsec(inode) };
+
+       return ts;
 }
 
 static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode,
                                                      struct timespec64 ts)
 {
-       inode->__i_ctime = ts;
+       inode->i_ctime_sec = ts.tv_sec;
+       inode->i_ctime_nsec = ts.tv_nsec;
        return ts;
 }