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: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
Родитель
12f275cdd1
Коммит
c82bac6f4b
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
break;
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче