[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH] Make use of the 'physical-sector-size' reported by the backend



blkif backends can report a 'physical-sector-size' as will as
'sector-size'. XENVBD currently reads this xenstore key but does
nothing with the value. This patch makes use of the value to set the
LogicalPerPhysicalExponent field in the READ_CAPACITY16_DATA structure
which is populated in response to a SCSIOP_READ_CAPACITY16 CDB.

The patch also modifies XENDISK to discover the logical block size by
sending a SCSIOP_READ_CAPACITY16 rather than relying on an IOCTL to
query StorageAccessAlignmentProperty being sent down the stack and
succeeded by STORPORT (which does not seem to be the case for Windows 10).

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xendisk/pdo.c | 273 ++++++++++++++++++++++++++++++++++--------------------
 src/xenvbd/pdo.c  |  12 ++-
 2 files changed, 183 insertions(+), 102 deletions(-)

diff --git a/src/xendisk/pdo.c b/src/xendisk/pdo.c
index eaa3e2d..d845050 100644
--- a/src/xendisk/pdo.c
+++ b/src/xendisk/pdo.c
@@ -326,104 +326,6 @@ PdoCompleteIrp(
 __drv_functionClass(IO_COMPLETION_ROUTINE)
 __drv_sameIRQL
 static NTSTATUS
-__PdoQueryProperty(
-    IN  PDEVICE_OBJECT  DeviceObject,
-    IN  PIRP            Irp,
-    IN  PVOID           Context
-    )
-{
-    PXENDISK_PDO        Pdo = Context;
-    PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR    Descriptor = Irp->UserBuffer;
-
-    UNREFERENCED_PARAMETER(DeviceObject);
-
-    if (Irp->PendingReturned)
-        IoMarkIrpPending(Irp);
-
-    if (!NT_SUCCESS(Irp->IoStatus.Status))
-        goto done;
-
-    if (Irp->IoStatus.Information != 
(ULONG_PTR)sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR))
-        goto done;
-
-    Descriptor = Irp->AssociatedIrp.SystemBuffer;
-    Pdo->SectorSize = Descriptor->BytesPerLogicalSector;
-    Verbose("%p : %u bytes per sector\n", Pdo->Dx->DeviceObject, 
Pdo->SectorSize);
-
-done:
-    IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
-
-    return STATUS_SUCCESS;
-}
-
-static DECLSPEC_NOINLINE NTSTATUS
-PdoQueryProperty(
-    IN  PXENDISK_PDO        Pdo,
-    IN  PIRP                Irp
-    )
-{
-    PIO_STACK_LOCATION      StackLocation;
-    PSTORAGE_PROPERTY_QUERY Query;
-    NTSTATUS                status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-
-    if (StackLocation->Parameters.DeviceIoControl.InputBufferLength <
-        sizeof (STORAGE_PROPERTY_QUERY))
-        return PdoCompleteIrp(Pdo, Irp, STATUS_INFO_LENGTH_MISMATCH);
-
-    Query = Irp->AssociatedIrp.SystemBuffer;
-
-    switch (Query->PropertyId) {
-    case StorageAccessAlignmentProperty:
-        if (Query->QueryType == PropertyStandardQuery) {
-            IoCopyCurrentIrpStackLocationToNext(Irp);
-            IoSetCompletionRoutine(Irp,
-                                   __PdoQueryProperty,
-                                   Pdo,
-                                   TRUE,
-                                   TRUE,
-                                   TRUE);
-
-            status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
-        } else {
-            status = PdoForwardIrpAndForget(Pdo, Irp);
-        }
-        break;
-
-    case StorageDeviceTrimProperty:
-        if (Query->QueryType == PropertyStandardQuery) {
-            PDEVICE_TRIM_DESCRIPTOR Trim;
-
-            if (StackLocation->Parameters.DeviceIoControl.OutputBufferLength <
-                sizeof (DEVICE_TRIM_DESCRIPTOR))
-                return PdoCompleteIrp(Pdo, Irp, STATUS_BUFFER_OVERFLOW);
-
-            Trim = Irp->AssociatedIrp.SystemBuffer;
-
-            Trim->Version = sizeof(DEVICE_TRIM_DESCRIPTOR);
-            Trim->Size = sizeof(DEVICE_TRIM_DESCRIPTOR);
-            Trim->TrimEnabled = TRUE;
-
-            Irp->IoStatus.Information = 
(ULONG_PTR)sizeof(DEVICE_TRIM_DESCRIPTOR);
-        } else {
-            Irp->IoStatus.Information = 0;
-        }
-
-        status = PdoCompleteIrp(Pdo, Irp, STATUS_SUCCESS);
-        break;
-
-    default:
-        status = PdoForwardIrpAndForget(Pdo, Irp);
-        break;
-    }
-
-    return status;
-}
-
-__drv_functionClass(IO_COMPLETION_ROUTINE)
-__drv_sameIRQL
-static NTSTATUS
 __PdoSendAwaitSrb(
     IN  PDEVICE_OBJECT          DeviceObject,
     IN  PIRP                    Irp,
@@ -488,7 +390,7 @@ PdoSendAwaitSrb(
 
 #pragma warning(disable:6320)
     try {
-        MmProbeAndLockPages(Irp->MdlAddress, KernelMode, IoReadAccess);
+        MmProbeAndLockPages(Irp->MdlAddress, KernelMode, IoWriteAccess);
     } except (EXCEPTION_EXECUTE_HANDLER) {
         status = GetExceptionCode();
 
@@ -523,6 +425,70 @@ fail1:
 }
 
 static NTSTATUS
+PdoSendReadCapacity16Synchronous(
+    IN  PXENDISK_PDO            Pdo,
+    OUT PULONG                  SectorSize
+    )
+{
+    SCSI_REQUEST_BLOCK          Srb;
+    PCDB                        Cdb;
+    PREAD_CAPACITY16_DATA       Capacity;
+    ULONG                       Length;
+    NTSTATUS                    status;
+
+    Trace("====>\n");
+
+    Length = sizeof(READ_CAPACITY16_DATA);
+
+    status = STATUS_NO_MEMORY;
+    Capacity = __PdoAllocate(Length);
+    if (Capacity == NULL)
+        goto fail1;
+
+    RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
+    Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
+    Srb.SrbFlags = 0;
+    Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
+    Srb.DataBuffer = Capacity;
+    Srb.DataTransferLength = Length;
+    Srb.TimeOutValue = (ULONG)-1;
+    Srb.CdbLength = 16;
+
+    Cdb = (PCDB)&Srb.Cdb[0];
+    Cdb->READ_CAPACITY16.OperationCode = SCSIOP_READ_CAPACITY16;
+    Cdb->READ_CAPACITY16.ServiceAction = SERVICE_ACTION_READ_CAPACITY16;
+    *(PULONG)Cdb->READ_CAPACITY16.AllocationLength = _byteswap_ulong(Length);
+
+    status = PdoSendAwaitSrb(Pdo, &Srb);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Srb.DataTransferLength < Length)
+        goto fail3;
+
+    *SectorSize = _byteswap_ulong(Capacity->BytesPerBlock);
+
+    __PdoFree(Capacity);
+
+    Trace("<====\n");
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    __PdoFree(Capacity);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
 PdoSendTrimSynchronous(
     IN  PXENDISK_PDO            Pdo,
     IN  PDEVICE_DATA_SET_RANGE  Ranges,
@@ -594,6 +560,95 @@ fail1:
     return status;
 }
 
+static const CHAR *
+PropertyIdName(
+    IN  STORAGE_PROPERTY_ID Id
+    )
+{
+#define _STORAGE_PROPERTY_NAME(_Id) \
+    case Storage ## _Id:            \
+        return #_Id;
+
+    switch (Id) {
+    _STORAGE_PROPERTY_NAME(DeviceProperty);
+    _STORAGE_PROPERTY_NAME(AdapterProperty);
+    _STORAGE_PROPERTY_NAME(DeviceIdProperty);
+    _STORAGE_PROPERTY_NAME(DeviceUniqueIdProperty);
+    _STORAGE_PROPERTY_NAME(DeviceWriteCacheProperty);
+    _STORAGE_PROPERTY_NAME(MiniportProperty);
+    _STORAGE_PROPERTY_NAME(AccessAlignmentProperty);
+    _STORAGE_PROPERTY_NAME(DeviceSeekPenaltyProperty);
+    _STORAGE_PROPERTY_NAME(DeviceTrimProperty);
+    _STORAGE_PROPERTY_NAME(DeviceWriteAggregationProperty);
+    _STORAGE_PROPERTY_NAME(DeviceDeviceTelemetryProperty);
+    _STORAGE_PROPERTY_NAME(DeviceLBProvisioningProperty);
+    _STORAGE_PROPERTY_NAME(DevicePowerProperty);
+    _STORAGE_PROPERTY_NAME(DeviceCopyOffloadProperty);
+    _STORAGE_PROPERTY_NAME(DeviceResiliencyProperty);
+    _STORAGE_PROPERTY_NAME(DeviceMediumProductType);
+    _STORAGE_PROPERTY_NAME(DeviceTieringProperty);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef _STORAGE_PROPERTY_NAME
+}
+
+static DECLSPEC_NOINLINE NTSTATUS
+PdoQueryProperty(
+    IN  PXENDISK_PDO        Pdo,
+    IN  PIRP                Irp
+    )
+{
+    PIO_STACK_LOCATION      StackLocation;
+    PSTORAGE_PROPERTY_QUERY Query;
+    NTSTATUS                status;
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    if (StackLocation->Parameters.DeviceIoControl.InputBufferLength <
+        sizeof (STORAGE_PROPERTY_QUERY))
+        return PdoCompleteIrp(Pdo, Irp, STATUS_INFO_LENGTH_MISMATCH);
+
+    Query = Irp->AssociatedIrp.SystemBuffer;
+
+    Trace("%s\n", PropertyIdName(Query->PropertyId));
+
+    switch (Query->PropertyId) {
+    case StorageDeviceTrimProperty:
+        if (Query->QueryType == PropertyStandardQuery) {
+            PDEVICE_TRIM_DESCRIPTOR Trim;
+
+            if (StackLocation->Parameters.DeviceIoControl.OutputBufferLength <
+                sizeof (DEVICE_TRIM_DESCRIPTOR))
+                return PdoCompleteIrp(Pdo, Irp, STATUS_BUFFER_OVERFLOW);
+
+            Trim = Irp->AssociatedIrp.SystemBuffer;
+
+            RtlZeroMemory(Trim, sizeof(DEVICE_TRIM_DESCRIPTOR));
+
+            Trim->Version = sizeof(DEVICE_TRIM_DESCRIPTOR);
+            Trim->Size = sizeof(DEVICE_TRIM_DESCRIPTOR);
+            Trim->TrimEnabled = TRUE;
+
+            Irp->IoStatus.Information = sizeof(DEVICE_TRIM_DESCRIPTOR);
+        } else {
+            Irp->IoStatus.Information = 0;
+        }
+
+        status = PdoCompleteIrp(Pdo, Irp, STATUS_SUCCESS);
+        break;
+
+    default:
+        status = PdoForwardIrpAndForget(Pdo, Irp);
+        break;
+    }
+
+    return status;
+}
+
 static DECLSPEC_NOINLINE NTSTATUS
 PdoManageDataSetAttributes(
     IN  PXENDISK_PDO    Pdo,
@@ -677,6 +732,7 @@ PdoStartDevice(
     IN  PIRP            Irp
     )
 {
+    ULONG               SectorSize;
     POWER_STATE         PowerState;
     NTSTATUS            status;
 
@@ -688,6 +744,12 @@ PdoStartDevice(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = PdoSendReadCapacity16Synchronous(Pdo, &SectorSize);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    Pdo->SectorSize = SectorSize;
+
     __PdoSetSystemPowerState(Pdo, PowerSystemWorking);
     __PdoSetDevicePowerState(Pdo, PowerDeviceD0);
 
@@ -705,10 +767,17 @@ PdoStartDevice(
 
     return STATUS_SUCCESS;
 
+fail3:
+    Error("fail3\n");
+
 fail2:
+    Error("fail2\n");
+
     IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
 
 fail1:
+    Error("fail1 (%08x)\n", status);
+
     Irp->IoStatus.Status = status;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
@@ -844,6 +913,8 @@ __PdoStopDevice(
 
     IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
 
+    Pdo->SectorSize = 0;
+
     return STATUS_SUCCESS;
 }
 
@@ -1094,6 +1165,8 @@ done:
     status = PdoForwardIrpSynchronously(Pdo, Irp);
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
+    Pdo->SectorSize = 0;
+
     FdoAcquireMutex(Fdo);
     PdoDestroy(Pdo);
     FdoReleaseMutex(Fdo);
@@ -1965,7 +2038,6 @@ PdoCreate(
     Pdo->Dx = Dx;
     Pdo->PhysicalDeviceObject = PhysicalDeviceObject;
     Pdo->LowerDeviceObject = LowerDeviceObject;
-    Pdo->SectorSize = 512;
 
     status = ThreadCreate(PdoSystemPower, Pdo, &Pdo->SystemPowerThread);
     if (!NT_SUCCESS(status))
@@ -2048,7 +2120,6 @@ PdoDestroy(
     ThreadJoin(Pdo->SystemPowerThread);
     Pdo->SystemPowerThread = NULL;
 
-    Pdo->SectorSize = 0;
     Pdo->PhysicalDeviceObject = NULL;
     Pdo->LowerDeviceObject = NULL;
     Pdo->Dx = NULL;
diff --git a/src/xenvbd/pdo.c b/src/xenvbd/pdo.c
index 269fdfb..7e78ce4 100644
--- a/src/xenvbd/pdo.c
+++ b/src/xenvbd/pdo.c
@@ -1982,10 +1982,13 @@ PdoReadCapacity16(
     __in PSCSI_REQUEST_BLOCK     Srb
     )
 {
-    PREAD_CAPACITY_DATA_EX  Capacity = Srb->DataBuffer;
+    PREAD_CAPACITY16_DATA   Capacity = Srb->DataBuffer;
     PXENVBD_DISKINFO        DiskInfo = FrontendGetDiskInfo(Pdo->Frontend);
     ULONG64                 SectorCount;
     ULONG                   SectorSize;
+    ULONG                   PhysSectorSize;
+    ULONG                   LogicalPerPhysical;
+    ULONG                   LogicalPerPhysicalExponent;
 
     if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0) {
         Srb->ScsiStatus = 0x02; // CHECK_CONDITION
@@ -1994,10 +1997,17 @@ PdoReadCapacity16(
 
     SectorCount = DiskInfo->SectorCount;
     SectorSize = DiskInfo->SectorSize;
+    PhysSectorSize = DiskInfo->PhysSectorSize;
+
+    LogicalPerPhysical = PhysSectorSize / SectorSize;
+
+    if (!_BitScanReverse(&LogicalPerPhysicalExponent, LogicalPerPhysical))
+        LogicalPerPhysicalExponent = 0;
 
     if (Capacity) {
         Capacity->LogicalBlockAddress.QuadPart = _byteswap_uint64(SectorCount 
- 1);
         Capacity->BytesPerBlock = _byteswap_ulong(SectorSize);
+        Capacity->LogicalPerPhysicalExponent = 
(UCHAR)LogicalPerPhysicalExponent;
     }
 
     Srb->SrbStatus = SRB_STATUS_SUCCESS;
-- 
2.5.3


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.