Date: Fri, 10 Dec 2010 21:38:51 +0000 (UTC) From: "Kenneth D. Merry" <ken@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r216361 - in head: sbin/camcontrol sys/cam sys/cam/scsi Message-ID: <201012102138.oBALcpJs086334@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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));
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201012102138.oBALcpJs086334>