Fix a slow leak of session structures in the NFSv4.1 server.
For a fairly rare case of a client doing an ExchangeID after a hard reboot, the old confirmed clientid still exists, but some clients use a new co_verifier. For this case, the server was not freeing up the sessions on the old confirmed clientid. This patch fixes this case. It also adds two LIST_INIT() macros, which are actually no-ops, since the structure is malloc()d with M_ZERO so the pointer is already set to NULL. It should have minimal impact, since the only way I could exercise this code path was by doing a hard power cycle (pulling the plus) on a machine running Linux with a NFSv4.1 mount on the server. Originally spotted during testing of the ESXi 6.5 client. Tested by: andreas.nagy@frequentis.com MFC after: 2 months
This commit is contained in:
parent
1e4675982e
commit
de34a49ecf
@ -180,9 +180,10 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
|
||||
nfsquad_t *clientidp, nfsquad_t *confirmp, NFSPROC_T *p)
|
||||
{
|
||||
struct nfsclient *clp = NULL, *new_clp = *new_clpp;
|
||||
int i, error = 0;
|
||||
int i, error = 0, ret;
|
||||
struct nfsstate *stp, *tstp;
|
||||
struct sockaddr_in *sad, *rad;
|
||||
struct nfsdsession *sep, *nsep;
|
||||
int zapit = 0, gotit, hasstate = 0, igotlock;
|
||||
static u_int64_t confirm_index = 0;
|
||||
|
||||
@ -352,6 +353,15 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
|
||||
* can be thrown away once the SETCLIENTID_CONFIRM occurs.
|
||||
*/
|
||||
LIST_REMOVE(clp, lc_hash);
|
||||
|
||||
/* Get rid of all sessions on this clientid. */
|
||||
LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep) {
|
||||
ret = nfsrv_freesession(sep, NULL);
|
||||
if (ret != 0)
|
||||
printf("nfsrv_setclient: verifier changed free"
|
||||
" session failed=%d\n", ret);
|
||||
}
|
||||
|
||||
new_clp->lc_flags |= LCL_NEEDSCONFIRM;
|
||||
if ((nd->nd_flag & ND_NFSV41) != 0)
|
||||
new_clp->lc_confirm.lval[0] = confirmp->lval[0] =
|
||||
@ -387,6 +397,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
|
||||
LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash)
|
||||
tstp->ls_clp = new_clp;
|
||||
}
|
||||
LIST_INIT(&new_clp->lc_session);
|
||||
LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
|
||||
lc_hash);
|
||||
nfsstatsv1.srvclients++;
|
||||
@ -451,6 +462,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
|
||||
LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash)
|
||||
tstp->ls_clp = new_clp;
|
||||
}
|
||||
LIST_INIT(&new_clp->lc_session);
|
||||
LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
|
||||
lc_hash);
|
||||
nfsstatsv1.srvclients++;
|
||||
|
Loading…
Reference in New Issue
Block a user