[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 |