svn commit: r216361 - in head: sbin/camcontrol sys/cam sys/cam/scsi

Kenneth D. Merry ken at FreeBSD.org
Fri Dec 10 21:38:52 UTC 2010


Author: ken
Date: Fri Dec 10 21:38:51 2010
New Revision: 216361
URL: http://svn.freebsd.org/changeset/base/216361

Log:
  Fix a few issues related to the XPT_GDEV_ADVINFO CCB.
  
  camcontrol.c:	In buildbusdevlist(), don't attempt to get call
  		getdevid() for an unconfigured device, even when the
  		verbose flag is set.  The cam_open_btl() call will almost
  		certainly fail.
  
  		Probe for the buffer size when issuing the XPT_GDEV_ADVINFO
  		CCB.  Probing for the buffer size first helps us avoid
  		allocating the maximum buffer size when it really may not
  		be necessary.  This also helps avoid errors from
  		cam_periph_mapmem() if we attempt to map more than MAXPHYS.
  
  cam_periph.c:	In cam_periph_mapmem(), if the XPT_GDEV_ADVINFO CCB
  		shows a bufsiz of 0, we don't have anything to map,
  		so just return.
  
  		Also, set the maximum mapping size to MAXPHYS
  		instead of DFLTPHYS for XPT_GDEV_ADVINFO CCBs,
  		since they don't actually go down to the hardware.
  
  scsi_pass.c:	Don't bother mapping the buffer in XPT_GDEV_ADVINFO
  		CCBs if bufsiz is 0.

Modified:
  head/sbin/camcontrol/camcontrol.c
  head/sys/cam/cam_periph.c
  head/sys/cam/scsi/scsi_pass.c

Modified: head/sbin/camcontrol/camcontrol.c
==============================================================================
--- head/sbin/camcontrol/camcontrol.c	Fri Dec 10 20:27:50 2010	(r216360)
+++ head/sbin/camcontrol/camcontrol.c	Fri Dec 10 21:38:51 2010	(r216361)
@@ -5026,14 +5026,7 @@ getdevid(struct cam_devitem *item)
 		goto bailout;
 	}
 
-	item->device_id_len = CAM_SCSI_DEVID_MAXLEN;
-	item->device_id = malloc(item->device_id_len);
-	if (item->device_id == NULL) {
-		warn("%s: unable to allocate %d bytes", __func__,
-		     item->device_id_len);
-		retval = 1;
-		goto bailout;
-	}
+	item->device_id_len = 0;
 
 	ccb = cam_getccb(dev);
 	if (ccb == NULL) {
@@ -5044,12 +5037,19 @@ getdevid(struct cam_devitem *item)
 
 	bzero(&(&ccb->ccb_h)[1],
 	      sizeof(union ccb) - sizeof(struct ccb_hdr));
+
+	/*
+	 * On the first try, we just probe for the size of the data, and
+	 * then allocate that much memory and try again.
+	 */
+retry:
 	ccb->ccb_h.func_code = XPT_GDEV_ADVINFO;
 	ccb->ccb_h.flags = CAM_DIR_IN;
 	ccb->cgdai.flags = CGDAI_FLAG_PROTO;
 	ccb->cgdai.buftype = CGDAI_TYPE_SCSI_DEVID;
 	ccb->cgdai.bufsiz = item->device_id_len;
-	ccb->cgdai.buf = (uint8_t *)item->device_id;
+	if (item->device_id_len != 0)
+		ccb->cgdai.buf = (uint8_t *)item->device_id;
 
 	if (cam_send_ccb(dev, ccb) < 0) {
 		warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__);
@@ -5063,6 +5063,29 @@ getdevid(struct cam_devitem *item)
 		goto bailout;
 	}
 
