summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2016-01-27 05:19:05 +0000
committersephe <sephe@FreeBSD.org>2016-01-27 05:19:05 +0000
commitab5817778ba6e3a18afecb75cb4a290e4f7efece (patch)
tree9327d0e36db1f92f8edb15d50865798fc7197162 /sys/dev/hyperv
parente15fc69684ffd8c8e682b637c6f154f82142f2ff (diff)
downloadFreeBSD-src-ab5817778ba6e3a18afecb75cb4a290e4f7efece.zip
FreeBSD-src-ab5817778ba6e3a18afecb75cb4a290e4f7efece.tar.gz
MFC r294557:
hyperv/stor: Verify returned inquiry data before further dispatching Windows 10 and Window 2016 will return all zero inquiry data for non-existing slots. If we dispatched them, then a lot of useless (0 sized) disks would be created. So we verify the returned inquiry data (valid type, non-empty vendor/product/revision etc.), before further dispatching. Minor white space cleanup and wording fix. Submitted by: Hongjiang Zhang <honzhan microsoft com> Reviewed by: adrian, sephe, Jun Su <junsu microsoft com> Approved by: adrian (mentor) Modified by: sephe Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D4928
Diffstat (limited to 'sys/dev/hyperv')
-rw-r--r--sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c88
1 files changed, 85 insertions, 3 deletions
diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
index 3a27115..7582aec 100644
--- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
@@ -1923,6 +1923,66 @@ create_storvsc_request(union ccb *ccb, struct hv_storvsc_request *reqp)
return(0);
}
+/*
+ * Modified based on scsi_print_inquiry which is responsible to
+ * print the detail information for scsi_inquiry_data.
+ *
+ * Return 1 if it is valid, 0 otherwise.
+ */
+static inline int
+is_inquiry_valid(const struct scsi_inquiry_data *inq_data)
+{
+ uint8_t type;
+ char vendor[16], product[48], revision[16];
+
+ /*
+ * Check device type and qualifier
+ */
+ if (!(SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ||
+ SID_QUAL(inq_data) == SID_QUAL_LU_CONNECTED))
+ return (0);
+
+ type = SID_TYPE(inq_data);
+ switch (type) {
+ case T_DIRECT:
+ case T_SEQUENTIAL:
+ case T_PRINTER:
+ case T_PROCESSOR:
+ case T_WORM:
+ case T_CDROM:
+ case T_SCANNER:
+ case T_OPTICAL:
+ case T_CHANGER:
+ case T_COMM:
+ case T_STORARRAY:
+ case T_ENCLOSURE:
+ case T_RBC:
+ case T_OCRW:
+ case T_OSD:
+ case T_ADC:
+ break;
+ case T_NODEVICE:
+ default:
+ return (0);
+ }
+
+ /*
+ * Check vendor, product, and revision
+ */
+ cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
+ sizeof(vendor));
+ cam_strvis(product, inq_data->product, sizeof(inq_data->product),
+ sizeof(product));
+ cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
+ sizeof(revision));
+ if (strlen(vendor) == 0 ||
+ strlen(product) == 0 ||
+ strlen(revision) == 0)
+ return (0);
+
+ return (1);
+}
+
/**
* @brief completion function before returning to CAM
*
@@ -1993,11 +2053,33 @@ storvsc_io_done(struct hv_storvsc_request *reqp)
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
if (vm_srb->scsi_status == SCSI_STATUS_OK) {
- ccb->ccb_h.status |= CAM_REQ_CMP;
- } else {
+ const struct scsi_generic *cmd;
+
+ /*
+ * Check whether the data for INQUIRY cmd is valid or
+ * not. Windows 10 and Windows 2016 send all zero
+ * inquiry data to VM even for unpopulated slots.
+ */
+ cmd = (const struct scsi_generic *)
+ ((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+ csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
+ if (cmd->opcode == INQUIRY &&
+ is_inquiry_valid(
+ (const struct scsi_inquiry_data *)csio->data_ptr) == 0) {
+ ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+ if (bootverbose) {
+ mtx_lock(&sc->hs_lock);
+ xpt_print(ccb->ccb_h.path,
+ "storvsc uninstalled device\n");
+ mtx_unlock(&sc->hs_lock);
+ }
+ } else {
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+ }
+ } else {
mtx_lock(&sc->hs_lock);
xpt_print(ccb->ccb_h.path,
- "srovsc scsi_status = %d\n",
+ "storvsc scsi_status = %d\n",
vm_srb->scsi_status);
mtx_unlock(&sc->hs_lock);
ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
OpenPOWER on IntegriCloud