|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |