Author: rmacklem Date: Wed Jun 6 22:18:24 2018 New Revision: 334741 URL: https://svnweb.freebsd.org/changeset/base/334741
Log: MFC: r333580 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. PR: 228497 Modified: stable/10/sys/fs/nfsserver/nfs_nfsdstate.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/fs/nfsserver/nfs_nfsdstate.c ============================================================================== --- stable/10/sys/fs/nfsserver/nfs_nfsdstate.c Wed Jun 6 22:02:44 2018 (r334740) +++ stable/10/sys/fs/nfsserver/nfs_nfsdstate.c Wed Jun 6 22:18:24 2018 (r334741) @@ -183,9 +183,10 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsc 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; @@ -355,6 +356,15 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsc * 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] = @@ -390,6 +400,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsc 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); newnfsstats.srvclients++; @@ -454,6 +465,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsc 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); newnfsstats.srvclients++; _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"