aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
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)