aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2013-04-01 16:37:12 -0400
committerJ. Bruce Fields <bfields@redhat.com>2013-04-08 09:55:32 -0400
commit9411b1d4c7df26dca6bc6261b5dc87a5b4c81e5c (patch)
tree43fe6d0f9e83740f0b2e7b4691b3fb374c03fd17 /fs/nfsd/nfs4state.c
parent41d22663cb6a4108091c050cba3c470a3e175dd9 (diff)
nfsd4: cleanup handling of nfsv4.0 closed stateid's
Closed stateid's are kept around a little while to handle close replays in the 4.0 case. So we stash them in the last-used stateid in the oo_last_closed_stateid field of the open owner. We can free that in encode_seqid_op_tail once the seqid on the open owner is next incremented. But we don't want to do that on the close itself; so we set NFS4_OO_PURGE_CLOSE flag set on the open owner, skip freeing it the first time through encode_seqid_op_tail, then when we see that flag set next time we free it. This is unnecessarily baroque. Instead, just move the logic that increments the seqid out of the xdr code and into the operation code itself. The justification given for the current placement is that we need to wait till the last minute to be sure we know whether the status is a sequence-id-mutating error or not, but examination of the code shows that can't actually happen. Reported-by: Yanchuan Nian <ycnian@gmail.com> Tested-by: Yanchuan Nian <ycnian@gmail.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c57
1 files changed, 33 insertions, 24 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 795b24d82d18..bcd2339ae8c1 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -720,6 +720,28 @@ dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
720} 720}
721#endif 721#endif
722 722
723/*
724 * Bump the seqid on cstate->replay_owner, and clear replay_owner if it
725 * won't be used for replay.
726 */
727void nfsd4_bump_seqid(struct nfsd4_compound_state *cstate, __be32 nfserr)
728{
729 struct nfs4_stateowner *so = cstate->replay_owner;
730
731 if (nfserr == nfserr_replay_me)
732 return;
733
734 if (!seqid_mutating_err(ntohl(nfserr))) {
735 cstate->replay_owner = NULL;
736 return;
737 }
738 if (!so)
739 return;
740 if (so->so_is_open_owner)
741 release_last_closed_stateid(openowner(so));
742 so->so_seqid++;
743 return;
744}
723 745
724static void 746static void
725gen_sessionid(struct nfsd4_session *ses) 747gen_sessionid(struct nfsd4_session *ses)
@@ -3702,6 +3724,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3702 nfsd4_client_record_create(oo->oo_owner.so_client); 3724 nfsd4_client_record_create(oo->oo_owner.so_client);
3703 status = nfs_ok; 3725 status = nfs_ok;
3704out: 3726out:
3727 nfsd4_bump_seqid(cstate, status);
3705 if (!cstate->replay_owner) 3728 if (!cstate->replay_owner)
3706 nfs4_unlock_state(); 3729 nfs4_unlock_state();
3707 return status; 3730 return status;
@@ -3785,31 +3808,12 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
3785 memcpy(&od->od_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 3808 memcpy(&od->od_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
3786 status = nfs_ok; 3809 status = nfs_ok;
3787out: 3810out:
3811 nfsd4_bump_seqid(cstate, status);
3788 if (!cstate->replay_owner) 3812 if (!cstate->replay_owner)
3789 nfs4_unlock_state(); 3813 nfs4_unlock_state();
3790 return status; 3814 return status;
3791} 3815}
3792 3816
3793void nfsd4_purge_closed_stateid(struct nfs4_stateowner *so)
3794{
3795 struct nfs4_openowner *oo;
3796 struct nfs4_ol_stateid *s;
3797
3798 if (!so->so_is_open_owner)
3799 return;
3800 oo = openowner(so);
3801 s = oo->oo_last_closed_stid;
3802 if (!s)
3803 return;
3804 if (!(oo->oo_flags & NFS4_OO_PURGE_CLOSE)) {
3805 /* Release the last_closed_stid on the next seqid bump: */
3806 oo->oo_flags |= NFS4_OO_PURGE_CLOSE;
3807 return;
3808 }
3809 oo->oo_flags &= ~NFS4_OO_PURGE_CLOSE;
3810 release_last_closed_stateid(oo);
3811}
3812
3813static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s) 3817static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s)
3814{ 3818{
3815 unhash_open_stateid(s); 3819 unhash_open_stateid(s);
@@ -3838,17 +3842,20 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3838 &close->cl_stateid, 3842 &close->cl_stateid,
3839 NFS4_OPEN_STID|NFS4_CLOSED_STID, 3843 NFS4_OPEN_STID|NFS4_CLOSED_STID,
3840 &stp, nn); 3844 &stp, nn);
3845 nfsd4_bump_seqid(cstate, status);
3841 if (status) 3846 if (status)
3842 goto out; 3847 goto out;
3843 oo = openowner(stp->st_stateowner); 3848 oo = openowner(stp->st_stateowner);
3844 status = nfs_ok;
3845 update_stateid(&stp->st_stid.sc_stateid); 3849 update_stateid(&stp->st_stid.sc_stateid);
3846 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 3850 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
3847 3851
3848 nfsd4_close_open_stateid(stp); 3852 nfsd4_close_open_stateid(stp);
3849 release_last_closed_stateid(oo); 3853
3850 oo->oo_flags &= ~NFS4_OO_PURGE_CLOSE; 3854 if (cstate->minorversion) {
3851 oo->oo_last_closed_stid = stp; 3855 unhash_stid(&stp->st_stid);
3856 free_generic_stateid(stp);
3857 } else
3858 oo->oo_last_closed_stid = stp;
3852 3859
3853 if (list_empty(&oo->oo_owner.so_stateids)) { 3860 if (list_empty(&oo->oo_owner.so_stateids)) {
3854 if (cstate->minorversion) { 3861 if (cstate->minorversion) {
@@ -4270,6 +4277,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4270out: 4277out:
4271 if (status && new_state) 4278 if (status && new_state)
4272 release_lockowner(lock_sop); 4279 release_lockowner(lock_sop);
4280 nfsd4_bump_seqid(cstate, status);
4273 if (!cstate->replay_owner) 4281 if (!cstate->replay_owner)
4274 nfs4_unlock_state(); 4282 nfs4_unlock_state();
4275 if (file_lock) 4283 if (file_lock)
@@ -4439,6 +4447,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4439 memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 4447 memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
4440 4448
4441out: 4449out:
4450 nfsd4_bump_seqid(cstate, status);
4442 if (!cstate->replay_owner) 4451 if (!cstate->replay_owner)
4443 nfs4_unlock_state(); 4452 nfs4_unlock_state();
4444 if (file_lock) 4453 if (file_lock)