@@ -1030,6 +1030,8 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
generic_fillattr(d_inode(dentry), stat);
return 0;
}
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
fid = v9fs_fid_lookup(dentry);
if (IS_ERR(fid))
return PTR_ERR(fid);
@@ -743,6 +743,9 @@ int afs_getattr(const struct path *path, struct kstat *stat,
_enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation);
+ if (query_flags & AT_STATX_CACHED)
+ return -EAGAIN;
+
do {
read_seqbegin_or_lock(&vnode->cb_lock, &seq);
generic_fillattr(inode, stat);
@@ -2378,6 +2378,8 @@ int ceph_getattr(const struct path *path, struct kstat *stat,
/* Skip the getattr altogether if we're asked not to sync */
if (!(flags & AT_STATX_DONT_SYNC)) {
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
err = ceph_do_getattr(inode,
statx_to_caps(request_mask, inode->i_mode),
flags & AT_STATX_FORCE_SYNC);
@@ -2379,6 +2379,9 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
struct inode *inode = d_inode(dentry);
int rc;
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
+
/*
* We need to be sure that all dirty pages are written and the server
* has actual ctime, mtime and file length.
@@ -254,7 +254,12 @@ static void coda_evict_inode(struct inode *inode)
int coda_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags)
{
- int err = coda_revalidate_inode(d_inode(path->dentry));
+ int err;
+
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
+
+ err = coda_revalidate_inode(d_inode(path->dentry));
if (!err)
generic_fillattr(d_inode(path->dentry), stat);
return err;
@@ -980,6 +980,9 @@ static int ecryptfs_getattr_link(const struct path *path, struct kstat *stat,
char *target;
size_t targetsiz;
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
+
target = ecryptfs_readlink_lower(dentry, &targetsiz);
if (!IS_ERR(target)) {
kfree(target);
@@ -1084,6 +1084,8 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
sync = time_before64(fi->i_time, get_jiffies_64());
if (sync) {
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
forget_all_cached_acls(inode);
err = fuse_do_getattr(inode, stat, file);
} else if (stat) {
@@ -2032,6 +2032,8 @@ static int gfs2_getattr(const struct path *path, struct kstat *stat,
gfs2_holder_mark_uninitialized(&gh);
if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
if (error)
return error;
@@ -189,7 +189,13 @@ int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
struct inode *inode = d_inode(path->dentry);
struct kernfs_node *kn = inode->i_private;
- mutex_lock(&kernfs_mutex);
+ if (query_flags & AT_STATX_CACHED) {
+ if (!mutex_trylock(&kernfs_mutex))
+ return -EAGAIN;
+ } else {
+ mutex_lock(&kernfs_mutex);
+ }
+
kernfs_refresh_inode(kn, inode);
mutex_unlock(&kernfs_mutex);
@@ -799,6 +799,9 @@ int nfs_getattr(const struct path *path, struct kstat *stat,
trace_nfs_getattr_enter(inode);
+ if (query_flags & AT_STATX_CACHED)
+ return -EAGAIN;
+
if ((query_flags & AT_STATX_DONT_SYNC) && !force_sync) {
nfs_readdirplus_parent_cache_hit(path->dentry);
goto out_no_update;
@@ -1306,6 +1306,9 @@ int ocfs2_getattr(const struct path *path, struct kstat *stat,
struct ocfs2_super *osb = sb->s_fs_info;
int err;
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
+
err = ocfs2_inode_revalidate(path->dentry);
if (err) {
if (err != -ENOENT)
@@ -900,6 +900,9 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
"orangefs_getattr: called on %pd mask %u\n",
path->dentry, request_mask);
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
+
ret = orangefs_inode_getattr(inode,
request_mask & STATX_SIZE ? ORANGEFS_GETATTR_SIZE : 0);
if (ret == 0) {
@@ -1573,7 +1573,12 @@ int ubifs_getattr(const struct path *path, struct kstat *stat,
struct inode *inode = d_inode(path->dentry);
struct ubifs_inode *ui = ubifs_inode(inode);
- mutex_lock(&ui->ui_mutex);
+ if (flags & AT_STATX_CACHED) {
+ if (!mutex_trylock(&ui->ui_mutex))
+ return -EAGAIN;
+ } else {
+ mutex_lock(&ui->ui_mutex);
+ }
if (ui->flags & UBIFS_APPEND_FL)
stat->attributes |= STATX_ATTR_APPEND;
@@ -159,6 +159,9 @@ static int udf_symlink_getattr(const struct path *path, struct kstat *stat,
struct inode *inode = d_backing_inode(dentry);
struct page *page;
+ if (flags & AT_STATX_CACHED)
+ return -EAGAIN;
+
generic_fillattr(inode, stat);
page = read_mapping_page(inode->i_mapping, 0, NULL);
if (IS_ERR(page))
@@ -228,6 +228,10 @@ int vboxsf_getattr(const struct path *path, struct kstat *kstat,
sf_i->force_restat = 1;
fallthrough;
default:
+ if (flags & AT_STATX_CACHED) {
+ err = -EAGAIN;
+ break;
+ }
err = vboxsf_inode_revalidate(dentry);
}
if (err)
For filesystems that provide a private ->getattr() implementation, some of them need to do IO to satisfy the request. If we need to block off ->getattr() and AT_STATX_CACHED is set, then return -EAGAIN and have the caller retry. Signed-off-by: Jens Axboe <axboe@kernel.dk> --- fs/9p/vfs_inode.c | 2 ++ fs/afs/inode.c | 3 +++ fs/ceph/inode.c | 2 ++ fs/cifs/inode.c | 3 +++ fs/coda/inode.c | 7 ++++++- fs/ecryptfs/inode.c | 3 +++ fs/fuse/dir.c | 2 ++ fs/gfs2/inode.c | 2 ++ fs/kernfs/inode.c | 8 +++++++- fs/nfs/inode.c | 3 +++ fs/ocfs2/file.c | 3 +++ fs/orangefs/inode.c | 3 +++ fs/ubifs/dir.c | 7 ++++++- fs/udf/symlink.c | 3 +++ fs/vboxsf/utils.c | 4 ++++ 15 files changed, 52 insertions(+), 3 deletions(-)