summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-11-02 17:23:44 +0000
committermav <mav@FreeBSD.org>2014-11-02 17:23:44 +0000
commit3f2b3e757a205c086811984d821be472cc16ba57 (patch)
tree5ac8f4f6f817ebb716489e212cc140e25bfba4d8
parentd8d62b896b89f951f88e70ff55e1b80172582d95 (diff)
downloadFreeBSD-src-3f2b3e757a205c086811984d821be472cc16ba57.zip
FreeBSD-src-3f2b3e757a205c086811984d821be472cc16ba57.tar.gz
MFC r272401, r272402: Rework the logic of sequential SCSI LUN scanner.
Previous logic was not differentiating disconnected LUNs and absent targets. That made it to stop scan if LUN 0 was not found for any reason. That made problematic, for example, using iSCSI targets declaring SPC-2 compliance and having no LUN 0 configured. The new logic continues sequential LUN scan if: -- we have more configured LUNs that need recheck; -- this LUN is connected and its SCSI version allows more LUNs; -- this LUN is disconnected, its SCSI version allows more LUNs and we guess they may be connected (we haven't scanned first 8 LUNs yet or kern.cam.cam_srch_hi sysctl is set to scan more).
-rw-r--r--sys/cam/scsi/scsi_xpt.c101
1 files changed, 39 insertions, 62 deletions
diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c
index 6d93b6a..fb3109b 100644
--- a/sys/cam/scsi/scsi_xpt.c
+++ b/sys/cam/scsi/scsi_xpt.c
@@ -1138,6 +1138,7 @@ out:
u_int8_t periph_qual;
path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID;
+ scsi_find_quirk(path->device);
inq_buf = &path->device->inq_data;
periph_qual = SID_QUAL(inq_buf);
@@ -1166,8 +1167,6 @@ out:
goto out;
}
- scsi_find_quirk(path->device);
-
scsi_devise_transport(path);
if (path->device->lun_id == 0 &&
@@ -1216,10 +1215,13 @@ out:
: SF_RETRY_UA,
&softc->saved_ccb) == ERESTART) {
goto outr;
- } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
- /* Don't wedge the queue */
- xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
- /*run_queue*/TRUE);
+ } else {
+ if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path,
+ /*count*/1, /*run_queue*/TRUE);
+ }
+ path->device->flags &= ~CAM_DEV_INQUIRY_DATA_VALID;
}
/*
* If we get to this point, we got an error status back
@@ -1980,7 +1982,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
struct cam_path *path, *oldpath;
scsi_scan_bus_info *scan_info;
struct cam_et *target;
- struct cam_ed *device;
+ struct cam_ed *device, *nextdev;
int next_target;
path_id_t path_id;
target_id_t target_id;
@@ -1989,18 +1991,10 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
oldpath = request_ccb->ccb_h.path;
status = cam_ccb_status(request_ccb);
- /* Reuse the same CCB to query if a device was really found */
scan_info = (scsi_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0;
- xpt_setup_ccb(&request_ccb->ccb_h, request_ccb->ccb_h.path,
- request_ccb->ccb_h.pinfo.priority);
- request_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
-
-
path_id = request_ccb->ccb_h.path_id;
target_id = request_ccb->ccb_h.target_id;
lun_id = request_ccb->ccb_h.target_lun;
- xpt_action(request_ccb);
-
target = request_ccb->ccb_h.path->target;
next_target = 1;
@@ -2077,56 +2071,39 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
}
}
} else {
- mtx_unlock(&target->luns_mtx);
- if (request_ccb->ccb_h.status != CAM_REQ_CMP) {
- int phl;
-
- /*
- * If we already probed lun 0 successfully, or
- * we have additional configured luns on this
- * target that might have "gone away", go onto
- * the next lun.
- */
- /*
- * We may touch devices that we don't
- * hold references too, so ensure they
- * don't disappear out from under us.
- * The target above is referenced by the
- * path in the request ccb.
- */
- phl = 0;
- device = TAILQ_FIRST(&target->ed_entries);
- if (device != NULL) {
- phl = CAN_SRCH_HI_SPARSE(device);
- if (device->lun_id == 0)
- device = TAILQ_NEXT(device, links);
- }
- if ((lun_id != 0) || (device != NULL)) {
- if (lun_id < (CAM_SCSI2_MAXLUN-1) || phl) {
- lun_id++;
- next_target = 0;
- }
- }
- if (lun_id == request_ccb->ccb_h.target_lun
- || lun_id > scan_info->cpi->max_lun)
- next_target = 1;
- } else {
-
+ mtx_unlock(&target->luns_mtx);
device = request_ccb->ccb_h.path->device;
-
- if ((SCSI_QUIRK(device)->quirks &
- CAM_QUIRK_NOLUNS) == 0) {
- /* Try the next lun */
- if (lun_id < (CAM_SCSI2_MAXLUN-1)
- || CAN_SRCH_HI_DENSE(device)) {
- lun_id++;
+ /* Continue sequential LUN scan if: */
+ /* -- we have more LUNs that need recheck */
+ mtx_lock(&target->bus->eb_mtx);
+ nextdev = device;
+ while ((nextdev = TAILQ_NEXT(nextdev, links)) != NULL)
+ if ((nextdev->flags & CAM_DEV_UNCONFIGURED) == 0)
+ break;
+ mtx_unlock(&target->bus->eb_mtx);
+ if (nextdev != NULL) {
+ next_target = 0;
+ /* -- stop if CAM_QUIRK_NOLUNS is set. */
+ } else if (SCSI_QUIRK(device)->quirks & CAM_QUIRK_NOLUNS) {
+ next_target = 1;
+ /* -- this LUN is connected and its SCSI version
+ * allows more LUNs. */
+ } else if ((device->flags & CAM_DEV_UNCONFIGURED) == 0) {
+ if (lun_id < (CAM_SCSI2_MAXLUN-1) ||
+ CAN_SRCH_HI_DENSE(device))
+ next_target = 0;
+ /* -- this LUN is disconnected, its SCSI version
+ * allows more LUNs and we guess they may be. */
+ } else if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0) {
+ if (lun_id < (CAM_SCSI2_MAXLUN-1) ||
+ CAN_SRCH_HI_SPARSE(device))
next_target = 0;
- }
}
- if (lun_id == request_ccb->ccb_h.target_lun
- || lun_id > scan_info->cpi->max_lun)
- next_target = 1;
- }
+ if (next_target == 0) {
+ lun_id++;
+ if (lun_id > scan_info->cpi->max_lun)
+ next_target = 1;
+ }
}
/*
OpenPOWER on IntegriCloud