NFSv4: Delegreturn must set m/atime when they are delegated

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>
This commit is contained in:
Trond Myklebust 2024-06-16 21:21:29 -04:00 committed by Anna Schumaker
parent e3e9d44de1
commit b81aca0961
3 changed files with 32 additions and 8 deletions

View 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; const struct cred *cred;
int res = 0; int res = 0;
@ -275,9 +277,8 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
spin_lock(&delegation->lock); spin_lock(&delegation->lock);
cred = get_cred(delegation->cred); cred = get_cred(delegation->cred);
spin_unlock(&delegation->lock); spin_unlock(&delegation->lock);
res = nfs4_proc_delegreturn(inode, cred, res = nfs4_proc_delegreturn(inode, cred, &delegation->stateid,
&delegation->stateid, delegation, issync);
issync);
put_cred(cred); put_cred(cred);
} }
return res; return res;

View File

@ -70,7 +70,9 @@ void nfs_test_expired_all_delegations(struct nfs_client *clp);
void nfs_reap_expired_delegations(struct nfs_client *clp); void nfs_reap_expired_delegations(struct nfs_client *clp);
/* NFSv4 delegation-related procedures */ /* 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_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); 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); bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred);

View File

@ -6739,7 +6739,10 @@ static const struct rpc_call_ops nfs4_delegreturn_ops = {
.rpc_release = nfs4_delegreturn_release, .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 nfs4_delegreturndata *data;
struct nfs_server *server = NFS_SERVER(inode); 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) if (!data->inode)
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
1); 1);
else else
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
0); 0);
task_setup_data.callback_data = data; task_setup_data.callback_data = data;
msg.rpc_argp = &data->args; msg.rpc_argp = &data->args;
msg.rpc_resp = &data->res; msg.rpc_resp = &data->res;
@ -6814,13 +6832,16 @@ out:
return status; 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 nfs_server *server = NFS_SERVER(inode);
struct nfs4_exception exception = { }; struct nfs4_exception exception = { };
int err; int err;
do { do {
err = _nfs4_proc_delegreturn(inode, cred, stateid, issync); err = _nfs4_proc_delegreturn(inode, cred, stateid,
delegation, issync);
trace_nfs4_delegreturn(inode, stateid, err); trace_nfs4_delegreturn(inode, stateid, err);
switch (err) { switch (err) {
case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_STATEID: