2021-03-24 19:54:45

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 2/3] NFS: Don't revalidate attributes that are not being asked for

From: Trond Myklebust <[email protected]>

If the user doesn't set STATX_UID/GID/MODE, then don't care if they are
known to be stale. Ditto if we're not being asked for the file size.

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/inode.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 398f814ff8f8..001a6e4aabfd 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -852,12 +852,20 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
/* Check whether the cached attributes are stale */
do_update |= force_sync || nfs_attribute_cache_expired(inode);
cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
- do_update |= cache_validity &
- (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL);
+ do_update |= cache_validity & NFS_INO_INVALID_CHANGE;
if (request_mask & STATX_ATIME)
do_update |= cache_validity & NFS_INO_INVALID_ATIME;
- if (request_mask & (STATX_CTIME|STATX_MTIME))
- do_update |= cache_validity & NFS_INO_REVAL_PAGECACHE;
+ if (request_mask & STATX_CTIME)
+ do_update |= cache_validity &
+ (NFS_INO_INVALID_CTIME | NFS_INO_REVAL_PAGECACHE);
+ if (request_mask & STATX_MTIME)
+ do_update |= cache_validity &
+ (NFS_INO_INVALID_MTIME | NFS_INO_REVAL_PAGECACHE);
+ if (request_mask & STATX_SIZE)
+ do_update |= cache_validity &
+ (NFS_INO_INVALID_SIZE | NFS_INO_REVAL_PAGECACHE);
+ if (request_mask & (STATX_UID | STATX_GID | STATX_MODE | STATX_NLINK))
+ do_update |= cache_validity & NFS_INO_INVALID_OTHER;
if (request_mask & STATX_BLOCKS)
do_update |= cache_validity & NFS_INO_INVALID_BLOCKS;
if (do_update) {
--
2.30.2


2021-03-24 19:54:50

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 3/3] NFS: Fix up statx() results

From: Trond Myklebust <[email protected]>

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 <[email protected]>
---
fs/nfs/inode.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 001a6e4aabfd..3699f9fc8e15 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -805,6 +805,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)
{
@@ -819,7 +841,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. */
@@ -868,6 +890,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))
@@ -881,8 +904,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))
--
2.30.2