+	if (item->device_id_len == 0) {
+		/*
+		 * This is our first time through.  Allocate the buffer,
+		 * and then go back to get the data.
+		 */
+		if (ccb->cgdai.provsiz == 0) {
+			warnx("%s: invalid .provsiz field returned with "
+			     "XPT_GDEV_ADVINFO CCB", __func__);
+			retval = 1;
+			goto bailout;
+		}
+		item->device_id_len = ccb->cgdai.provsiz;
+		item->device_id = malloc(item->device_id_len);
+		if (item->device_id == NULL) {
+			warn("%s: unable to allocate %d bytes", __func__,
+			     item->device_id_len);
+			retval = 1;
+			goto bailout;
+		}
+		ccb->ccb_h.status = CAM_REQ_INPROG;
+		goto retry;
+	}
+
 bailout:
 	if (dev != NULL)
 		cam_close_device(dev);
@@ -5158,9 +5181,8 @@ buildbusdevlist(struct cam_devlist *devl
 				dev_result = 
 				     &ccb.cdm.matches[i].result.device_result;
 
-				if ((dev_result->flags
-				     & DEV_RESULT_UNCONFIGURED)
-				 && ((arglist & CAM_ARG_VERBOSE) == 0)) {
+				if (dev_result->flags &
+				    DEV_RESULT_UNCONFIGURED) {
 					skip_device = 1;
 					break;
 				} else

Modified: head/sys/cam/cam_periph.c
==============================================================================
--- head/sys/cam/cam_periph.c	Fri Dec 10 20:27:50 2010	(r216360)
+++ head/sys/cam/cam_periph.c	Fri Dec 10 21:38:51 2010	(r216361)
@@ -658,10 +658,19 @@ cam_periph_mapmem(union ccb *ccb, struct
 		numbufs = 2;
 		break;
 	case XPT_GDEV_ADVINFO:
+		if (ccb->cgdai.bufsiz == 0)
+			return (0);
+
 		data_ptrs[0] = (uint8_t **)&ccb->cgdai.buf;
 		lengths[0] = ccb->cgdai.bufsiz;
 		dirs[0] = CAM_DIR_IN;
 		numbufs = 1;
+
+		/*
+		 * This request will not go to the hardware, no reason
+		 * to be so strict. vmapbuf() is able to map up to MAXPHYS.
+		 */
+		maxmap = MAXPHYS;
 		break;
 	default:
 		return(EINVAL);

Modified: head/sys/cam/scsi/scsi_pass.c
==============================================================================
--- head/sys/cam/scsi/scsi_pass.c	Fri Dec 10 20:27:50 2010	(r216360)
+++ head/sys/cam/scsi/scsi_pass.c	Fri Dec 10 21:38:51 2010	(r216361)
@@ -525,9 +525,9 @@ passsendccb(struct cam_periph *periph, u
 	 * if they haven't passed in a physical memory pointer,
 	 * and if there is actually an I/O operation to perform.
 	 * cam_periph_mapmem() supports SCSI, ATA, SMP, ADVINFO and device
-	 * match CCBs.  For the SCSI and ATA CCBs, we only pass the CCB in if
-	 * there's actually data to map.  cam_periph_mapmem() will do the
-	 * right thing, even if there isn't data to map, but since CCBs
+	 * match CCBs.  For the SCSI, ATA and ADVINFO CCBs, we only pass the
+	 * CCB in if there's actually data to map.  cam_periph_mapmem() will
+	 * do the right thing, even if there isn't data to map, but since CCBs
 	 * without data are a reasonably common occurance (e.g. test unit
 	 * ready), it will save a few cycles if we check for it here.
 	 */
@@ -537,7 +537,8 @@ passsendccb(struct cam_periph *periph, u
 	    && ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE))
 	  || (ccb->ccb_h.func_code == XPT_DEV_MATCH)
 	  || (ccb->ccb_h.func_code == XPT_SMP_IO)
-	  || (ccb->ccb_h.func_code == XPT_GDEV_ADVINFO))) {
+	  || ((ccb->ccb_h.func_code == XPT_GDEV_ADVINFO)
+	   && (ccb->cgdai.bufsiz > 0)))) {
 
 		bzero(&mapinfo, sizeof(mapinfo));
 


More information about the svn-src-head mailing list