diff options
author | ken <ken@FreeBSD.org> | 2010-12-10 21:38:51 +0000 |
---|---|---|
committer | ken <ken@FreeBSD.org> | 2010-12-10 21:38:51 +0000 |
commit | ff1d787db7946285069059143079c2906cf1725e (patch) | |
tree | 16ae5188eba0247928f464c632436c72f8e34e77 /sbin/camcontrol | |
parent | 3e590c80dd031994516eb3aacfd132e53a5de7ba (diff) | |
download | FreeBSD-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.c | 46 |
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 |