Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Jun 2018 22:18:24 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r334741 - stable/10/sys/fs/nfsserver
Message-ID:  <201806062218.w56MIOVQ077172@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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++;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201806062218.w56MIOVQ077172>