1

fs: switch timespec64 fields in inode to discrete integers

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>
This commit is contained in:
Jeff Layton 2024-05-17 20:08:40 -04:00 committed by Christian Brauner
parent 23cc6ef6fd
commit 3aa63a569c

View 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;
}