svn commit: r334739 - stable/11/sys/fs/nfsserver
Rick Macklem
rmacklem at FreeBSD.org
Wed Jun 6 22:02:21 UTC 2018
Author: rmacklem
Date: Wed Jun 6 22:02:20 2018
New Revision: 334739
URL: https://svnweb.freebsd.org/changeset/base/334739
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/11/sys/fs/nfsserver/nfs_nfsdstate.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- stable/11/sys/fs/nfsserver/nfs_nfsdstate.c Wed Jun 6 21:32:49 2018 (r334738)
+++ stable/11/sys/fs/nfsserver/nfs_nfsdstate.c Wed Jun 6 22:02:20 2018 (r334739)
@@ -178,9 +178,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;
@@ -350,6 +351,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] =
@@ -385,6 +395,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);
nfsstatsv1.srvclients++;
@@ -449,6 +460,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);
nfsstatsv1.srvclients++;
More information about the svn-src-stable
mailing list