Commit 5ec094c1 authored by J. Bruce Fields's avatar J. Bruce Fields

nfsd4: extend state lock over seqid replay logic

There are currently a couple races in the seqid replay code: a
retransmission could come while we're still encoding the original reply,
or a new seqid-mutating call could come as we're encoding a replay.

So, extend the state lock over the encoding (both encoding of a replayed
reply and caching of the original encoded reply).

I really hate doing this, and previously added the stateowner
reference-counting code to avoid it (which was insufficient)--but I
don't see a less complicated alternative at the moment.
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 9072d5c6
...@@ -408,8 +408,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -408,8 +408,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (open->op_stateowner) { if (open->op_stateowner) {
nfs4_get_stateowner(open->op_stateowner); nfs4_get_stateowner(open->op_stateowner);
cstate->replay_owner = open->op_stateowner; cstate->replay_owner = open->op_stateowner;
} } else
nfs4_unlock_state(); nfs4_unlock_state();
return status; return status;
} }
...@@ -1227,6 +1227,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, ...@@ -1227,6 +1227,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
be32_to_cpu(status)); be32_to_cpu(status));
if (cstate->replay_owner) { if (cstate->replay_owner) {
nfs4_unlock_state();
nfs4_put_stateowner(cstate->replay_owner); nfs4_put_stateowner(cstate->replay_owner);
cstate->replay_owner = NULL; cstate->replay_owner = NULL;
} }
......
...@@ -3501,7 +3501,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -3501,7 +3501,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
nfsd4_create_clid_dir(sop->so_client); nfsd4_create_clid_dir(sop->so_client);
out: out:
nfs4_unlock_state(); if (!cstate->replay_owner)
nfs4_unlock_state();
return status; return status;
} }
...@@ -3568,7 +3569,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, ...@@ -3568,7 +3569,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t)); memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));
status = nfs_ok; status = nfs_ok;
out: out:
nfs4_unlock_state(); if (!cstate->replay_owner)
nfs4_unlock_state();
return status; return status;
} }
...@@ -3609,7 +3611,8 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -3609,7 +3611,8 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (list_empty(&so->so_stateids)) if (list_empty(&so->so_stateids))
move_to_close_lru(so); move_to_close_lru(so);
out: out:
nfs4_unlock_state(); if (!cstate->replay_owner)
nfs4_unlock_state();
return status; return status;
} }
...@@ -4071,7 +4074,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -4071,7 +4074,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
out: out:
if (status && lock->lk_is_new && lock_sop) if (status && lock->lk_is_new && lock_sop)
release_lockowner(lock_sop); release_lockowner(lock_sop);
nfs4_unlock_state(); if (!cstate->replay_owner)
nfs4_unlock_state();
return status; return status;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment