Patch "Revert "nfsd: skip some unnecessary stats in the v4 case"" has been added to the 5.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    Revert "nfsd: skip some unnecessary stats in the v4 case"

to the 5.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     revert-nfsd-skip-some-unnecessary-stats-in-the-v4-ca.patch
and it can be found in the queue-5.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit e55aa271cc61d2d595617f2a99a13d03c70a9de0
Author: Chuck Lever <chuck.lever@xxxxxxxxxx>
Date:   Fri Dec 24 14:22:28 2021 -0500

    Revert "nfsd: skip some unnecessary stats in the v4 case"
    
    [ Upstream commit 58f258f65267542959487dbe8b5641754411843d ]
    
    On the wire, I observed NFSv4 OPEN(CREATE) operations sometimes
    returning a reasonable-looking value in the cinfo.before field and
    zero in the cinfo.after field.
    
    RFC 8881 Section 10.8.1 says:
    > When a client is making changes to a given directory, it needs to
    > determine whether there have been changes made to the directory by
    > other clients.  It does this by using the change attribute as
    > reported before and after the directory operation in the associated
    > change_info4 value returned for the operation.
    
    and
    
    > ... The post-operation change
    > value needs to be saved as the basis for future change_info4
    > comparisons.
    
    A good quality client implementation therefore saves the zero
    cinfo.after value. During a subsequent OPEN operation, it will
    receive a different non-zero value in the cinfo.before field for
    that directory, and it will incorrectly believe the directory has
    changed, triggering an undesirable directory cache invalidation.
    
    There are filesystem types where fs_supports_change_attribute()
    returns false, tmpfs being one. On NFSv4 mounts, this means the
    fh_getattr() call site in fill_pre_wcc() and fill_post_wcc() is
    never invoked. Subsequently, nfsd4_change_attribute() is invoked
    with an uninitialized @stat argument.
    
    In fill_pre_wcc(), @stat contains stale stack garbage, which is
    then placed on the wire. In fill_post_wcc(), ->fh_post_wc is all
    zeroes, so zero is placed on the wire. Both of these values are
    meaningless.
    
    This fix can be applied immediately to stable kernels. Once there
    are more regression tests in this area, this optimization can be
    attempted again.
    
    Fixes: 428a23d2bf0c ("nfsd: skip some unnecessary stats in the v4 case")
    Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index c3ac1b6aa3aaa..84088581bbe09 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -487,11 +487,6 @@ svcxdr_encode_wcc_data(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 	return true;
 }
 
-static bool fs_supports_change_attribute(struct super_block *sb)
-{
-	return sb->s_flags & SB_I_VERSION || sb->s_export_op->fetch_iversion;
-}
-
 /*
  * Fill in the pre_op attr for the wcc data
  */
@@ -500,26 +495,24 @@ void fill_pre_wcc(struct svc_fh *fhp)
 	struct inode    *inode;
 	struct kstat	stat;
 	bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
+	__be32 err;
 
 	if (fhp->fh_no_wcc || fhp->fh_pre_saved)
 		return;
 	inode = d_inode(fhp->fh_dentry);
-	if (fs_supports_change_attribute(inode->i_sb) || !v4) {
-		__be32 err = fh_getattr(fhp, &stat);
-
-		if (err) {
-			/* Grab the times from inode anyway */
-			stat.mtime = inode->i_mtime;
-			stat.ctime = inode->i_ctime;
-			stat.size  = inode->i_size;
-		}
-		fhp->fh_pre_mtime = stat.mtime;
-		fhp->fh_pre_ctime = stat.ctime;
-		fhp->fh_pre_size  = stat.size;
+	err = fh_getattr(fhp, &stat);
+	if (err) {
+		/* Grab the times from inode anyway */
+		stat.mtime = inode->i_mtime;
+		stat.ctime = inode->i_ctime;
+		stat.size  = inode->i_size;
 	}
 	if (v4)
 		fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
 
+	fhp->fh_pre_mtime = stat.mtime;
+	fhp->fh_pre_ctime = stat.ctime;
+	fhp->fh_pre_size  = stat.size;
 	fhp->fh_pre_saved = true;
 }
 
@@ -530,6 +523,7 @@ void fill_post_wcc(struct svc_fh *fhp)
 {
 	bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
 	struct inode *inode = d_inode(fhp->fh_dentry);
+	__be32 err;
 
 	if (fhp->fh_no_wcc)
 		return;
@@ -537,16 +531,12 @@ void fill_post_wcc(struct svc_fh *fhp)
 	if (fhp->fh_post_saved)
 		printk("nfsd: inode locked twice during operation.\n");
 
-	fhp->fh_post_saved = true;
-
-	if (fs_supports_change_attribute(inode->i_sb) || !v4) {
-		__be32 err = fh_getattr(fhp, &fhp->fh_post_attr);
-
-		if (err) {
-			fhp->fh_post_saved = false;
-			fhp->fh_post_attr.ctime = inode->i_ctime;
-		}
-	}
+	err = fh_getattr(fhp, &fhp->fh_post_attr);
+	if (err) {
+		fhp->fh_post_saved = false;
+		fhp->fh_post_attr.ctime = inode->i_ctime;
+	} else
+		fhp->fh_post_saved = true;
 	if (v4)
 		fhp->fh_post_change =
 			nfsd4_change_attribute(&fhp->fh_post_attr, inode);




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux