Author: mav
Date: Thu Oct  2 09:42:11 2014
New Revision: 272401
URL: https://svnweb.freebsd.org/changeset/base/272401

Log:
  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).
  
  Reported by:  trasz
  MFC after:    1 month

Modified:
  head/sys/cam/scsi/scsi_xpt.c

Modified: head/sys/cam/scsi/scsi_xpt.c
==============================================================================
--- head/sys/cam/scsi/scsi_xpt.c        Thu Oct  2 08:57:11 2014        
(r272400)
+++ head/sys/cam/scsi/scsi_xpt.c        Thu Oct  2 09:42:11 2014        
(r272401)
@@ -1135,6 +1135,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);
@@ -1163,8 +1164,6 @@ out:
                                        goto out;
                                }
 
-                               scsi_find_quirk(path->device);
-
                                scsi_devise_transport(path);
 
                                if (path->device->lun_id == 0 &&
@@ -1213,10 +1212,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
@@ -1975,7 +1977,7 @@ scsi_scan_bus(struct cam_periph *periph,
                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;
@@ -1984,18 +1986,10 @@ scsi_scan_bus(struct cam_periph *periph,
                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;
 
@@ -2068,56 +2062,36 @@ scsi_scan_bus(struct cam_periph *periph,
                                }
                        }
                } 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;
+                       /*  -- 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 (next_target == 0) {
+                               lun_id++;
+                               if (lun_id > scan_info->cpi->max_lun)
+                                       next_target = 1;
                        }
-                       if (lun_id == request_ccb->ccb_h.target_lun
-                           || lun_id > scan_info->cpi->max_lun)
-                               next_target = 1;
-                   }
                }
 
                /*
_______________________________________________
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