nfscl: Add support for CB_RECALL_SLOT

The callback CB_RECALL_SLOT is required for NFSv4.1/4.2.
Fortunately, there does not appear to be any extant
NFSv4.1/4.2 servers that use it.  Since commit b97a478896
fixed handling of session slot shrinking, this patch
adds support for CB_RECALL_SLOT, which shrinks the
number of session slots as well.

MFC after:	2 weeks
This commit is contained in:
Rick Macklem 2025-02-14 12:56:52 -08:00
parent 8e8a77c56e
commit 4517fbfd42
3 changed files with 21 additions and 2 deletions

View file

@ -123,7 +123,6 @@ 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 *,
@ -1474,12 +1473,13 @@ nfsmout:
/*
* Reset slots above nfsess_foreslots that are not busy.
*/
static void
void
nfs_resetslots(struct nfsclsession *sep)
{
int i;
uint64_t bitval;
mtx_assert(&sep->nfsess_mtx, MA_OWNED);
bitval = (1 << sep->nfsess_foreslots);
for (i = sep->nfsess_foreslots; i < NFSV4_SLOTS; i++) {
if ((sep->nfsess_slots & bitval) == 0 &&

View file

@ -780,6 +780,7 @@ int newnfs_request(struct nfsrv_descript *, struct nfsmount *,
struct nfsclient *, struct nfssockreq *, vnode_t, NFSPROC_T *,
struct ucred *, u_int32_t, u_int32_t, u_char *, int, u_int64_t *,
struct nfsclsession *);
void nfs_resetslots(struct nfsclsession *);
int newnfs_connect(struct nfsmount *, struct nfssockreq *,
struct ucred *, NFSPROC_T *, int, bool, struct __rpc_client **);
void newnfs_disconnect(struct nfsmount *, struct nfssockreq *);

View file

@ -3934,6 +3934,24 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)
*tl = txdr_unsigned(NFSV4_CBSLOTS - 1);
}
break;
case NFSV4OP_CBRECALLSLOT:
NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
highslot = fxdr_unsigned(uint32_t, *tl);
NFSLOCKCLSTATE();
clp = nfscl_getclntsess(sessionid);
if (clp == NULL)
error = NFSERR_SERVERFAULT;
if (error == 0) {
tsep = nfsmnt_mdssession(clp->nfsc_nmp);
mtx_lock(&tsep->nfsess_mtx);
if ((highslot + 1) < tsep->nfsess_foreslots) {
tsep->nfsess_foreslots = (highslot + 1);
nfs_resetslots(tsep);
}
mtx_unlock(&tsep->nfsess_mtx);
}
NFSUNLOCKCLSTATE();
break;
default:
if (i == 0 && minorvers != NFSV4_MINORVERSION)
error = NFSERR_OPNOTINSESS;