mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-24 01:13:04 -05:00
sys: IRP_MJ_FLUSH_BUFFERS: flush volume implementation
This commit is contained in:
parent
71c1469b46
commit
83c59a6f37
@ -40,6 +40,9 @@ VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
|
||||
static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareContext;
|
||||
static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateContext;
|
||||
static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeContext;
|
||||
NTSTATUS FspFsvolDeviceCopyContextByNameList(PDEVICE_OBJECT DeviceObject,
|
||||
PVOID **PContexts, PULONG PContextCount);
|
||||
VOID FspFsvolDeviceDeleteContextByNameList(PVOID *Contexts, ULONG ContextCount);
|
||||
PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName,
|
||||
BOOLEAN SubpathOnly, PVOID *PRestartKey);
|
||||
PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName);
|
||||
@ -79,6 +82,8 @@ VOID FspDeviceDeleteAll(VOID);
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceCompareContext)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceAllocateContext)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFreeContext)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextByNameList)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceDeleteContextByNameList)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceEnumerateContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceLookupContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceInsertContextByName)
|
||||
@ -653,6 +658,45 @@ static VOID NTAPI FspFsvolDeviceFreeContext(
|
||||
PAGED_CODE();
|
||||
}
|
||||
|
||||
NTSTATUS FspFsvolDeviceCopyContextByNameList(PDEVICE_OBJECT DeviceObject,
|
||||
PVOID **PContexts, PULONG PContextCount)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
|
||||
FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT_DATA *Data;
|
||||
PVOID *Contexts;
|
||||
ULONG ContextCount, Index;
|
||||
|
||||
*PContexts = 0;
|
||||
*PContextCount = 0;
|
||||
|
||||
ContextCount = RtlNumberGenericTableElementsAvl(&FsvolDeviceExtension->ContextByNameTable);
|
||||
Contexts = FspAlloc(sizeof(PVOID) * ContextCount);
|
||||
if (0 == Contexts)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
Index = 0;
|
||||
Data = RtlEnumerateGenericTableAvl(&FsvolDeviceExtension->ContextByNameTable, TRUE);
|
||||
while (Index < ContextCount && 0 != Data)
|
||||
{
|
||||
Contexts[Index++] = Data->Context;
|
||||
Data = RtlEnumerateGenericTableAvl(&FsvolDeviceExtension->ContextByNameTable, FALSE);
|
||||
}
|
||||
|
||||
*PContexts = Contexts;
|
||||
*PContextCount = Index;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID FspFsvolDeviceDeleteContextByNameList(PVOID *Contexts, ULONG ContextCount)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FspFree(Contexts);
|
||||
}
|
||||
|
||||
PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName,
|
||||
BOOLEAN SubpathOnly, PVOID *PRestartKey)
|
||||
{
|
||||
@ -668,7 +712,7 @@ PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE
|
||||
|
||||
Result = RtlEnumerateGenericTableLikeADirectory(&FsvolDeviceExtension->ContextByNameTable,
|
||||
0, 0, SubpathOnly, PRestartKey, &DeleteCount, &FileName);
|
||||
|
||||
|
||||
if (0 != Result &&
|
||||
RtlPrefixUnicodeString(FileName, Result->FileName, CaseInsensitive) &&
|
||||
FileName->Length < Result->FileName->Length &&
|
||||
|
@ -764,6 +764,9 @@ PVOID FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier
|
||||
FSP_DEVICE_CONTEXT_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted);
|
||||
VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier,
|
||||
PBOOLEAN PDeleted);
|
||||
NTSTATUS FspFsvolDeviceCopyContextByNameList(PDEVICE_OBJECT DeviceObject,
|
||||
PVOID **PContexts, PULONG PContextCount);
|
||||
VOID FspFsvolDeviceDeleteContextByNameList(PVOID *Contexts, ULONG ContextCount);
|
||||
PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName,
|
||||
BOOLEAN SubpathOnly, PVOID *PRestartKey);
|
||||
PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName);
|
||||
@ -881,6 +884,9 @@ typedef struct
|
||||
UINT64 DirInfo;
|
||||
ULONG DirInfoCacheHint;
|
||||
} FSP_FILE_DESC;
|
||||
NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject,
|
||||
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount);
|
||||
VOID FspFileNodeDeleteList(FSP_FILE_NODE **FileNodes, ULONG FileNodeCount);
|
||||
NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
|
||||
ULONG ExtraSize, FSP_FILE_NODE **PFileNode);
|
||||
VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode);
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
#include <sys/driver.h>
|
||||
|
||||
NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject,
|
||||
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount);
|
||||
VOID FspFileNodeDeleteList(FSP_FILE_NODE **FileNodes, ULONG FileNodeCount);
|
||||
NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
|
||||
ULONG ExtraSize, FSP_FILE_NODE **PFileNode);
|
||||
VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode);
|
||||
@ -51,6 +54,8 @@ NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
||||
PUNICODE_STRING FileName, BOOLEAN Reset);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspFileNodeCopyList)
|
||||
#pragma alloc_text(PAGE, FspFileNodeDeleteList)
|
||||
#pragma alloc_text(PAGE, FspFileNodeCreate)
|
||||
#pragma alloc_text(PAGE, FspFileNodeDelete)
|
||||
#pragma alloc_text(PAGE, FspFileNodeAcquireSharedF)
|
||||
@ -102,6 +107,38 @@ NTSTATUS FspFileDescResetDirectoryPattern(FSP_FILE_DESC *FileDesc,
|
||||
if (IrpValid) \
|
||||
FspIrpSetFlags(Irp, FspIrpFlags(Irp) & (~Flags & 3))
|
||||
|
||||
NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject,
|
||||
FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
ULONG Index;
|
||||
|
||||
FspFsvolDeviceLockContextTable(DeviceObject);
|
||||
Result = FspFsvolDeviceCopyContextByNameList(DeviceObject, PFileNodes, PFileNodeCount);
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
for (Index = 0; *PFileNodeCount > Index; Index++)
|
||||
FspFileNodeReference((*PFileNodes)[Index]);
|
||||
}
|
||||
FspFsvolDeviceUnlockContextTable(DeviceObject);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID FspFileNodeDeleteList(FSP_FILE_NODE **FileNodes, ULONG FileNodeCount)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ULONG Index;
|
||||
|
||||
for (Index = 0; FileNodeCount > Index; Index++)
|
||||
FspFileNodeDereference(FileNodes[Index]);
|
||||
|
||||
FspFsvolDeviceDeleteContextByNameList(FileNodes, FileNodeCount);
|
||||
}
|
||||
|
||||
NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
|
||||
ULONG ExtraSize, FSP_FILE_NODE **PFileNode)
|
||||
{
|
||||
|
121
src/sys/flush.c
121
src/sys/flush.c
@ -7,7 +7,7 @@
|
||||
#include <sys/driver.h>
|
||||
|
||||
static NTSTATUS FspFsvolFlushBuffers(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
FSP_IOCMPL_DISPATCH FspFsvolFlushBuffersComplete;
|
||||
static FSP_IOP_REQUEST_FINI FspFsvolFlushBuffersRequestFini;
|
||||
FSP_DRIVER_DISPATCH FspFlushBuffers;
|
||||
@ -23,60 +23,98 @@ enum
|
||||
{
|
||||
/* FlushBuffers */
|
||||
RequestFileNode = 0,
|
||||
RequestFlushResult = 1,
|
||||
};
|
||||
|
||||
static NTSTATUS FspFsvolFlushBuffers(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
NTSTATUS Result, FlushResult;
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||
FSP_FILE_NODE **FileNodes;
|
||||
ULONG FileNodeCount, Index;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
|
||||
/* is this a valid FileObject? */
|
||||
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
|
||||
/*
|
||||
* A flush request on the volume (or the root directory according to FastFat)
|
||||
* is a request to flush the whole volume.
|
||||
*/
|
||||
if (!FspFileNodeIsValid(FileNode) || FileNode->IsRootDirectory)
|
||||
{
|
||||
/* indicate that we are flushing the whole volume! */
|
||||
Result = FspFileNodeCopyList(FsvolDeviceObject, &FileNodes, &FileNodeCount);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
/*
|
||||
* Enumerate in reverse order so that files are flushed before containing directories.
|
||||
* This would be useful if we ever started flushing directories, but since we do not
|
||||
* it is not as important now.
|
||||
*/
|
||||
FlushResult = STATUS_SUCCESS;
|
||||
for (Index = FileNodeCount - 1; FileNodeCount > Index; Index--)
|
||||
if (!FileNodes[Index]->IsDirectory)
|
||||
{
|
||||
Result = FspCcFlushCache(&FileNodes[Index]->NonPaged->SectionObjectPointers,
|
||||
0, 0, &IoStatus);
|
||||
if (!NT_SUCCESS(Result) && NT_SUCCESS(FlushResult))
|
||||
FlushResult = Result;
|
||||
}
|
||||
|
||||
FspFileNodeDeleteList(FileNodes, FileNodeCount);
|
||||
|
||||
Result = FspIopCreateRequest(Irp, 0, 0, &Request);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
/* a NULL UserContext indicates to user-mode to flush the whole volume! */
|
||||
Request->Kind = FspFsctlTransactFlushBuffersKind;
|
||||
//Request->Req.FlushBuffers.UserContext = 0;
|
||||
//Request->Req.FlushBuffers.UserContext2 = 0;
|
||||
|
||||
FspIopRequestContext(Request, RequestFileNode) = 0;
|
||||
FspIopRequestContext(Request, RequestFlushResult) = (PVOID)(UINT_PTR)FlushResult;
|
||||
|
||||
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))
|
||||
else
|
||||
{
|
||||
FspFileNodeRelease(FileNode, Full);
|
||||
return Result;
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
/* cannot really flush directories but we will say we did it! */
|
||||
if (FileNode->IsDirectory)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
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;
|
||||
FspIopRequestContext(Request, RequestFlushResult) = 0;
|
||||
|
||||
return FSP_STATUS_IOQ_POST;
|
||||
}
|
||||
|
||||
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(
|
||||
@ -84,6 +122,17 @@ NTSTATUS FspFsvolFlushBuffersComplete(
|
||||
{
|
||||
FSP_ENTER_IOC(PAGED_CODE());
|
||||
|
||||
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||
NTSTATUS FlushResult = (NTSTATUS)(UINT_PTR)FspIopRequestContext(Request, RequestFlushResult);
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
Result = Response->IoStatus.Status;
|
||||
else if (!NT_SUCCESS(FlushResult))
|
||||
Result = FlushResult;
|
||||
else
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
FSP_LEAVE_IOC("FileObject=%p",
|
||||
IrpSp->FileObject);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user