summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-10-20 07:57:07 +0000
committermav <mav@FreeBSD.org>2014-10-20 07:57:07 +0000
commite2ad56a41de731ac10d741064e55faaa2744cd91 (patch)
tree1aea1b25c703acf879251f44ddd04774d7e95629 /sys/cam
parenta0796a04ee35c3f816e1cf2ecc9a0a3ad56f54f8 (diff)
downloadFreeBSD-src-e2ad56a41de731ac10d741064e55faaa2744cd91.zip
FreeBSD-src-e2ad56a41de731ac10d741064e55faaa2744cd91.tar.gz
MFC r272938: Filter out duplicate AC_PATH_REGISTERED async events.
Queued async events handling in CAM opened race, that may lead to duplicate AC_PATH_REGISTERED events delivery during boot. That was not happening before r272935 because the driver was initialized later. After that change it started create duplicate ports in CTL.
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/ctl/scsi_ctl.c84
1 files changed, 39 insertions, 45 deletions
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index fee5f4c..1dac651 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -271,11 +271,19 @@ ctlfeperiphinit(void)
static void
ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
{
+ struct ctlfe_softc *softc;
#ifdef CTLFEDEBUG
printf("%s: entered\n", __func__);
#endif
+ mtx_lock(&ctlfe_list_mtx);
+ STAILQ_FOREACH(softc, &ctlfe_softc_list, links) {
+ if (softc->path_id == xpt_path_path_id(path))
+ break;
+ }
+ mtx_unlock(&ctlfe_list_mtx);
+
/*
* When a new path gets registered, and it is capable of target
* mode, go ahead and attach. Later on, we may need to be more
@@ -284,7 +292,6 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
switch (code) {
case AC_PATH_REGISTERED: {
struct ctl_port *port;
- struct ctlfe_softc *bus_softc;
struct ccb_pathinq *cpi;
int retval;
@@ -299,6 +306,14 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
break;
}
+ if (softc != NULL) {
+#ifdef CTLFEDEBUG
+ printf("%s: CTL port for CAM path %u already exists\n",
+ __func__, xpt_path_path_id(path));
+#endif
+ break;
+ }
+
#ifdef CTLFE_INIT_ENABLE
if (ctlfe_num_targets >= ctlfe_max_targets) {
union ccb *ccb;
@@ -347,25 +362,23 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
* use M_NOWAIT. Of course this means trouble if we
* can't allocate memory.
*/
- bus_softc = malloc(sizeof(*bus_softc), M_CTLFE,
- M_NOWAIT | M_ZERO);
- if (bus_softc == NULL) {
+ softc = malloc(sizeof(*softc), M_CTLFE, M_NOWAIT | M_ZERO);
+ if (softc == NULL) {
printf("%s: unable to malloc %zd bytes for softc\n",
- __func__, sizeof(*bus_softc));
+ __func__, sizeof(*softc));
return;
}
- bus_softc->path_id = cpi->ccb_h.path_id;
- bus_softc->sim = xpt_path_sim(path);
+ softc->path_id = cpi->ccb_h.path_id;
+ softc->sim = xpt_path_sim(path);
if (cpi->maxio != 0)
- bus_softc->maxio = cpi->maxio;
+ softc->maxio = cpi->maxio;
else
- bus_softc->maxio = DFLTPHYS;
- mtx_init(&bus_softc->lun_softc_mtx, "LUN softc mtx", NULL,
- MTX_DEF);
- STAILQ_INIT(&bus_softc->lun_softc_list);
+ softc->maxio = DFLTPHYS;
+ mtx_init(&softc->lun_softc_mtx, "LUN softc mtx", NULL, MTX_DEF);
+ STAILQ_INIT(&softc->lun_softc_list);
- port = &bus_softc->port;
+ port = &softc->port;
port->frontend = &ctlfe_frontend;
/*
@@ -380,21 +393,21 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
/* XXX KDM what should the real number be here? */
port->num_requested_ctl_io = 4096;
- snprintf(bus_softc->port_name, sizeof(bus_softc->port_name),
+ snprintf(softc->port_name, sizeof(softc->port_name),
"%s%d", cpi->dev_name, cpi->unit_number);
/*
* XXX KDM it would be nice to allocate storage in the
* frontend structure itself.
*/
- port->port_name = bus_softc->port_name;
+ port->port_name = softc->port_name;
port->physical_port = cpi->unit_number;
port->virtual_port = cpi->bus_id;
port->port_online = ctlfe_online;
port->port_offline = ctlfe_offline;
- port->onoff_arg = bus_softc;
+ port->onoff_arg = softc;
port->lun_enable = ctlfe_lun_enable;
port->lun_disable = ctlfe_lun_disable;
- port->targ_lun_arg = bus_softc;
+ port->targ_lun_arg = softc;
port->fe_datamove = ctlfe_datamove_done;
port->fe_done = ctlfe_datamove_done;
/*
@@ -416,35 +429,28 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
if (retval != 0) {
printf("%s: ctl_port_register() failed with "
"error %d!\n", __func__, retval);
- mtx_destroy(&bus_softc->lun_softc_mtx);
- free(bus_softc, M_CTLFE);
+ mtx_destroy(&softc->lun_softc_mtx);
+ free(softc, M_CTLFE);
break;
} else {
mtx_lock(&ctlfe_list_mtx);
- STAILQ_INSERT_TAIL(&ctlfe_softc_list, bus_softc, links);
+ STAILQ_INSERT_TAIL(&ctlfe_softc_list, softc, links);
mtx_unlock(&ctlfe_list_mtx);
}
break;
}
case AC_PATH_DEREGISTERED: {
- struct ctlfe_softc *softc = NULL;
-
- mtx_lock(&ctlfe_list_mtx);
- STAILQ_FOREACH(softc, &ctlfe_softc_list, links) {
- if (softc->path_id == xpt_path_path_id(path)) {
- STAILQ_REMOVE(&ctlfe_softc_list, softc,
- ctlfe_softc, links);
- break;
- }
- }
- mtx_unlock(&ctlfe_list_mtx);
if (softc != NULL) {
/*
* XXX KDM are we certain at this point that there
* are no outstanding commands for this frontend?
*/
+ mtx_lock(&ctlfe_list_mtx);
+ STAILQ_REMOVE(&ctlfe_softc_list, softc, ctlfe_softc,
+ links);
+ mtx_unlock(&ctlfe_list_mtx);
ctl_port_deregister(&softc->port);
mtx_destroy(&softc->lun_softc_mtx);
free(softc, M_CTLFE);
@@ -459,8 +465,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
switch (ac->contract_number) {
case AC_CONTRACT_DEV_CHG: {
struct ac_device_changed *dev_chg;
- struct ctlfe_softc *softc;
- int retval, found;
+ int retval;
dev_chg = (struct ac_device_changed *)ac->contract_data;
@@ -469,18 +474,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
xpt_path_path_id(path), dev_chg->target,
(dev_chg->arrived == 0) ? "left" : "arrived");
- found = 0;
-
- mtx_lock(&ctlfe_list_mtx);
- STAILQ_FOREACH(softc, &ctlfe_softc_list, links) {
- if (softc->path_id == xpt_path_path_id(path)) {
- found = 1;
- break;
- }
- }
- mtx_unlock(&ctlfe_list_mtx);
-
- if (found == 0) {
+ if (softc == NULL) {
printf("%s: CTL port for CAM path %u not "
"found!\n", __func__,
xpt_path_path_id(path));
OpenPOWER on IntegriCloud