summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>2012-12-09 19:53:21 +0000
committerken <ken@FreeBSD.org>2012-12-09 19:53:21 +0000
commit287e4f6a6baae6598a7ebb9580a440bbff2f9113 (patch)
tree09c72328c6e67b6e8ed0c793d8fd837be09a3719
parentd004c46035fec779a966e34d3480a59fd6ea06fd (diff)
downloadFreeBSD-src-287e4f6a6baae6598a7ebb9580a440bbff2f9113.zip
FreeBSD-src-287e4f6a6baae6598a7ebb9580a440bbff2f9113.tar.gz
Fix a couple of CTL locking issues and clean up some duplicated code.
ctl_frontend_cam_sim.c: Coalesce cfcs_online() and cfcs_offline() into a single function since these were identical except for one line. Make sure we hold the SIM lock around path creation, and calling xpt_rescan(). scsi_ctl.c: In ctlfe_onoffline(), make sure we hold the SIM lock around path creation and free calls, as well as xpt_action(). In ctlfe_lun_enable(), hold the SIM lock around path and peripheral operations that require it. Sponsored by: Spectra Logic Corporation MFC after: 1 week
-rw-r--r--sys/cam/ctl/ctl_frontend_cam_sim.c42
-rw-r--r--sys/cam/ctl/scsi_ctl.c26
2 files changed, 31 insertions, 37 deletions
diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c
index fa72059..43e4d61d 100644
--- a/sys/cam/ctl/ctl_frontend_cam_sim.c
+++ b/sys/cam/ctl/ctl_frontend_cam_sim.c
@@ -275,7 +275,7 @@ cfcs_shutdown(void)
}
static void
-cfcs_online(void *arg)
+cfcs_onoffline(void *arg, int online)
{
struct cfcs_softc *softc;
union ccb *ccb;
@@ -283,13 +283,12 @@ cfcs_online(void *arg)
softc = (struct cfcs_softc *)arg;
mtx_lock(&softc->lock);
- softc->online = 1;
- mtx_unlock(&softc->lock);
+ softc->online = online;
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) {
printf("%s: unable to allocate CCB for rescan\n", __func__);
- return;
+ goto bailout;
}
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
@@ -297,37 +296,24 @@ cfcs_online(void *arg)
CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
printf("%s: can't allocate path for rescan\n", __func__);
xpt_free_ccb(ccb);
- return;
+ goto bailout;
}
xpt_rescan(ccb);
+
+bailout:
+ mtx_unlock(&softc->lock);
}
static void
-cfcs_offline(void *arg)
+cfcs_online(void *arg)
{
- struct cfcs_softc *softc;
- union ccb *ccb;
-
- softc = (struct cfcs_softc *)arg;
-
- mtx_lock(&softc->lock);
- softc->online = 0;
- mtx_unlock(&softc->lock);
-
- ccb = xpt_alloc_ccb_nowait();
- if (ccb == NULL) {
- printf("%s: unable to allocate CCB for rescan\n", __func__);
- return;
- }
+ cfcs_onoffline(arg, /*online*/ 1);
+}
- if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
- cam_sim_path(softc->sim), CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- printf("%s: can't allocate path for rescan\n", __func__);
- xpt_free_ccb(ccb);
- return;
- }
- xpt_rescan(ccb);
+static void
+cfcs_offline(void *arg)
+{
+ cfcs_onoffline(arg, /*online*/ 0);
}
static int
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 898b8f4..59357123 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -1687,16 +1687,21 @@ ctlfe_onoffline(void *arg, int online)
set_wwnn = 0;
+ sim = bus_softc->sim;
+
+ CAM_SIM_LOCK(sim);
status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP) {
printf("%s: unable to create path!\n", __func__);
+ CAM_SIM_UNLOCK(sim);
return;
}
+ CAM_SIM_UNLOCK(sim);
+
ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, M_WAITOK | M_ZERO);
xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
- sim = xpt_path_sim(path);
/*
* Copan WWN format:
@@ -1883,27 +1888,30 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
bus_softc = (struct ctlfe_softc *)arg;
+ sim = bus_softc->sim;
+
+ CAM_SIM_LOCK(sim);
- status = xpt_create_path_unlocked(&path, /*periph*/ NULL,
- bus_softc->path_id,
- targ_id.id,
- lun_id);
+ status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
+ targ_id.id, lun_id);
/* XXX KDM need some way to return status to CTL here? */
if (status != CAM_REQ_CMP) {
printf("%s: could not create path, status %#x\n", __func__,
status);
+ CAM_SIM_UNLOCK(sim);
return (1);
}
+ CAM_SIM_UNLOCK(sim);
softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO);
- sim = xpt_path_sim(path);
- mtx_lock(sim->mtx);
+
+ CAM_SIM_LOCK(sim);
periph = cam_periph_find(path, "ctl");
if (periph != NULL) {
/* We've already got a periph, no need to alloc a new one. */
xpt_free_path(path);
free(softc, M_CTLFE);
- mtx_unlock(sim->mtx);
+ CAM_SIM_UNLOCK(sim);
return (0);
}
@@ -1923,7 +1931,7 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
xpt_free_path(path);
- mtx_unlock(sim->mtx);
+ CAM_SIM_UNLOCK(sim);
return (0);
}
OpenPOWER on IntegriCloud