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.c73
1 files changed, 71 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index dfc6d946cdfe..24b6e0593184 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1000,6 +1000,32 @@ error:
1000 return status; 1000 return status;
1001} 1001}
1002 1002
1003static int
1004check_slot_seqid(u32 seqid, struct nfsd4_slot *slot)
1005{
1006 dprintk("%s enter. seqid %d slot->sl_seqid %d\n", __func__, seqid,
1007 slot->sl_seqid);
1008
1009 /* The slot is in use, and no response has been sent. */
1010 if (slot->sl_inuse) {
1011 if (seqid == slot->sl_seqid)
1012 return nfserr_jukebox;
1013 else
1014 return nfserr_seq_misordered;
1015 }
1016 /* Normal */
1017 if (likely(seqid == slot->sl_seqid + 1))
1018 return nfs_ok;
1019 /* Replay */
1020 if (seqid == slot->sl_seqid)
1021 return nfserr_replay_cache;
1022 /* Wraparound */
1023 if (seqid == 1 && (slot->sl_seqid + 1) == 0)
1024 return nfs_ok;
1025 /* Misordered replay or misordered new request */
1026 return nfserr_seq_misordered;
1027}
1028
1003__be32 1029__be32
1004nfsd4_create_session(struct svc_rqst *rqstp, 1030nfsd4_create_session(struct svc_rqst *rqstp,
1005 struct nfsd4_compound_state *cstate, 1031 struct nfsd4_compound_state *cstate,
@@ -1017,11 +1043,54 @@ nfsd4_destroy_session(struct svc_rqst *r,
1017} 1043}
1018 1044
1019__be32 1045__be32
1020nfsd4_sequence(struct svc_rqst *r, 1046nfsd4_sequence(struct svc_rqst *rqstp,
1021 struct nfsd4_compound_state *cstate, 1047 struct nfsd4_compound_state *cstate,
1022 struct nfsd4_sequence *seq) 1048 struct nfsd4_sequence *seq)
1023{ 1049{
1024 return -1; /* stub */ 1050 struct nfsd4_session *session;
1051 struct nfsd4_slot *slot;
1052 int status;
1053
1054 spin_lock(&sessionid_lock);
1055 status = nfserr_badsession;
1056 session = find_in_sessionid_hashtbl(&seq->sessionid);
1057 if (!session)
1058 goto out;
1059
1060 status = nfserr_badslot;
1061 if (seq->slotid >= session->se_fnumslots)
1062 goto out;
1063
1064 slot = &session->se_slots[seq->slotid];
1065 dprintk("%s: slotid %d\n", __func__, seq->slotid);
1066
1067 status = check_slot_seqid(seq->seqid, slot);
1068 if (status == nfserr_replay_cache) {
1069 cstate->slot = slot;
1070 cstate->session = session;
1071 goto replay_cache;
1072 }
1073 if (status)
1074 goto out;
1075
1076 /* Success! bump slot seqid */
1077 slot->sl_inuse = true;
1078 slot->sl_seqid = seq->seqid;
1079
1080 cstate->slot = slot;
1081 cstate->session = session;
1082
1083replay_cache:
1084 /* Renew the clientid on success and on replay.
1085 * Hold a session reference until done processing the compound:
1086 * nfsd4_put_session called only if the cstate slot is set.
1087 */
1088 renew_client(session->se_client);
1089 nfsd4_get_session(session);
1090out:
1091 spin_unlock(&sessionid_lock);
1092 dprintk("%s: return %d\n", __func__, ntohl(status));
1093 return status;
1025} 1094}
1026 1095
1027__be32 1096__be32