mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 17:32:57 -05:00
sys: IRP_MJ_FLUSH_BUFFERS: flush volume implementation
This commit is contained in:
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user