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);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to