summaryrefslogtreecommitdiffstats
path: root/sys/cam/cam_periph.c
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2015-05-24 04:14:09 +0000
committertrasz <trasz@FreeBSD.org>2015-05-24 04:14:09 +0000
commit531e259796a40dbc2136525917ce52587b882c13 (patch)
tree63a0af7e72743511329ee86949d4bceed034b004 /sys/cam/cam_periph.c
parente65a83355e4c18754f620a7c9b6e26553c777817 (diff)
downloadFreeBSD-src-531e259796a40dbc2136525917ce52587b882c13.zip
FreeBSD-src-531e259796a40dbc2136525917ce52587b882c13.tar.gz
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
Diffstat (limited to 'sys/cam/cam_periph.c')
-rw-r--r--sys/cam/cam_periph.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 2544d27..53454f8 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -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)
OpenPOWER on IntegriCloud