aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenny Halevy <bhalevy@panasas.com>2009-04-03 01:28:08 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-04-03 20:41:16 -0400
commitb85d4c01b76f6969a085d07a767fa45225cb14be (patch)
tree5441d0f6bcec52fab3b81ad4887239ff784c5ad9
parenta1bcecd29cdf1670df6908a620add4211c0abb7a (diff)
nfsd41: sequence operation
Implement the sequence operation conforming to http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26 Check for stale clientid (as derived from the sessionid). Enforce slotid range and exactly-once semantics using the slotid and seqid. If everything went well renew the client lease and mark the slot INPROGRESS. Add a struct nfsd4_slot pointer to struct nfsd4_compound_state. To be used for sessions DRC replay. [nfsd41: rename sequence catchthis to cachethis] Signed-off-by: Andy Adamson<andros@netapp.com> [pulled some code to set cstate->slot from "nfsd DRC logic"] [use sessionid_lock spin lock] [nfsd41: use bool inuse for slot state] Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfsd: add a struct nfsd4_slot pointer to struct nfsd4_compound_state] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfsd41: add nfsd4_session pointer to nfsd4_compound_state] [nfsd41: set cstate session] [nfsd41: use cstate session in nfsd4_sequence] Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> [simplify nfsd4_encode_sequence error handling] Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--fs/nfsd/nfs4state.c73
-rw-r--r--fs/nfsd/nfs4xdr.c33
-rw-r--r--include/linux/nfsd/xdr4.h13
3 files changed, 113 insertions, 6 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
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index bebf6d249069..8556575480ce 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1113,7 +1113,16 @@ static __be32
1113nfsd4_decode_sequence(struct nfsd4_compoundargs *argp, 1113nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1114 struct nfsd4_sequence *seq) 1114 struct nfsd4_sequence *seq)
1115{ 1115{
1116 return nfserr_opnotsupp; /* stub */ 1116 DECODE_HEAD;
1117
1118 READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
1119 COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1120 READ32(seq->seqid);
1121 READ32(seq->slotid);
1122 READ32(seq->maxslots);
1123 READ32(seq->cachethis);
1124
1125 DECODE_TAIL;
1117} 1126}
1118 1127
1119static __be32 1128static __be32
@@ -2828,8 +2837,26 @@ static __be32
2828nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr, 2837nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
2829 struct nfsd4_sequence *seq) 2838 struct nfsd4_sequence *seq)
2830{ 2839{
2831 /* stub */ 2840 ENCODE_HEAD;
2832 return nfserr; 2841
2842 if (nfserr)
2843 return nfserr;
2844
2845 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 20);
2846 WRITEMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
2847 WRITE32(seq->seqid);
2848 WRITE32(seq->slotid);
2849 WRITE32(seq->maxslots);
2850 /*
2851 * FIXME: for now:
2852 * target_maxslots = maxslots
2853 * status_flags = 0
2854 */
2855 WRITE32(seq->maxslots);
2856 WRITE32(0);
2857
2858 ADJUST_ARGS();
2859 return 0;
2833} 2860}
2834 2861
2835static __be32 2862static __be32
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 33ee71e988b4..6e28a041008d 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -48,6 +48,9 @@ struct nfsd4_compound_state {
48 struct svc_fh current_fh; 48 struct svc_fh current_fh;
49 struct svc_fh save_fh; 49 struct svc_fh save_fh;
50 struct nfs4_stateowner *replay_owner; 50 struct nfs4_stateowner *replay_owner;
51 /* For sessions DRC */
52 struct nfsd4_session *session;
53 struct nfsd4_slot *slot;
51}; 54};
52 55
53struct nfsd4_change_info { 56struct nfsd4_change_info {
@@ -358,7 +361,15 @@ struct nfsd4_create_session {
358}; 361};
359 362
360struct nfsd4_sequence { 363struct nfsd4_sequence {
361 int foo; /* stub */ 364 struct nfs4_sessionid sessionid; /* request/response */
365 u32 seqid; /* request/response */
366 u32 slotid; /* request/response */
367 u32 maxslots; /* request/response */
368 u32 cachethis; /* request */
369#if 0
370 u32 target_maxslots; /* response */
371 u32 status_flags; /* response */
372#endif /* not yet */
362}; 373};
363 374
364struct nfsd4_destroy_session { 375struct nfsd4_destroy_session {