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/nfs4state.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/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index bc1a9dbc289c..6cf729a096c3 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -3501,7 +3501,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3501 | 3501 | ||
3502 | nfsd4_create_clid_dir(sop->so_client); | 3502 | nfsd4_create_clid_dir(sop->so_client); |
3503 | out: | 3503 | out: |
3504 | nfs4_unlock_state(); | 3504 | if (!cstate->replay_owner) |
3505 | nfs4_unlock_state(); | ||
3505 | return status; | 3506 | return status; |
3506 | } | 3507 | } |
3507 | 3508 | ||
@@ -3568,7 +3569,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, | |||
3568 | memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t)); | 3569 | memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t)); |
3569 | status = nfs_ok; | 3570 | status = nfs_ok; |
3570 | out: | 3571 | out: |
3571 | nfs4_unlock_state(); | 3572 | if (!cstate->replay_owner) |
3573 | nfs4_unlock_state(); | ||
3572 | return status; | 3574 | return status; |
3573 | } | 3575 | } |
3574 | 3576 | ||
@@ -3609,7 +3611,8 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3609 | if (list_empty(&so->so_stateids)) | 3611 | if (list_empty(&so->so_stateids)) |
3610 | move_to_close_lru(so); | 3612 | move_to_close_lru(so); |
3611 | out: | 3613 | out: |
3612 | nfs4_unlock_state(); | 3614 | if (!cstate->replay_owner) |
3615 | nfs4_unlock_state(); | ||
3613 | return status; | 3616 | return status; |
3614 | } | 3617 | } |
3615 | 3618 | ||
@@ -4071,7 +4074,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
4071 | out: | 4074 | out: |
4072 | if (status && lock->lk_is_new && lock_sop) | 4075 | if (status && lock->lk_is_new && lock_sop) |
4073 | release_lockowner(lock_sop); | 4076 | release_lockowner(lock_sop); |
4074 | nfs4_unlock_state(); | 4077 | if (!cstate->replay_owner) |
4078 | nfs4_unlock_state(); | ||
4075 | return status; | 4079 | return status; |
4076 | } | 4080 | } |
4077 | 4081 | ||