hyperv/stor: Enable INQUIRY result check only on WIN10 like host systems

On WIN8 like host systems, when rescan happens, the already installed
disks seem to return random invalid results for INQUIRY.

More investigation is under way to figure out why random invalid INQUIRY
results are delivered to VM on WIN8 like host systems.

Submitted by:	Hongjiang Zhang <honzhan microsoft com>
Reviewed by:	sephe
MFC after:	1 week
Sponsored by:	Microsoft OSTC
Differential Revision:	https://reviews.freebsd.org/D6316
This commit is contained in:
Sepherosa Ziehau 2016-05-12 03:29:29 +00:00
parent 5b81187fa9
commit 008c25ebb9
2 changed files with 90 additions and 45 deletions

View File

@ -81,12 +81,6 @@ __FBSDID("$FreeBSD$");
#define BLKVSC_MAX_IO_REQUESTS STORVSC_MAX_IO_REQUESTS
#define STORVSC_MAX_TARGETS (2)
#define STORVSC_WIN7_MAJOR 4
#define STORVSC_WIN7_MINOR 2
#define STORVSC_WIN8_MAJOR 5
#define STORVSC_WIN8_MINOR 1
#define VSTOR_PKT_SIZE (sizeof(struct vstor_packet) - vmscsi_size_delta)
#define HV_ALIGN(x, a) roundup2(x, a)
@ -207,7 +201,7 @@ static struct storvsc_driver_props g_drv_props_table[] = {
* Sense buffer size changed in win8; have a run-time
* variable to track the size we should use.
*/
static int sense_buffer_size;
static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
/*
* The size of the vmscsi_request has changed in win8. The
@ -217,9 +211,46 @@ static int sense_buffer_size;
* Track the correct size we need to apply.
*/
static int vmscsi_size_delta;
/*
* The storage protocol version is determined during the
* initial exchange with the host. It will indicate which
* storage functionality is available in the host.
*/
static int vmstor_proto_version;
static int storvsc_current_major;
static int storvsc_current_minor;
struct vmstor_proto {
int proto_version;
int sense_buffer_size;
int vmscsi_size_delta;
};
static const struct vmstor_proto vmstor_proto_list[] = {
{
VMSTOR_PROTOCOL_VERSION_WIN10,
POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
0
},
{
VMSTOR_PROTOCOL_VERSION_WIN8_1,
POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
0
},
{
VMSTOR_PROTOCOL_VERSION_WIN8,
POST_WIN7_STORVSC_SENSE_BUFFER_SIZE,
0
},
{
VMSTOR_PROTOCOL_VERSION_WIN7,
PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE,
sizeof(struct vmscsi_win8_extension),
},
{
VMSTOR_PROTOCOL_VERSION_WIN6,
PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE,
sizeof(struct vmscsi_win8_extension),
}
};
/* static functions */
static int storvsc_probe(device_t dev);
@ -427,7 +458,7 @@ storvsc_send_multichannel_request(struct hv_device *dev, int max_chans)
static int
hv_storvsc_channel_init(struct hv_device *dev)
{
int ret = 0;
int ret = 0, i;
struct hv_storvsc_request *request;
struct vstor_packet *vstor_packet;
struct storvsc_softc *sc;
@ -476,19 +507,20 @@ hv_storvsc_channel_init(struct hv_device *dev)
goto cleanup;
}
/* reuse the packet for version range supported */
for (i = 0; i < nitems(vmstor_proto_list); i++) {
/* reuse the packet for version range supported */
memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->operation = VSTOR_OPERATION_QUERYPROTOCOLVERSION;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->operation = VSTOR_OPERATION_QUERYPROTOCOLVERSION;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
vstor_packet->u.version.major_minor =
VMSTOR_PROTOCOL_VERSION(storvsc_current_major, storvsc_current_minor);
vstor_packet->u.version.major_minor =
vmstor_proto_list[i].proto_version;
/* revision is only significant for Windows guests */
vstor_packet->u.version.revision = 0;
/* revision is only significant for Windows guests */
vstor_packet->u.version.revision = 0;
ret = hv_vmbus_channel_send_packet(
ret = hv_vmbus_channel_send_packet(
dev->channel,
vstor_packet,
VSTOR_PKT_SIZE,
@ -496,20 +528,34 @@ hv_storvsc_channel_init(struct hv_device *dev)
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
if (ret != 0)
if (ret != 0)
goto cleanup;
/* wait 5 seconds */
ret = sema_timedwait(&request->synch_sema, 5 * hz);
if (ret)
goto cleanup;
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO) {
ret = EINVAL;
goto cleanup;
}
if (vstor_packet->status == 0) {
vmstor_proto_version =
vmstor_proto_list[i].proto_version;
sense_buffer_size =
vmstor_proto_list[i].sense_buffer_size;
vmscsi_size_delta =
vmstor_proto_list[i].vmscsi_size_delta;
break;
}
}
if (vstor_packet->status != 0) {
ret = EINVAL;
goto cleanup;
/* wait 5 seconds */
ret = sema_timedwait(&request->synch_sema, 5 * hz);
if (ret)
goto cleanup;
/* TODO: Check returned version */
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO ||
vstor_packet->status != 0)
goto cleanup;
}
/**
* Query channel properties
*/
@ -903,19 +949,6 @@ storvsc_probe(device_t dev)
int ata_disk_enable = 0;
int ret = ENXIO;
if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 ||
hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) {
sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE;
vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
storvsc_current_major = STORVSC_WIN7_MAJOR;
storvsc_current_minor = STORVSC_WIN7_MINOR;
} else {
sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE;
vmscsi_size_delta = 0;
storvsc_current_major = STORVSC_WIN8_MAJOR;
storvsc_current_minor = STORVSC_WIN8_MINOR;
}
switch (storvsc_get_storage_type(dev)) {
case DRIVER_BLKVSC:
if(bootverbose)
@ -2048,6 +2081,13 @@ storvsc_io_done(struct hv_storvsc_request *reqp)
((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
if (cmd->opcode == INQUIRY &&
/*
* XXX: Temporary work around disk hot plugin on win2k12r2,
* only filtering the invalid disk on win10 or 2016 server.
* So, the hot plugin on win10 and 2016 server needs
* to be fixed.
*/
vmstor_proto_version == VMSTOR_PROTOCOL_VERSION_WIN10 &&
is_inquiry_valid(
(const struct scsi_inquiry_data *)csio->data_ptr) == 0) {
ccb->ccb_h.status |= CAM_DEV_NOT_THERE;

View File

@ -41,6 +41,11 @@
#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
(((MINOR_) & 0xff) ))
#define VMSTOR_PROTOCOL_VERSION_WIN6 VMSTOR_PROTOCOL_VERSION(2, 0)
#define VMSTOR_PROTOCOL_VERSION_WIN7 VMSTOR_PROTOCOL_VERSION(4, 2)
#define VMSTOR_PROTOCOL_VERSION_WIN8 VMSTOR_PROTOCOL_VERSION(5, 1)
#define VMSTOR_PROTOCOL_VERSION_WIN8_1 VMSTOR_PROTOCOL_VERSION(6, 0)
#define VMSTOR_PROTOCOL_VERSION_WIN10 VMSTOR_PROTOCOL_VERSION(6, 2)
/*
* Invalid version.
*/