From e6ab31a0e09a1fe404c653fa6a7a706f2480a1cb Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Sat, 2 Apr 2016 11:38:24 -0700 Subject: [PATCH] sys: IRP_MJ_FLUSH_BUFFERS --- inc/winfsp/fsctl.h | 5 +++ inc/winfsp/winfsp.h | 5 +++ src/dll/dispatch.c | 3 +- src/dll/fsop.c | 10 ++++++ src/sys/driver.h | 2 ++ src/sys/flush.c | 72 ++++++++++++++++++++++++++++++++++++-- src/sys/util.c | 26 ++++++++++++++ tst/winfsp-tests/memfs.cpp | 9 +++++ 8 files changed, 128 insertions(+), 4 deletions(-) diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index b796807b..28a6798b 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -246,6 +246,11 @@ typedef struct } Info; } SetInformation; struct + { + UINT64 UserContext; + UINT64 UserContext2; + } FlushBuffers; + struct { UINT32 FsInformationClass; union diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index dfe5b239..c2e4c7b7 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -72,6 +72,9 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE FSP_FSCTL_TRANSACT_REQ *Request, PVOID FileNode, PVOID Buffer, UINT64 Offset, ULONG Length, BOOLEAN WriteToEndOfFile, PULONG PBytesTransferred, FSP_FSCTL_FILE_INFO *FileInfo); + NTSTATUS (*Flush)(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, + PVOID FileNode); NTSTATUS (*GetFileInfo)(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PVOID FileNode, @@ -196,6 +199,8 @@ FSP_API NTSTATUS FspFileSystemOpQueryInformation(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); FSP_API NTSTATUS FspFileSystemOpSetInformation(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); +FSP_API NTSTATUS FspFileSystemOpFlushBuffers(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); FSP_API NTSTATUS FspFileSystemOpQueryVolumeInformation(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); FSP_API NTSTATUS FspFileSystemOpSetVolumeInformation(FSP_FILE_SYSTEM *FileSystem, diff --git a/src/dll/dispatch.c b/src/dll/dispatch.c index 37f85339..3179dbe3 100644 --- a/src/dll/dispatch.c +++ b/src/dll/dispatch.c @@ -46,14 +46,15 @@ FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath, FileSystem->Operations[FspFsctlTransactCloseKind] = FspFileSystemOpClose; FileSystem->Operations[FspFsctlTransactReadKind] = FspFileSystemOpRead; FileSystem->Operations[FspFsctlTransactWriteKind] = FspFileSystemOpWrite; - // !!!: ... FileSystem->Operations[FspFsctlTransactQueryInformationKind] = FspFileSystemOpQueryInformation; FileSystem->Operations[FspFsctlTransactSetInformationKind] = FspFileSystemOpSetInformation; + FileSystem->Operations[FspFsctlTransactFlushBuffersKind] = FspFileSystemOpFlushBuffers; FileSystem->Operations[FspFsctlTransactQueryVolumeInformationKind] = FspFileSystemOpQueryVolumeInformation; FileSystem->Operations[FspFsctlTransactSetVolumeInformationKind] = FspFileSystemOpSetVolumeInformation; FileSystem->Operations[FspFsctlTransactQueryDirectoryKind] = FspFileSystemOpQueryDirectory; FileSystem->Operations[FspFsctlTransactQuerySecurityKind] = FspFileSystemOpQuerySecurity; FileSystem->Operations[FspFsctlTransactSetSecurityKind] = FspFileSystemOpSetSecurity; + // !!!: ... FileSystem->Interface = Interface; *PFileSystem = FileSystem; diff --git a/src/dll/fsop.c b/src/dll/fsop.c index 1cd4d1eb..a806be84 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -463,6 +463,16 @@ FSP_API NTSTATUS FspFileSystemOpWrite(FSP_FILE_SYSTEM *FileSystem, return Result; } +FSP_API NTSTATUS FspFileSystemOpFlushBuffers(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) +{ + if (0 == FileSystem->Interface->Flush) + return STATUS_SUCCESS; /* liar! */ + + return FileSystem->Interface->Flush(FileSystem, Request, + (PVOID)Request->Req.FlushBuffers.UserContext); +} + FSP_API NTSTATUS FspFileSystemOpQueryInformation(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) { diff --git a/src/sys/driver.h b/src/sys/driver.h index ff925b67..122dc04b 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -408,6 +408,8 @@ NTSTATUS FspCcMdlReadComplete(PFILE_OBJECT FileObject, PMDL MdlChain); NTSTATUS FspCcPrepareMdlWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus); NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain); +NTSTATUS FspCcFlushCache(PSECTION_OBJECT_POINTERS SectionObjectPointer, + PLARGE_INTEGER FileOffset, ULONG Length, PIO_STATUS_BLOCK IoStatus); NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength, PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor); diff --git a/src/sys/flush.c b/src/sys/flush.c index 51cd2a12..267176b4 100644 --- a/src/sys/flush.c +++ b/src/sys/flush.c @@ -9,20 +9,74 @@ static NTSTATUS FspFsvolFlushBuffers( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_IOCMPL_DISPATCH FspFsvolFlushBuffersComplete; +static FSP_IOP_REQUEST_FINI FspFsvolFlushBuffersRequestFini; FSP_DRIVER_DISPATCH FspFlushBuffers; #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, FspFsvolFlushBuffers) #pragma alloc_text(PAGE, FspFsvolFlushBuffersComplete) +#pragma alloc_text(PAGE, FspFsvolFlushBuffersRequestFini) #pragma alloc_text(PAGE, FspFlushBuffers) #endif +enum +{ + /* FlushBuffers */ + RequestFileNode = 0, +}; + static NTSTATUS FspFsvolFlushBuffers( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PAGED_CODE(); - return STATUS_INVALID_DEVICE_REQUEST; + NTSTATUS Result; + FSP_FSCTL_TRANSACT_REQ *Request; + + /* is this a valid FileObject? */ + if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext)) + { + /* indicate that we are flushing the whole volume! */ + Result = FspIopCreateRequest(Irp, 0, 0, &Request); + if (!NT_SUCCESS(Result)) + return Result; + + Request->Kind = FspFsctlTransactFlushBuffersKind; + + return FSP_STATUS_IOQ_POST; + } + + PFILE_OBJECT FileObject = IrpSp->FileObject; + FSP_FILE_NODE *FileNode = FileObject->FsContext; + FSP_FILE_DESC *FileDesc = FileObject->FsContext2; + IO_STATUS_BLOCK IoStatus; + + ASSERT(FileNode == FileDesc->FileNode); + + FspFileNodeAcquireExclusive(FileNode, Full); + + Result = FspCcFlushCache(FileObject->SectionObjectPointer, 0, 0, &IoStatus); + if (!NT_SUCCESS(Result)) + { + FspFileNodeRelease(FileNode, Full); + return Result; + } + + Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolFlushBuffersRequestFini, &Request); + if (!NT_SUCCESS(Result)) + { + FspFileNodeRelease(FileNode, Full); + return Result; + } + + Request->Kind = FspFsctlTransactFlushBuffersKind; + Request->Req.FlushBuffers.UserContext = FileNode->UserContext; + Request->Req.FlushBuffers.UserContext2 = FileDesc->UserContext2; + + FspFileNodeSetOwner(FileNode, Full, Request); + FspIopRequestContext(Request, RequestFileNode) = FileNode; + + return FSP_STATUS_IOQ_POST; } NTSTATUS FspFsvolFlushBuffersComplete( @@ -30,7 +84,18 @@ NTSTATUS FspFsvolFlushBuffersComplete( { FSP_ENTER_IOC(PAGED_CODE()); - FSP_LEAVE_IOC("%s", ""); + FSP_LEAVE_IOC("FileObject=%p", + IrpSp->FileObject); +} + +static VOID FspFsvolFlushBuffersRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) +{ + PAGED_CODE(); + + FSP_FILE_NODE *FileNode = Context[RequestFileNode]; + + if (0 != FileNode) + FspFileNodeReleaseOwner(FileNode, Full, Request); } NTSTATUS FspFlushBuffers( @@ -46,5 +111,6 @@ NTSTATUS FspFlushBuffers( FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST); } - FSP_LEAVE_MJ("%s", ""); + FSP_LEAVE_MJ("FileObject=%p", + IrpSp->FileObject); } diff --git a/src/sys/util.c b/src/sys/util.c index cef5c1de..76dee9a2 100644 --- a/src/sys/util.c +++ b/src/sys/util.c @@ -29,6 +29,8 @@ NTSTATUS FspCcMdlReadComplete(PFILE_OBJECT FileObject, PMDL MdlChain); NTSTATUS FspCcPrepareMdlWrite(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, PMDL *PMdlChain, PIO_STATUS_BLOCK IoStatus); NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain); +NTSTATUS FspCcFlushCache(PSECTION_OBJECT_POINTERS SectionObjectPointer, + PLARGE_INTEGER FileOffset, ULONG Length, PIO_STATUS_BLOCK IoStatus); NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength, PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor); @@ -83,6 +85,7 @@ VOID FspSafeMdlDelete(FSP_SAFE_MDL *SafeMdl); #pragma alloc_text(PAGE, FspCcMdlReadComplete) #pragma alloc_text(PAGE, FspCcPrepareMdlWrite) #pragma alloc_text(PAGE, FspCcMdlWriteComplete) +#pragma alloc_text(PAGE, FspCcFlushCache) #pragma alloc_text(PAGE, FspQuerySecurityDescriptorInfo) #pragma alloc_text(PAGE, FspNotifyInitializeSync) #pragma alloc_text(PAGE, FspNotifyFullChangeDirectory) @@ -528,6 +531,29 @@ NTSTATUS FspCcMdlWriteComplete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffse } } +NTSTATUS FspCcFlushCache(PSECTION_OBJECT_POINTERS SectionObjectPointer, + PLARGE_INTEGER FileOffset, ULONG Length, PIO_STATUS_BLOCK IoStatus) +{ + PAGED_CODE(); + + NTSTATUS Result; + + try + { + CcFlushCache(SectionObjectPointer, FileOffset, Length, IoStatus); + Result = IoStatus->Status; + } + except (EXCEPTION_EXECUTE_HANDLER) + { + Result = GetExceptionCode(); + + IoStatus->Information = 0; + IoStatus->Status = Result; + } + + return Result; +} + NTSTATUS FspQuerySecurityDescriptorInfo(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor, PULONG PLength, PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor) diff --git a/tst/winfsp-tests/memfs.cpp b/tst/winfsp-tests/memfs.cpp index 974e330c..2623d4fa 100644 --- a/tst/winfsp-tests/memfs.cpp +++ b/tst/winfsp-tests/memfs.cpp @@ -501,6 +501,14 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem, return STATUS_SUCCESS; } +NTSTATUS Flush(FSP_FILE_SYSTEM *FileSystem, + FSP_FSCTL_TRANSACT_REQ *Request, + PVOID FileNode) +{ + /* nothing to do, since we do not cache anything */ + return STATUS_SUCCESS; +} + static NTSTATUS GetFileInfo(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, PVOID FileNode0, @@ -802,6 +810,7 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface = Close, Read, Write, + Flush, GetFileInfo, SetBasicInfo, SetAllocationSize,