Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 May 2015 04:14:10 +0000 (UTC)
From:      Edward Tomasz Napierala <trasz@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: r283349 - stable/10/sys/cam
Message-ID:  <201505240414.t4O4EATu013539@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trasz
Date: Sun May 24 04:14:09 2015
New Revision: 283349
URL: https://svnweb.freebsd.org/changeset/base/283349

Log:
  MFC r279554:
  
  Make periphdriver_register() take XPT lock when modifying the periph_drivers
  array.
  
  This fixes a panic that sometimes occured when kldloading ctl.ko.
  
  PR:		200384
  Sponsored by:	The FreeBSD Foundation

Modified:
  stable/10/sys/cam/cam_periph.c
  stable/10/sys/cam/cam_xpt.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cam/cam_periph.c
==============================================================================
--- stable/10/sys/cam/cam_periph.c	Sun May 24 02:46:08 2015	(r283348)
+++ stable/10/sys/cam/cam_periph.c	Sun May 24 04:14:09 2015	(r283349)
@@ -108,9 +108,19 @@ periphdriver_register(void *data)
 	struct periph_driver **newdrivers, **old;
 	int ndrivers;
 
+again:
 	ndrivers = nperiph_drivers + 2;
 	newdrivers = malloc(sizeof(*newdrivers) * ndrivers, M_CAMPERIPH,
 			    M_WAITOK);
+	xpt_lock_buses();
+	if (ndrivers != nperiph_drivers + 2) {
+		/*
+		 * Lost race against itself; go around.
+		 */
+		xpt_unlock_buses();
+		free(newdrivers, M_CAMPERIPH);
+		goto again;
+	}
 	if (periph_drivers)
 		bcopy(periph_drivers, newdrivers,
 		      sizeof(*newdrivers) * nperiph_drivers);
@@ -118,9 +128,10 @@ periphdriver_register(void *data)
 	newdrivers[nperiph_drivers + 1] = NULL;
 	old = periph_drivers;
 	periph_drivers = newdrivers;
+	nperiph_drivers++;
+	xpt_unlock_buses();
 	if (old)
 		free(old, M_CAMPERIPH);
-	nperiph_drivers++;
 	/* If driver marked as early or it is late now, initialize it. */
 	if (((drv->flags & CAM_PERIPH_DRV_EARLY) != 0 && initialized > 0) ||
 	    initialized > 1)

Modified: stable/10/sys/cam/cam_xpt.c
==============================================================================
--- stable/10/sys/cam/cam_xpt.c	Sun May 24 02:46:08 2015	(r283348)
+++ stable/10/sys/cam/cam_xpt.c	Sun May 24 04:14:09 2015	(r283349)
@@ -149,6 +149,8 @@ typedef int	xpt_pdrvfunc_t (struct perip
 /* Transport layer configuration information */
 static struct xpt_softc xsoftc;
 
+MTX_SYSINIT(xpt_topo_init, &xsoftc.xpt_topo_lock, "XPT topology lock", MTX_DEF);
+
 TUNABLE_INT("kern.cam.boot_delay", &xsoftc.boot_delay);
 SYSCTL_INT(_kern_cam, OID_AUTO, boot_delay, CTLFLAG_RDTUN,
            &xsoftc.boot_delay, 0, "Bus registration wait time");
@@ -850,7 +852,6 @@ xpt_init(void *dummy)
 
 	mtx_init(&xsoftc.xpt_lock, "XPT lock", NULL, MTX_DEF);
 	mtx_init(&xsoftc.xpt_highpower_lock, "XPT highpower lock", NULL, MTX_DEF);
-	mtx_init(&xsoftc.xpt_topo_lock, "XPT topology lock", NULL, MTX_DEF);
 	xsoftc.xpt_taskq = taskqueue_create("CAM XPT task", M_WAITOK,
 	    taskqueue_thread_enqueue, /*context*/&xsoftc.xpt_taskq);
 



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