mirror of
https://github.com/opnsense/src.git
synced 2026-06-04 06:15:33 -04:00
nfscl: Re-initialize session seq#s when server shrinks slot table
When a NFSv4.1/4.2 server reduces the size of the slot table for a session as indicated by a smaller value for sr_target_highest_slot in a Sequence reply, the sequence numbers for the slots no longer in use must be re-initialized. This is needed since the slot table may be grown again by the server later. The RFC did not make the need for the sequence numbers to be re-initialized when a shrink/grow of the slot table size happens, but this has now been confirmed as correct behaviour. The patch adds the code that does this re-initialization. I am not currently aware of a NFSv4.1/4.2 server where the session slots fail if this is not done, but there may be such a case. MFC after: 2 weeks
This commit is contained in:
parent
c48ca725a8
commit
b97a478896
2 changed files with 36 additions and 8 deletions
|
|
@ -123,6 +123,7 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, skip_wcc_data_onerr, CTLFLAG_RW, &nfs_skip_wcc_da
|
|||
SYSCTL_INT(_vfs_nfs, OID_AUTO, dsretries, CTLFLAG_RW, &nfs_dsretries, 0,
|
||||
"Number of retries for a DS RPC before failure");
|
||||
|
||||
static void nfs_resetslots(struct nfsclsession *);
|
||||
static void nfs_down(struct nfsmount *, struct thread *, const char *,
|
||||
int, int);
|
||||
static void nfs_up(struct nfsmount *, struct thread *, const char *,
|
||||
|
|
@ -670,7 +671,7 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
|
|||
struct thread *td, struct ucred *cred, u_int32_t prog, u_int32_t vers,
|
||||
u_char *retsum, int toplevel, u_int64_t *xidp, struct nfsclsession *dssep)
|
||||
{
|
||||
uint32_t retseq, retval, slotseq, *tl;
|
||||
uint32_t retseq, retval, retval0, slotseq, *tl;
|
||||
int i = 0, j = 0, opcnt, set_sigset = 0, slot;
|
||||
int error = 0, usegssname = 0, secflavour = AUTH_SYS;
|
||||
int freeslot, maxslot, reterr, slotpos, timeo;
|
||||
|
|
@ -1039,7 +1040,7 @@ tryagain:
|
|||
sep->nfsess_badslots |= (0x1ULL << nd->nd_slotid);
|
||||
mtx_unlock(&sep->nfsess_mtx);
|
||||
/* And free the slot. */
|
||||
nfsv4_freeslot(sep, nd->nd_slotid, false);
|
||||
nfsv4_freeslot(sep, nd->nd_slotid, true);
|
||||
}
|
||||
if (stat == RPC_INTR)
|
||||
error = EINTR;
|
||||
|
|
@ -1192,15 +1193,22 @@ tryagain:
|
|||
if (retseq != sep->nfsess_slotseq[slot])
|
||||
printf("retseq diff 0x%x\n",
|
||||
retseq);
|
||||
retval = fxdr_unsigned(uint32_t, *++tl);
|
||||
retval0 = fxdr_unsigned(uint32_t,*tl++);
|
||||
retval = fxdr_unsigned(uint32_t, *tl);
|
||||
if ((retval + 1) < sep->nfsess_foreslots
|
||||
)
|
||||
) {
|
||||
sep->nfsess_foreslots = (retval
|
||||
+ 1);
|
||||
else if ((retval + 1) >
|
||||
sep->nfsess_foreslots)
|
||||
sep->nfsess_foreslots = (retval
|
||||
< 64) ? (retval + 1) : 64;
|
||||
nfs_resetslots(sep);
|
||||
} else if ((retval + 1) >
|
||||
sep->nfsess_foreslots) {
|
||||
if (retval0 > retval)
|
||||
printf("Sess:highest > "
|
||||
"target_highest\n");
|
||||
sep->nfsess_foreslots =
|
||||
(retval < NFSV4_SLOTS) ?
|
||||
(retval + 1) : NFSV4_SLOTS;
|
||||
}
|
||||
}
|
||||
mtx_unlock(&sep->nfsess_mtx);
|
||||
|
||||
|
|
@ -1463,6 +1471,24 @@ nfsmout:
|
|||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset slots above nfsess_foreslots that are not busy.
|
||||
*/
|
||||
static void
|
||||
nfs_resetslots(struct nfsclsession *sep)
|
||||
{
|
||||
int i;
|
||||
uint64_t bitval;
|
||||
|
||||
bitval = (1 << sep->nfsess_foreslots);
|
||||
for (i = sep->nfsess_foreslots; i < NFSV4_SLOTS; i++) {
|
||||
if ((sep->nfsess_slots & bitval) == 0 &&
|
||||
(sep->nfsess_badslots & bitval) == 0)
|
||||
sep->nfsess_slotseq[i] = 0;
|
||||
bitval <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark all of an nfs mount's outstanding requests with R_SOFTTERM and
|
||||
* wait for all requests to complete. This is used by forced unmounts
|
||||
|
|
|
|||
|
|
@ -5047,6 +5047,8 @@ nfsv4_freeslot(struct nfsclsession *sep, int slot, bool resetseq)
|
|||
mtx_lock(&sep->nfsess_mtx);
|
||||
if (resetseq)
|
||||
sep->nfsess_slotseq[slot]--;
|
||||
else if (slot > sep->nfsess_foreslots)
|
||||
sep->nfsess_slotseq[slot] = 0;
|
||||
if ((bitval & sep->nfsess_slots) == 0)
|
||||
printf("freeing free slot!!\n");
|
||||
sep->nfsess_slots &= ~bitval;
|
||||
|
|
|
|||
Loading…
Reference in a new issue