nfsd4: fix sessions slotid wraparound logic
Subsystems (2)
PATCH 1/3 nfsd4: fix sessions slotid wraparound logic
From: "J. Bruce Fields" <[email protected]>
Quoted 1 line
From RFC 5661 2.10.6.1: "If the previous sequence ID was
0xFFFFFFFF,
then the next request for the slot MUST have the sequence ID set to zero."
While we're there, delete some redundant comments.
--- fs/nfsd/nfs4state.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
fs/nfsd/nfs4state.c +1 -6
@@ -1575,16 +1575,11 @@ check_slot_seqid(u32 seqid, u32 slot_seqid, int slot_inuse)else return nfserr_seq_misordered; } -/* Normal */ +/* Note unsigned 32-bit arithmetic handles wraparound: */ if (likely (seqid == slot_seqid +1 ))return nfs_ok; -/* Replay */ if (seqid == slot_seqid)return nfserr_replay_cache; -/* Wraparound */ -if (seqid ==1 && (slot_seqid +1 ) ==0 ) -return nfs_ok; -/* Misordered replay or misordered new request */ return nfserr_seq_misordered; }
Signature · 1 line
1.7.5.4
PATCH 2/3 nfsd4: rearrange struct nfsd4_slot
From: "J. Bruce Fields" <[email protected]>
Combine two booleans into a single flag field, move the smaller fields to the end.
(In practice this doesn't make the struct any smaller. But we'll be adding another flag here soon.)
Remove some debugging code that doesn't look useful, while we're in the neighborhood.
--- fs/nfsd/nfs4state.c | 13 ++++++------- fs/nfsd/nfs4xdr.c | 5 ++--- fs/nfsd/state.h | 7 ++++--- fs/nfsd/xdr4.h | 3 ++- 4 files changed, 14 insertions(+), 14 deletions(-)
fs/nfsd/nfs4state.c +6 -7
@@ -1374,15 +1374,12 @@ nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args,struct nfsd4_op *op;struct nfsd4_slot *slot = resp->cstate.slot; -dprintk ("--> %s resp->opcnt %d cachethis %u \n" , __func__, - resp->opcnt, resp->cstate.slot->sl_cachethis); -/* Encode the replayed sequence operation */ op = &args->ops[resp->opcnt -1 ];nfsd4_encode_operation (resp, op);/* Return nfserr_retry_uncached_rep in next operation. */ -if (args->opcnt >1 && slot->sl_cachethis ==0 ) { +if (args->opcnt >1 && !(slot->sl_flags &NFSD4_SLOT_CACHETHIS )) { op = &args->ops[resp->opcnt++]; op->status = nfserr_retry_uncached_rep;nfsd4_encode_operation (resp, op);
@@ -1916,7 +1913,8 @@ nfsd4_sequence(struct svc_rqst *rqstp,* sr_highest_slotid and the sr_target_slot id to maxslots */ seq->maxslots = session->se_fchannel.maxreqs; - status =check_slot_seqid (seq->seqid, slot->sl_seqid, slot->sl_inuse); + status =check_slot_seqid (seq->seqid, slot->sl_seqid, + slot->sl_flags &NFSD4_SLOT_INUSE );if (status == nfserr_replay_cache) { cstate->slot = slot; cstate->session = session;
@@ -1933,9 +1931,10 @@ nfsd4_sequence(struct svc_rqst *rqstp, conn =NULL ;/* Success! bump slot seqid */ - slot->sl_inuse = true; slot->sl_seqid = seq->seqid; - slot->sl_cachethis = seq->cachethis; + slot->sl_flags =NFSD4_SLOT_INUSE ; +if (seq->cachethis) + slot->sl_flags |=NFSD4_SLOT_CACHETHIS ; cstate->slot = slot; cstate->session = session;
fs/nfsd/nfs4xdr.c +2 -3
@@ -3532,7 +3532,7 @@ int nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad)if (length > session->se_fchannel.maxresp_sz)return nfserr_rep_too_big; -if (slot->sl_cachethis ==1 && +if ((slot->sl_flags &NFSD4_SLOT_CACHETHIS ) && length > session->se_fchannel.maxresp_cached)return nfserr_rep_too_big_to_cache;
@@ -3656,8 +3656,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoif (nfsd4_has_session (cs)) {if (cs->status != nfserr_replay_cache) {nfsd4_store_cache_entry (resp); -dprintk ("%s: SET SLOT STATE TO AVAILABLE\n" , __func__); - cs->slot->sl_inuse = false; + cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE ; }/* Renew the clientid on success and on replay */ release_session_client (cs->session);
fs/nfsd/state.h +4 -3
@@ -128,12 +128,13 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s) (NFSD_CACHE_SIZE_SLOTS_PER_SESSION * NFSD_SLOT_CACHE_SIZE)struct nfsd4_slot { -bool sl_inuse; -bool sl_cachethis; -u16 sl_opcnt;u32 sl_seqid;__be32 sl_status;u32 sl_datalen; +u16 sl_opcnt; +#define NFSD4_SLOT_INUSE (1 << 0) +#define NFSD4_SLOT_CACHETHIS (1 << 1) +u8 sl_flags;char sl_data[]; };
fs/nfsd/xdr4.h +2 -1
@@ -503,7 +503,8 @@ static inline bool nfsd4_is_solo_sequence(struct nfsd4_compoundres *resp)static inline bool nfsd4_not_cached (struct nfsd4_compoundres *resp) { -return !resp->cstate.slot->sl_cachethis ||nfsd4_is_solo_sequence (resp); +return !(resp->cstate.slot->sl_flags &NFSD4_SLOT_CACHETHIS ) + ||nfsd4_is_solo_sequence (resp); }#define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs)
Signature · 1 line
1.7.5.4
PATCH 3/3 nfsd4: check for uninitialized slot
In reply to J. Bruce FieldsFrom: "J. Bruce Fields" <[email protected]>
This fixes an oops when a buggy client tries to use an initial seqid of 0 on a new slot, which we may misinterpret as a replay.
--- fs/nfsd/nfs4state.c | 8 +++++++- fs/nfsd/state.h | 1 + 2 files changed, 8 insertions(+), 1 deletions(-)
fs/nfsd/nfs4state.c +7 -1
@@ -1347,6 +1347,7 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) slot->sl_opcnt = resp->opcnt; slot->sl_status = resp->cstate.status; + slot->sl_flags |=NFSD4_SLOT_INITIALIZED ;if (nfsd4_not_cached (resp)) { slot->sl_datalen =0 ;return ;
@@ -1916,6 +1917,9 @@ nfsd4_sequence(struct svc_rqst *rqstp, status =check_slot_seqid (seq->seqid, slot->sl_seqid, slot->sl_flags &NFSD4_SLOT_INUSE );if (status == nfserr_replay_cache) { + status = nfserr_seq_misordered; +if (!(slot->sl_flags &NFSD4_SLOT_INITIALIZED )) + goto out; cstate->slot = slot; cstate->session = session;/* Return the cached reply status and set cstate->status
@@ -1932,9 +1936,11 @@ nfsd4_sequence(struct svc_rqst *rqstp,/* Success! bump slot seqid */ slot->sl_seqid = seq->seqid; - slot->sl_flags =NFSD4_SLOT_INUSE ; + slot->sl_flags |=NFSD4_SLOT_INUSE ;if (seq->cachethis) slot->sl_flags |=NFSD4_SLOT_CACHETHIS ; +else + slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS ; cstate->slot = slot; cstate->session = session;
fs/nfsd/state.h +1 -0
@@ -134,6 +134,7 @@ struct nfsd4_slot {u16 sl_opcnt;#define NFSD4_SLOT_INUSE (1 << 0)#define NFSD4_SLOT_CACHETHIS (1 << 1) +#define NFSD4_SLOT_INITIALIZED (1 << 2)u8 sl_flags;char sl_data[]; };
Signature · 1 line
1.7.5.4