Commit 63cdd7ed authored by Trond Myklebust's avatar Trond Myklebust

NFS: Fix up statx() results

If statx has valid attributes available that weren't asked for, then
return them and set the result mask appropriately.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent e8764a6f
...@@ -806,6 +806,28 @@ static bool nfs_need_revalidate_inode(struct inode *inode) ...@@ -806,6 +806,28 @@ static bool nfs_need_revalidate_inode(struct inode *inode)
return false; 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, int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
struct kstat *stat, u32 request_mask, unsigned int query_flags) struct kstat *stat, u32 request_mask, unsigned int query_flags)
{ {
...@@ -824,7 +846,7 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path, ...@@ -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) { if ((query_flags & AT_STATX_DONT_SYNC) && !force_sync) {
nfs_readdirplus_parent_cache_hit(path->dentry); 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. */ /* Flush out writes to the server in order to update c/mtime. */
...@@ -870,6 +892,7 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path, ...@@ -870,6 +892,7 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
do_update |= cache_validity & NFS_INO_INVALID_OTHER; do_update |= cache_validity & NFS_INO_INVALID_OTHER;
if (request_mask & STATX_BLOCKS) if (request_mask & STATX_BLOCKS)
do_update |= cache_validity & NFS_INO_INVALID_BLOCKS; do_update |= cache_validity & NFS_INO_INVALID_BLOCKS;
if (do_update) { if (do_update) {
/* Update the attribute cache */ /* Update the attribute cache */
if (!(server->flags & NFS_MOUNT_NOAC)) if (!(server->flags & NFS_MOUNT_NOAC))
...@@ -883,8 +906,8 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path, ...@@ -883,8 +906,8 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
nfs_readdirplus_parent_cache_hit(path->dentry); nfs_readdirplus_parent_cache_hit(path->dentry);
out_no_revalidate: out_no_revalidate:
/* Only return attributes that were revalidated. */ /* Only return attributes that were revalidated. */
stat->result_mask &= request_mask; stat->result_mask = nfs_get_valid_attrmask(inode) | request_mask;
out_no_update:
generic_fillattr(&init_user_ns, inode, stat); generic_fillattr(&init_user_ns, inode, stat);
stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode)); stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode));
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment