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.
This commit is contained in:
Kenneth D. Merry 2010-12-10 21:38:51 +00:00
parent 7cea3d952b
commit 7c103dde1e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216361
3 changed files with 48 additions and 16 deletions

View File

@ -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

View File

@ -658,10 +658,19 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
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);

View File

@ -525,9 +525,9 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
* 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, union ccb *ccb, union ccb *inccb)
&& ((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));