diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-08-30 17:02:48 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-09-01 07:07:59 -0400 |
commit | 5ec094c1096ab3bb795651855d53f18daa26afde (patch) | |
tree | cb9cbbd50698cf039cf81823d40e073fbcdf53da /fs/nfsd/nfs4proc.c | |
parent | 9072d5c66b17292e3cd055bc8057b2ce6af2fe34 (diff) |
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: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 50bae7471147..50063a85f505 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -408,8 +408,8 @@ out: | |||
408 | if (open->op_stateowner) { | 408 | if (open->op_stateowner) { |
409 | nfs4_get_stateowner(open->op_stateowner); | 409 | nfs4_get_stateowner(open->op_stateowner); |
410 | cstate->replay_owner = open->op_stateowner; | 410 | cstate->replay_owner = open->op_stateowner; |
411 | } | 411 | } else |
412 | nfs4_unlock_state(); | 412 | nfs4_unlock_state(); |
413 | return status; | 413 | return status; |
414 | } | 414 | } |
415 | 415 | ||
@@ -1227,6 +1227,7 @@ encode_op: | |||
1227 | be32_to_cpu(status)); | 1227 | be32_to_cpu(status)); |
1228 | 1228 | ||
1229 | if (cstate->replay_owner) { | 1229 | if (cstate->replay_owner) { |
1230 | nfs4_unlock_state(); | ||
1230 | nfs4_put_stateowner(cstate->replay_owner); | 1231 | nfs4_put_stateowner(cstate->replay_owner); |
1231 | cstate->replay_owner = NULL; | 1232 | cstate->replay_owner = NULL; |
1232 | } | 1233 | } |