fs: new accessor methods for atime and mtime

Recently, we converted the ctime accesses in the kernel to use new
accessor functions. Linus recently pointed out though that if we add
accessors for the atime and mtime, then that would allow us to
seamlessly change how these timestamps are stored in the inode.

Add new accessor functions for the atime and mtime that mirror the
accessors for the ctime.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://lore.kernel.org/r/20231004185239.80830-1-jlayton@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Jeff Layton 2023-10-04 14:52:37 -04:00 committed by Christian Brauner
parent 94f6f0550c
commit 077c212f03
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
2 changed files with 102 additions and 24 deletions

View File

@ -541,7 +541,8 @@ void simple_recursive_removal(struct dentry *dentry,
dput(victim); // unpin it dput(victim); // unpin it
} }
if (victim == dentry) { if (victim == dentry) {
inode->i_mtime = inode_set_ctime_current(inode); inode_set_mtime_to_ts(inode,
inode_set_ctime_current(inode));
if (d_is_dir(dentry)) if (d_is_dir(dentry))
drop_nlink(inode); drop_nlink(inode);
inode_unlock(inode); inode_unlock(inode);
@ -582,7 +583,7 @@ static int pseudo_fs_fill_super(struct super_block *s, struct fs_context *fc)
*/ */
root->i_ino = 1; root->i_ino = 1;
root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
root->i_atime = root->i_mtime = inode_set_ctime_current(root); simple_inode_init_ts(root);
s->s_root = d_make_root(root); s->s_root = d_make_root(root);
if (!s->s_root) if (!s->s_root)
return -ENOMEM; return -ENOMEM;
@ -638,8 +639,8 @@ int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *den
{ {
struct inode *inode = d_inode(old_dentry); struct inode *inode = d_inode(old_dentry);
dir->i_mtime = inode_set_ctime_to_ts(dir, inode_set_mtime_to_ts(dir,
inode_set_ctime_current(inode)); inode_set_ctime_to_ts(dir, inode_set_ctime_current(inode)));
inc_nlink(inode); inc_nlink(inode);
ihold(inode); ihold(inode);
dget(dentry); dget(dentry);
@ -673,8 +674,8 @@ int simple_unlink(struct inode *dir, struct dentry *dentry)
{ {
struct inode *inode = d_inode(dentry); struct inode *inode = d_inode(dentry);
dir->i_mtime = inode_set_ctime_to_ts(dir, inode_set_mtime_to_ts(dir,
inode_set_ctime_current(inode)); inode_set_ctime_to_ts(dir, inode_set_ctime_current(inode)));
drop_nlink(inode); drop_nlink(inode);
dput(dentry); dput(dentry);
return 0; return 0;
@ -709,9 +710,10 @@ void simple_rename_timestamp(struct inode *old_dir, struct dentry *old_dentry,
{ {
struct inode *newino = d_inode(new_dentry); struct inode *newino = d_inode(new_dentry);
old_dir->i_mtime = inode_set_ctime_current(old_dir); inode_set_mtime_to_ts(old_dir, inode_set_ctime_current(old_dir));
if (new_dir != old_dir) if (new_dir != old_dir)
new_dir->i_mtime = inode_set_ctime_current(new_dir); inode_set_mtime_to_ts(new_dir,
inode_set_ctime_current(new_dir));
inode_set_ctime_current(d_inode(old_dentry)); inode_set_ctime_current(d_inode(old_dentry));
if (newino) if (newino)
inode_set_ctime_current(newino); inode_set_ctime_current(newino);
@ -926,7 +928,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic,
*/ */
inode->i_ino = 1; inode->i_ino = 1;
inode->i_mode = S_IFDIR | 0755; inode->i_mode = S_IFDIR | 0755;
inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); simple_inode_init_ts(inode);
inode->i_op = &simple_dir_inode_operations; inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations; inode->i_fop = &simple_dir_operations;
set_nlink(inode, 2); set_nlink(inode, 2);
@ -952,7 +954,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic,
goto out; goto out;
} }
inode->i_mode = S_IFREG | files->mode; inode->i_mode = S_IFREG | files->mode;
inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); simple_inode_init_ts(inode);
inode->i_fop = files->ops; inode->i_fop = files->ops;
inode->i_ino = i; inode->i_ino = i;
d_add(dentry, inode); d_add(dentry, inode);
@ -1520,7 +1522,7 @@ struct inode *alloc_anon_inode(struct super_block *s)
inode->i_uid = current_fsuid(); inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid(); inode->i_gid = current_fsgid();
inode->i_flags |= S_PRIVATE; inode->i_flags |= S_PRIVATE;
inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); simple_inode_init_ts(inode);
return inode; return inode;
} }
EXPORT_SYMBOL(alloc_anon_inode); EXPORT_SYMBOL(alloc_anon_inode);
@ -1912,3 +1914,20 @@ ssize_t direct_write_fallback(struct kiocb *iocb, struct iov_iter *iter,
return direct_written + buffered_written; return direct_written + buffered_written;
} }
EXPORT_SYMBOL_GPL(direct_write_fallback); EXPORT_SYMBOL_GPL(direct_write_fallback);
/**
* simple_inode_init_ts - initialize the timestamps for a new inode
* @inode: inode to be initialized
*
* When a new inode is created, most filesystems set the timestamps to the
* current time. Add a helper to do this.
*/
struct timespec64 simple_inode_init_ts(struct inode *inode)
{
struct timespec64 ts = inode_set_ctime_current(inode);
inode_set_atime_to_ts(inode, ts);
inode_set_mtime_to_ts(inode, ts);
return ts;
}
EXPORT_SYMBOL(simple_inode_init_ts);

View File

@ -1511,24 +1511,81 @@ static inline bool fsuidgid_has_mapping(struct super_block *sb,
struct timespec64 current_time(struct inode *inode); struct timespec64 current_time(struct inode *inode);
struct timespec64 inode_set_ctime_current(struct inode *inode); struct timespec64 inode_set_ctime_current(struct inode *inode);
/** static inline time64_t inode_get_atime_sec(const struct inode *inode)
* inode_get_ctime - fetch the current ctime from the inode {
* @inode: inode from which to fetch ctime return inode->i_atime.tv_sec;
* }
* Grab the current ctime from the inode and return it.
*/ static inline long inode_get_atime_nsec(const struct inode *inode)
{
return inode->i_atime.tv_nsec;
}
static inline struct timespec64 inode_get_atime(const struct inode *inode)
{
return inode->i_atime;
}
static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode,
struct timespec64 ts)
{
inode->i_atime = ts;
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_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 struct timespec64 inode_get_mtime(const struct inode *inode)
{
return inode->i_mtime;
}
static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode,
struct timespec64 ts)
{
inode->i_mtime = ts;
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 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 struct timespec64 inode_get_ctime(const struct inode *inode) static inline struct timespec64 inode_get_ctime(const struct inode *inode)
{ {
return inode->__i_ctime; return inode->__i_ctime;
} }
/**
* inode_set_ctime_to_ts - set the ctime in the inode
* @inode: inode in which to set the ctime
* @ts: value to set in the ctime field
*
* Set the ctime in @inode to @ts
*/
static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode, static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode,
struct timespec64 ts) struct timespec64 ts)
{ {
@ -1553,6 +1610,8 @@ static inline struct timespec64 inode_set_ctime(struct inode *inode,
return inode_set_ctime_to_ts(inode, ts); return inode_set_ctime_to_ts(inode, ts);
} }
struct timespec64 simple_inode_init_ts(struct inode *inode);
/* /*
* Snapshotting support. * Snapshotting support.
*/ */