NFSv4: Delegreturn must set m/atime when they are delegated
authorTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 17 Jun 2024 01:21:29 +0000 (21:21 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Mon, 8 Jul 2024 17:47:25 +0000 (13:47 -0400)
If the atime or mtime attributes were delegated, then we need to
propagate their new values back to the server when returning the
delegation.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Lance Shelton <lance.shelton@hammerspace.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/nfs4proc.c

index d9117630e062057f2f33a24ce48ff66e68e1f6f4..d5edb3b3eeef0d5e1b1aaba7817d5958e9155a5c 100644 (file)
@@ -266,7 +266,9 @@ void nfs_inode_reclaim_delegation(struct inode *inode, const struct cred *cred,
        }
 }
 
-static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
+static int nfs_do_return_delegation(struct inode *inode,
+                                   struct nfs_delegation *delegation,
+                                   int issync)
 {
        const struct cred *cred;
        int res = 0;
@@ -275,9 +277,8 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
                spin_lock(&delegation->lock);
                cred = get_cred(delegation->cred);
                spin_unlock(&delegation->lock);
-               res = nfs4_proc_delegreturn(inode, cred,
-                               &delegation->stateid,
-                               issync);
+               res = nfs4_proc_delegreturn(inode, cred, &delegation->stateid,
+                                           delegation, issync);
                put_cred(cred);
        }
        return res;
index 001551e2ab6092f016285d8023dcf9869a937b24..71524d34ed207ca5cc53cc83559f82bef5c6f6f2 100644 (file)
@@ -70,7 +70,9 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp);
 void nfs_reap_expired_delegations(struct nfs_client *clp);
 
 /* NFSv4 delegation-related procedures */
-int nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, const nfs4_stateid *stateid, int issync);
+int nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
+                         const nfs4_stateid *stateid,
+                         struct nfs_delegation *delegation, int issync);
 int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
 int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid);
 bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred);
index 1209ce22158ed10b91e828529e317a27320d3f3f..88edeaf5b5d5d9a133df9c32e5a6f6ffdfdb425f 100644 (file)
@@ -6739,7 +6739,10 @@ static const struct rpc_call_ops nfs4_delegreturn_ops = {
        .rpc_release = nfs4_delegreturn_release,
 };
 
-static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, const nfs4_stateid *stateid, int issync)
+static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
+                                 const nfs4_stateid *stateid,
+                                 struct nfs_delegation *delegation,
+                                 int issync)
 {
        struct nfs4_delegreturndata *data;
        struct nfs_server *server = NFS_SERVER(inode);
@@ -6791,12 +6794,27 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
                }
        }
 
+       if (delegation &&
+           test_bit(NFS_DELEGATION_DELEGTIME, &delegation->flags)) {
+               if (delegation->type & FMODE_READ) {
+                       data->sattr.atime = inode_get_atime(inode);
+                       data->sattr.atime_set = true;
+               }
+               if (delegation->type & FMODE_WRITE) {
+                       data->sattr.mtime = inode_get_mtime(inode);
+                       data->sattr.mtime_set = true;
+               }
+               data->args.sattr_args = &data->sattr;
+               data->res.sattr_res = true;
+       }
+
        if (!data->inode)
                nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
                                   1);
        else
                nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
                                   0);
+
        task_setup_data.callback_data = data;
        msg.rpc_argp = &data->args;
        msg.rpc_resp = &data->res;
@@ -6814,13 +6832,16 @@ out:
        return status;
 }
 
-int nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred, const nfs4_stateid *stateid, int issync)
+int nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
+                         const nfs4_stateid *stateid,
+                         struct nfs_delegation *delegation, int issync)
 {
        struct nfs_server *server = NFS_SERVER(inode);
        struct nfs4_exception exception = { };
        int err;
        do {
-               err = _nfs4_proc_delegreturn(inode, cred, stateid, issync);
+               err = _nfs4_proc_delegreturn(inode, cred, stateid,
+                                            delegation, issync);
                trace_nfs4_delegreturn(inode, stateid, err);
                switch (err) {
                        case -NFS4ERR_STALE_STATEID: