mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-06 16:40:47 +00:00
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:
parent
7cea3d952b
commit
7c103dde1e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216361
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
Loading…
Reference in a new issue