summaryrefslogtreecommitdiff
path: root/fs/nfsd/nfs3xdr.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2020-11-30 17:46:14 -0500
committerChuck Lever <chuck.lever@oracle.com>2020-12-09 09:39:37 -0500
commit70b87f77294d16d3e567056ba4c9ee2b091a5b50 (patch)
tree557e788075d69a9eb9248a8cc6aeb3486dd5c348 /fs/nfsd/nfs3xdr.c
parent4a9d81caf841cd2c0ae36abec9c2963bf21d0284 (diff)
nfsd: only call inode_query_iversion in the I_VERSION case
inode_query_iversion() can modify i_version. Depending on the exported filesystem, that may not be safe. For example, if you're re-exporting NFS, NFS stores the server's change attribute in i_version and does not expect it to be modified locally. This has been observed causing unnecessary cache invalidations. The way a filesystem indicates that it's OK to call inode_query_iverson() is by setting SB_I_VERSION. So, move the I_VERSION check out of encode_change(), where it's used only in GETATTR responses, to nfsd4_change_attribute(), which is also called for pre- and post- operation attributes. (Note we could also pull the NFSEXP_V4ROOT case into nfsd4_change_attribute() as well. That would actually be a no-op, since pre/post attrs are only used for metadata-modifying operations, and V4ROOT exports are read-only. But we might make the change in the future just for simplicity.) Reported-by: Daire Byrne <daire@dneg.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'fs/nfsd/nfs3xdr.c')
-rw-r--r--fs/nfsd/nfs3xdr.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index a6718b952975..4599de24ef1a 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -291,14 +291,13 @@ void fill_post_wcc(struct svc_fh *fhp)
printk("nfsd: inode locked twice during operation.\n");
err = fh_getattr(fhp, &fhp->fh_post_attr);
- fhp->fh_post_change = nfsd4_change_attribute(&fhp->fh_post_attr,
- d_inode(fhp->fh_dentry));
if (err) {
fhp->fh_post_saved = false;
- /* Grab the ctime anyway - set_change_info might use it */
fhp->fh_post_attr.ctime = d_inode(fhp->fh_dentry)->i_ctime;
} else
fhp->fh_post_saved = true;
+ fhp->fh_post_change = nfsd4_change_attribute(&fhp->fh_post_attr,
+ d_inode(fhp->fh_dentry));
}
/*