svn commit: r283349 - stable/10/sys/cam
Edward Tomasz Napierala
trasz at FreeBSD.org
Sun May 24 04:14:11 UTC 2015
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);
More information about the svn-src-all
mailing list