Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

NFSv4: Don't try to CLOSE if the stateid 'other' field has changed



If the stateid is no longer recognised on the server, either due to a
restart, or due to a competing CLOSE call, then we do not have to
retry. Any open contexts that triggered a reopen of the file, will
also act as triggers for any CLOSE for the updated stateids.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 12f275cd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -462,6 +462,8 @@ extern int nfs4_select_rw_stateid(struct nfs4_state *, fmode_t,
		struct rpc_cred **);
extern bool nfs4_refresh_open_stateid(nfs4_stateid *dst,
		struct nfs4_state *state);
extern bool nfs4_copy_open_stateid(nfs4_stateid *dst,
		struct nfs4_state *state);

extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask);
extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
+4 −10
Original line number Diff line number Diff line
@@ -3215,14 +3215,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
					task->tk_msg.rpc_cred);
			/* Fallthrough */
		case -NFS4ERR_BAD_STATEID:
			if (!nfs4_stateid_match(&calldata->arg.stateid,
						&state->open_stateid)) {
				rpc_restart_call_prepare(task);
				goto out_release;
			}
			if (calldata->arg.fmode == 0)
			break;
			/* Fallthrough */
		default:
			if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) {
				rpc_restart_call_prepare(task);
@@ -3254,7 +3247,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
	is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
	is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
	is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
	nfs4_stateid_copy(&calldata->arg.stateid, &state->open_stateid);
	/* Calculate the change in open mode */
	calldata->arg.fmode = 0;
	if (state->n_rdwr == 0) {
@@ -3272,7 +3264,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
		calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;

	if (!nfs4_valid_open_stateid(state) ||
	    test_bit(NFS_OPEN_STATE, &state->flags) == 0)
	    !nfs4_refresh_open_stateid(&calldata->arg.stateid, state))
		call_close = 0;
	spin_unlock(&state->owner->so_lock);

@@ -3366,6 +3358,8 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait)
	calldata->inode = state->inode;
	calldata->state = state;
	calldata->arg.fh = NFS_FH(state->inode);
	if (!nfs4_copy_open_stateid(&calldata->arg.stateid, state))
		goto out_free_calldata;
	/* Serialization for the sequence id */
	alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid;
	calldata->arg.seqid = alloc_seqid(&state->owner->so_seqid, gfp_mask);
+7 −2
Original line number Diff line number Diff line
@@ -1002,18 +1002,23 @@ bool nfs4_refresh_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
	return ret;
}

static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
bool nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
{
	bool ret;
	const nfs4_stateid *src;
	int seq;

	do {
		ret = false;
		src = &zero_stateid;
		seq = read_seqbegin(&state->seqlock);
		if (test_bit(NFS_OPEN_STATE, &state->flags))
		if (test_bit(NFS_OPEN_STATE, &state->flags)) {
			src = &state->open_stateid;
			ret = true;
		}
		nfs4_stateid_copy(dst, src);
	} while (read_seqretry(&state->seqlock, seq));
	return ret;
}

/*