summaryrefslogtreecommitdiffstats
path: root/sbin/camcontrol
diff options
context:
space:
mode:
authorken <ken@FreeBSD.org>2010-12-10 21:38:51 +0000
committerken <ken@FreeBSD.org>2010-12-10 21:38:51 +0000
commitff1d787db7946285069059143079c2906cf1725e (patch)
tree16ae5188eba0247928f464c632436c72f8e34e77 /sbin/camcontrol
parent3e590c80dd031994516eb3aacfd132e53a5de7ba (diff)
downloadFreeBSD-src-ff1d787db7946285069059143079c2906cf1725e.zip
FreeBSD-src-ff1d787db7946285069059143079c2906cf1725e.tar.gz
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.
Diffstat (limited to 'sbin/camcontrol')
-rw-r--r--sbin/camcontrol/camcontrol.c46
1 files changed, 34 insertions, 12 deletions
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index 88ae1ac..b5f2fb5 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -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 *devlist)
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
OpenPOWER on IntegriCloud