Skip to content

Commit

Permalink
NFS: Fix up statx() results
Browse files Browse the repository at this point in the history
If statx has valid attributes available that weren't asked for, then
return them and set the result mask appropriately.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
  • Loading branch information
Trond Myklebust committed Apr 12, 2021
1 parent e8764a6 commit 63cdd7e
Showing 1 changed file with 26 additions and 3 deletions.
29 changes: 26 additions & 3 deletions fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,28 @@ static bool nfs_need_revalidate_inode(struct inode *inode)
return false;
}

static u32 nfs_get_valid_attrmask(struct inode *inode)
{
unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
u32 reply_mask = STATX_INO | STATX_TYPE;

if (!(cache_validity & NFS_INO_INVALID_ATIME))
reply_mask |= STATX_ATIME;
if (!(cache_validity & NFS_INO_REVAL_PAGECACHE)) {
if (!(cache_validity & NFS_INO_INVALID_CTIME))
reply_mask |= STATX_CTIME;
if (!(cache_validity & NFS_INO_INVALID_MTIME))
reply_mask |= STATX_MTIME;
if (!(cache_validity & NFS_INO_INVALID_SIZE))
reply_mask |= STATX_SIZE;
}
if (!(cache_validity & NFS_INO_INVALID_OTHER))
reply_mask |= STATX_UID | STATX_GID | STATX_MODE | STATX_NLINK;
if (!(cache_validity & NFS_INO_INVALID_BLOCKS))
reply_mask |= STATX_BLOCKS;
return reply_mask;
}

int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
struct kstat *stat, u32 request_mask, unsigned int query_flags)
{
Expand All @@ -824,7 +846,7 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,

if ((query_flags & AT_STATX_DONT_SYNC) && !force_sync) {
nfs_readdirplus_parent_cache_hit(path->dentry);
goto out_no_update;
goto out_no_revalidate;
}

/* Flush out writes to the server in order to update c/mtime. */
Expand Down Expand Up @@ -870,6 +892,7 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
do_update |= cache_validity & NFS_INO_INVALID_OTHER;
if (request_mask & STATX_BLOCKS)
do_update |= cache_validity & NFS_INO_INVALID_BLOCKS;

if (do_update) {
/* Update the attribute cache */
if (!(server->flags & NFS_MOUNT_NOAC))
Expand All @@ -883,8 +906,8 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
nfs_readdirplus_parent_cache_hit(path->dentry);
out_no_revalidate:
/* Only return attributes that were revalidated. */
stat->result_mask &= request_mask;
out_no_update:
stat->result_mask = nfs_get_valid_attrmask(inode) | request_mask;

generic_fillattr(&init_user_ns, inode, stat);
stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode));
if (S_ISDIR(inode->i_mode))
Expand Down

0 comments on commit 63cdd7e

Please sign in to comment.