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-all
mailing list