]> xenbits.xensource.com Git - pvdrivers/win/xenvbd.git/commitdiff
Fixed improper SCSI UNMAP request implementation
authorDave Buches <davebuch@amazon.com>
Fri, 22 Jan 2016 04:30:03 +0000 (20:30 -0800)
committerPaul Durrant <paul.durrant@citrix.com>
Fri, 22 Jan 2016 08:53:13 +0000 (08:53 +0000)
The XenDisk disk class filter driver was generating requests
that did not adhere to the t10 SBC-3 SCSI specification for UNMAP
operations.  Specifically, the data length and block descriptor data
length fields were not populated properly per the spec.

Although the XenVBD miniport driver handled these malformed
requests correctly, it failed to handle *properly* formed requests,
which would result in unpredictable behavior.

Additionally, the XenDisk filter wasn't properly responding to
StorageDeviceTrimProperty queries per the MSDN spec. Specifically,
the DEVICE_TRIM_DESCRIPTOR::Version structure member needs to be set
to sizeof(DEVICE_TRIM_DESCRIPTOR).

Signed-off-by: David Buches <davebuch@amazon.com>
src/xendisk/pdo.c
src/xenvbd/pdo.c

index 07f4cfd0ab4ed4d7bd308bbb164f0e37b2f517d4..eaa3e2d17fb44bddad22c7ae7f76ee98dd071ab2 100644 (file)
@@ -401,7 +401,7 @@ PdoQueryProperty(
 
             Trim = Irp->AssociatedIrp.SystemBuffer;
 
-            Trim->Version = 0;
+            Trim->Version = sizeof(DEVICE_TRIM_DESCRIPTOR);
             Trim->Size = sizeof(DEVICE_TRIM_DESCRIPTOR);
             Trim->TrimEnabled = TRUE;
 
@@ -557,8 +557,8 @@ PdoSendTrimSynchronous(
     Cdb->UNMAP.OperationCode = SCSIOP_UNMAP;
     *(PUSHORT)Cdb->UNMAP.AllocationLength = _byteswap_ushort((USHORT)Length);
 
-    *(PUSHORT)Unmap->DataLength = _byteswap_ushort((USHORT)Length);
-    *(PUSHORT)Unmap->BlockDescrDataLength = _byteswap_ushort((USHORT)sizeof(UNMAP_BLOCK_DESCRIPTOR));
+       *(PUSHORT)Unmap->DataLength = _byteswap_ushort((USHORT)(Length - FIELD_OFFSET(UNMAP_LIST_HEADER, BlockDescrDataLength)));
+       *(PUSHORT)Unmap->BlockDescrDataLength = _byteswap_ushort((USHORT)(Length - FIELD_OFFSET(UNMAP_LIST_HEADER, Descriptors[0])));
 
     for (Index = 0; Index < Count; ++Index) {
         PUNMAP_BLOCK_DESCRIPTOR Block = &Unmap->Descriptors[Index];
index 488a74b5cb8b64c1f5c7cc4e4885ea85e9b60bde..67800e47c8eb870bf06472ae38a1563873c52c9b 100644 (file)
@@ -1264,8 +1264,7 @@ PrepareUnmap(
 {
     PXENVBD_SRBEXT      SrbExt = GetSrbExt(Srb);
     PUNMAP_LIST_HEADER  Unmap = Srb->DataBuffer;
-    ULONG               Count = _byteswap_ushort(*(PUSHORT)Unmap->DataLength) /
-                                _byteswap_ushort(*(PUSHORT)Unmap->BlockDescrDataLength);
+       ULONG               Count = _byteswap_ushort(*(PUSHORT)Unmap->BlockDescrDataLength) / sizeof(UNMAP_BLOCK_DESCRIPTOR);
     ULONG               Index;
     LIST_ENTRY          List;