diff options
author | sephe <sephe@FreeBSD.org> | 2016-01-27 05:19:05 +0000 |
---|---|---|
committer | sephe <sephe@FreeBSD.org> | 2016-01-27 05:19:05 +0000 |
commit | ab5817778ba6e3a18afecb75cb4a290e4f7efece (patch) | |
tree | 9327d0e36db1f92f8edb15d50865798fc7197162 /sys/dev | |
parent | e15fc69684ffd8c8e682b637c6f154f82142f2ff (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c | 88 |
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; |