aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2011-08-30 17:02:48 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-09-01 07:07:59 -0400
commit5ec094c1096ab3bb795651855d53f18daa26afde (patch)
treecb9cbbd50698cf039cf81823d40e073fbcdf53da /fs/nfsd/nfs4state.c
parent9072d5c66b17292e3cd055bc8057b2ce6af2fe34 (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.c12
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);
3503out: 3503out:
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;
3570out: 3571out:
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);
3611out: 3613out:
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,
4071out: 4074out:
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