diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2023-08-10 12:45:05 +0200 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2023-08-21 12:14:59 +0200 |
commit | 972f4c46d0a1bb7fde3ce0bd15775855b2d02c68 (patch) | |
tree | 04408bbb3e7e60b02f6b642cbc9c7b432336314e /fs/fuse/dir.c | |
parent | d3045530bdd29d91033eea437d8a961f4ee598b5 (diff) | |
download | linux-972f4c46d0a1bb7fde3ce0bd15775855b2d02c68.tar.gz linux-972f4c46d0a1bb7fde3ce0bd15775855b2d02c68.tar.bz2 linux-972f4c46d0a1bb7fde3ce0bd15775855b2d02c68.zip |
fuse: cache btime
Not all inode attributes are supported by all filesystems, but for the
basic stats (which are returned by stat(2) and friends) all of them will
have some value, even if that doesn't reflect a real attribute of the file.
Btime is different, in that filesystems are free to report or not report a
value in statx. If the value is available, then STATX_BTIME bit is set in
stx_mask.
When caching the value of btime, remember the availability of the attribute
as well as the value (if available). This is done by using the
FUSE_I_BTIME bit in fuse_inode->state to indicate availability, while using
fuse_inode->inval_mask & STATX_BTIME to indicate the state of the cache
itself (i.e. set if cache is invalid, and cleared if cache is valid).
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r-- | fs/fuse/dir.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e7f63e60118c..3db9d26d341e 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -255,7 +255,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) goto invalid; forget_all_cached_acls(inode); - fuse_change_attributes(inode, &outarg.attr, + fuse_change_attributes(inode, &outarg.attr, NULL, ATTR_TIMEOUT(&outarg), attr_version); fuse_change_entry_timeout(entry, &outarg); @@ -1213,8 +1213,8 @@ static int fuse_do_statx(struct inode *inode, struct file *file, fuse_statx_to_attr(&outarg.stat, &attr); if ((sx->mask & STATX_BASIC_STATS) == STATX_BASIC_STATS) { - fuse_change_attributes(inode, &attr, ATTR_TIMEOUT(&outarg), - attr_version); + fuse_change_attributes(inode, &attr, &outarg.stat, + ATTR_TIMEOUT(&outarg), attr_version); } stat->result_mask = sx->mask & (STATX_BASIC_STATS | STATX_BTIME); stat->btime.tv_sec = sx->btime.tv_sec; @@ -1261,7 +1261,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, fuse_make_bad(inode); err = -EIO; } else { - fuse_change_attributes(inode, &outarg.attr, + fuse_change_attributes(inode, &outarg.attr, NULL, ATTR_TIMEOUT(&outarg), attr_version); if (stat) @@ -1316,6 +1316,10 @@ retry: generic_fillattr(&nop_mnt_idmap, inode, stat); stat->mode = fi->orig_i_mode; stat->ino = fi->orig_ino; + if (test_bit(FUSE_I_BTIME, &fi->state)) { + stat->btime = fi->i_btime; + stat->result_mask |= STATX_BTIME; + } } return err; @@ -1952,7 +1956,7 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, /* FIXME: clear I_DIRTY_SYNC? */ } - fuse_change_attributes_common(inode, &outarg.attr, + fuse_change_attributes_common(inode, &outarg.attr, NULL, ATTR_TIMEOUT(&outarg), fuse_get_cache_mask(inode)); oldsize = inode->i_size; |