Commit b81aca09 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker
Browse files

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: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: default avatarLance Shelton <lance.shelton@hammerspace.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent e3e9d44d
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -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;
+3 −1
Original line number Diff line number Diff line
@@ -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);
+24 −3
Original line number Diff line number Diff line
@@ -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 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
	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: