NFSv4: Don't invalidate inode attributes on delegation return
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 25 Apr 2022 22:04:27 +0000 (18:04 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 May 2022 10:30:15 +0000 (12:30 +0200)
commit 00c94ebec5925593c0377b941289224469e72ac7 upstream.

There is no need to declare attributes such as the ctime, mtime and
block size invalid when we're just returning a delegation, so it is
inappropriate to call nfs_post_op_update_inode_force_wcc().
Instead, just call nfs_refresh_inode() after faking up the change
attribute. We know that the GETATTR op occurs before the DELEGRETURN, so
we are safe when doing this.

Fixes: 0bc2c9b4dca9 ("NFSv4: Don't discard the attributes returned by asynchronous DELEGRETURN")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/nfs/nfs4proc.c

index dababa6cf3f42a156c2c3c196da8219d8845e647..ae6b3600ed11b58112971e92c45ea05e85a5ec00 100644 (file)
@@ -366,6 +366,14 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
        kunmap_atomic(start);
 }
 
+static void nfs4_fattr_set_prechange(struct nfs_fattr *fattr, u64 version)
+{
+       if (!(fattr->valid & NFS_ATTR_FATTR_PRECHANGE)) {
+               fattr->pre_change_attr = version;
+               fattr->valid |= NFS_ATTR_FATTR_PRECHANGE;
+       }
+}
+
 static void nfs4_test_and_free_stateid(struct nfs_server *server,
                nfs4_stateid *stateid,
                const struct cred *cred)
@@ -6558,7 +6566,9 @@ static void nfs4_delegreturn_release(void *calldata)
                pnfs_roc_release(&data->lr.arg, &data->lr.res,
                                 data->res.lr_ret);
        if (inode) {
-               nfs_post_op_update_inode_force_wcc(inode, &data->fattr);
+               nfs4_fattr_set_prechange(&data->fattr,
+                                        inode_peek_iversion_raw(inode));
+               nfs_refresh_inode(inode, &data->fattr);
                nfs_iput_and_deactive(inode);
        }
        kfree(calldata);