From 9436fd8402c5c8941d272abf3ce8f91ef46615e5 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 6 Sep 2019 20:52:15 -0700 Subject: [PATCH] sys: implement SectorSize queries - IRP_MJ_QUERY_VOLUME_INFORMATION/FileFsSectorSizeInformation - IOCTL_STORAGE_QUERY_PROPERTY/StorageAccessAlignmentProperty --- src/sys/devctl.c | 69 ++++++++++++++++++++++++++++++++++++++++++----- src/sys/driver.h | 2 ++ src/sys/volinfo.c | 40 +++++++++++++++++++++++++-- src/sys/volume.c | 4 +++ 4 files changed, 107 insertions(+), 8 deletions(-) diff --git a/src/sys/devctl.c b/src/sys/devctl.c index 3a153c4e..123a8a26 100644 --- a/src/sys/devctl.c +++ b/src/sys/devctl.c @@ -23,6 +23,9 @@ static NTSTATUS FspFsvrtDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); +static BOOLEAN FspFsvrtDeviceControlStorageQuery( + PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, + PNTSTATUS PResult); static NTSTATUS FspFsvolDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete; @@ -31,6 +34,7 @@ FSP_DRIVER_DISPATCH FspDeviceControl; #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, FspFsvrtDeviceControl) +#pragma alloc_text(PAGE, FspFsvrtDeviceControlStorageQuery) #pragma alloc_text(PAGE, FspFsvolDeviceControl) #pragma alloc_text(PAGE, FspFsvolDeviceControlComplete) #pragma alloc_text(PAGE, FspFsvolDeviceControlRequestFini) @@ -49,6 +53,9 @@ static NTSTATUS FspFsvrtDeviceControl( NTSTATUS Result; + if (FspFsvrtDeviceControlStorageQuery(FsvrtDeviceObject, Irp, IrpSp, &Result)) + return Result; + if (FspMountdevDeviceControl(FsvrtDeviceObject, Irp, IrpSp, &Result)) return Result; @@ -69,6 +76,62 @@ static NTSTATUS FspFsvrtDeviceControl( return STATUS_UNRECOGNIZED_VOLUME; } +static BOOLEAN FspFsvrtDeviceControlStorageQuery( + PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, + PNTSTATUS PResult) +{ + PAGED_CODE(); + + /* + * SQL Server insists on sending us storage level IOCTL's even though + * WinFsp file systems are not on top of a real disk. So bite the bullet + * and implement some of those storage IOCTL's to make SQL Server happy. + */ + + if (IOCTL_STORAGE_QUERY_PROPERTY != IrpSp->Parameters.DeviceIoControl.IoControlCode || + sizeof(STORAGE_PROPERTY_QUERY) > IrpSp->Parameters.DeviceIoControl.InputBufferLength) + return FALSE; + + PSTORAGE_PROPERTY_QUERY Query = Irp->AssociatedIrp.SystemBuffer; + switch (Query->PropertyId) + { + case StorageAccessAlignmentProperty: + if (PropertyExistsQuery == Query->QueryType) + *PResult = STATUS_SUCCESS; + else if (PropertyStandardQuery == Query->QueryType) + { + FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject); + PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR Descriptor = Irp->AssociatedIrp.SystemBuffer; + ULONG OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + if (sizeof(STORAGE_DESCRIPTOR_HEADER) > OutputBufferLength) + *PResult = STATUS_BUFFER_TOO_SMALL; + else if (sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR) > OutputBufferLength) + { + Descriptor->Version = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR); + Descriptor->Size = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR); + Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER); + *PResult = STATUS_SUCCESS; + } + else + { + RtlZeroMemory(Descriptor, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR)); + Descriptor->Version = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR); + Descriptor->Size = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR); + Descriptor->BytesPerLogicalSector = FsvrtDeviceExtension->SectorSize; + Descriptor->BytesPerPhysicalSector = FsvrtDeviceExtension->SectorSize; + Irp->IoStatus.Information = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR); + *PResult = STATUS_SUCCESS; + } + } + else + *PResult = STATUS_NOT_SUPPORTED; + return TRUE; + } + + return FALSE; +} + static NTSTATUS FspFsvolDeviceControl( PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { @@ -79,11 +142,6 @@ static NTSTATUS FspFsvolDeviceControl( ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; NTSTATUS Result; -#if 0 - if (FspMountdevDeviceControl(FsvolDeviceExtension->FsvrtDeviceObject, Irp, IrpSp, &Result)) - return Result; -#endif - /* * Possibly forward the IOCTL request to the user mode file system. The rules are: * @@ -92,7 +150,6 @@ static NTSTATUS FspFsvolDeviceControl( * METHOD_BUFFERED will be forwarded. */ - /* do we support DeviceControl? */ if (!FsvolDeviceExtension->VolumeParams.DeviceControl) return STATUS_INVALID_DEVICE_REQUEST; diff --git a/src/sys/driver.h b/src/sys/driver.h index 01c02bf5..787c87d8 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -27,6 +27,7 @@ #define POOL_NX_OPTIN 1 #include #include +#include #include #include #include @@ -1106,6 +1107,7 @@ typedef struct typedef struct { FSP_DEVICE_EXTENSION Base; + UINT16 SectorSize; LONG IsMountdev; BOOLEAN Persistent; GUID UniqueId; diff --git a/src/sys/volinfo.c b/src/sys/volinfo.c index 5ae2ea1c..62de3be4 100644 --- a/src/sys/volinfo.c +++ b/src/sys/volinfo.c @@ -28,6 +28,9 @@ static NTSTATUS FspFsvolQueryFsDeviceInformation( static NTSTATUS FspFsvolQueryFsFullSizeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); +static NTSTATUS FspFsvolQueryFsSectorSizeInformation( + PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, + const FSP_FSCTL_VOLUME_INFO *VolumeInfo); static NTSTATUS FspFsvolQueryFsSizeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); @@ -50,6 +53,7 @@ FSP_DRIVER_DISPATCH FspSetVolumeInformation; #pragma alloc_text(PAGE, FspFsvolQueryFsAttributeInformation) #pragma alloc_text(PAGE, FspFsvolQueryFsDeviceInformation) #pragma alloc_text(PAGE, FspFsvolQueryFsFullSizeInformation) +#pragma alloc_text(PAGE, FspFsvolQueryFsSectorSizeInformation) #pragma alloc_text(PAGE, FspFsvolQueryFsSizeInformation) #pragma alloc_text(PAGE, FspFsvolQueryFsVolumeInformation) #pragma alloc_text(PAGE, FspFsvolQueryVolumeInformation) @@ -186,6 +190,35 @@ static NTSTATUS FspFsvolQueryFsFullSizeInformation( return STATUS_SUCCESS; } +static NTSTATUS FspFsvolQueryFsSectorSizeInformation( + PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, + const FSP_FSCTL_VOLUME_INFO *VolumeInfo) +{ + PAGED_CODE(); + + if (*PBuffer + sizeof(FILE_FS_SECTOR_SIZE_INFORMATION) > BufferEnd) + return STATUS_BUFFER_TOO_SMALL; + + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); + PFILE_FS_SECTOR_SIZE_INFORMATION Info = (PFILE_FS_SECTOR_SIZE_INFORMATION)*PBuffer; + + Info->LogicalBytesPerSector = + Info->PhysicalBytesPerSectorForAtomicity = + Info->PhysicalBytesPerSectorForPerformance = + Info->FileSystemEffectivePhysicalBytesPerSectorForAtomicity = + FsvolDeviceExtension->VolumeParams.SectorSize; + Info->Flags = + SSINFO_FLAGS_ALIGNED_DEVICE | + SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE | + SSINFO_FLAGS_NO_SEEK_PENALTY; + Info->ByteOffsetForSectorAlignment = 0; + Info->ByteOffsetForPartitionAlignment = 0; + + *PBuffer += sizeof(FILE_FS_SECTOR_SIZE_INFORMATION); + + return STATUS_SUCCESS; +} + static NTSTATUS FspFsvolQueryFsSizeInformation( PDEVICE_OBJECT FsvolDeviceObject, PUINT8 *PBuffer, PUINT8 BufferEnd, const FSP_FSCTL_VOLUME_INFO *VolumeInfo) @@ -255,7 +288,7 @@ static NTSTATUS FspFsvolQueryVolumeInformation( NTSTATUS Result; PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer; - PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryFile.Length; + PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryVolume.Length; switch (IrpSp->Parameters.QueryVolume.FsInformationClass) { @@ -268,6 +301,9 @@ static NTSTATUS FspFsvolQueryVolumeInformation( case FileFsFullSizeInformation: Result = FspFsvolQueryFsFullSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); break; + case FileFsSectorSizeInformation: + Result = FspFsvolQueryFsSectorSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); + break; case FileFsSizeInformation: Result = FspFsvolQueryFsSizeInformation(FsvolDeviceObject, &Buffer, BufferEnd, 0); break; @@ -310,7 +346,7 @@ NTSTATUS FspFsvolQueryVolumeInformationComplete( PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject; PUINT8 Buffer = Irp->AssociatedIrp.SystemBuffer; - PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryFile.Length; + PUINT8 BufferEnd = Buffer + IrpSp->Parameters.QueryVolume.Length; FspFsvolDeviceSetVolumeInfo(FsvolDeviceObject, &Response->Rsp.QueryVolumeInformation.VolumeInfo); diff --git a/src/sys/volume.c b/src/sys/volume.c index d1b02ea2..f17114f2 100644 --- a/src/sys/volume.c +++ b/src/sys/volume.c @@ -281,7 +281,11 @@ static NTSTATUS FspVolumeCreateNoLock( if (NT_SUCCESS(Result)) { if (0 != FsvrtDeviceObject) + { + FspFsvrtDeviceExtension(FsvrtDeviceObject)->SectorSize = + FsvolDeviceExtension->VolumeParams.SectorSize; Result = FspDeviceInitialize(FsvrtDeviceObject); + } } if (!NT_SUCCESS(Result)) {