winfsp/src/sys/callbacks.c
Bill Zissimopoulos bd952253fb cosmetic fix
2016-10-11 11:39:17 -07:00

311 lines
8.2 KiB
C

/**
* @file sys/callbacks.c
* Fast I/O and resource acquisition callbacks.
*
* @copyright 2015-2016 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this file in
* accordance with the commercial license agreement provided with the
* software.
*/
#include <sys/driver.h>
FAST_IO_CHECK_IF_POSSIBLE FspFastIoCheckIfPossible;
FAST_IO_ACQUIRE_FILE FspAcquireFileForNtCreateSection;
FAST_IO_RELEASE_FILE FspReleaseFileForNtCreateSection;
FAST_IO_ACQUIRE_FOR_MOD_WRITE FspAcquireForModWrite;
FAST_IO_RELEASE_FOR_MOD_WRITE FspReleaseForModWrite;
FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush;
FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
BOOLEAN FspAcquireForLazyWrite(
PVOID Context,
BOOLEAN Wait);
VOID FspReleaseFromLazyWrite(
PVOID Context);
BOOLEAN FspAcquireForReadAhead(
PVOID Context,
BOOLEAN Wait);
VOID FspReleaseFromReadAhead(
PVOID Context);
VOID FspPropagateTopFlags(PIRP Irp, PIRP TopLevelFlags);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFastIoCheckIfPossible)
#pragma alloc_text(PAGE, FspAcquireFileForNtCreateSection)
#pragma alloc_text(PAGE, FspReleaseFileForNtCreateSection)
#pragma alloc_text(PAGE, FspAcquireForModWrite)
#pragma alloc_text(PAGE, FspReleaseForModWrite)
#pragma alloc_text(PAGE, FspAcquireForCcFlush)
#pragma alloc_text(PAGE, FspReleaseForCcFlush)
#pragma alloc_text(PAGE, FspAcquireForLazyWrite)
#pragma alloc_text(PAGE, FspReleaseFromLazyWrite)
#pragma alloc_text(PAGE, FspAcquireForReadAhead)
#pragma alloc_text(PAGE, FspReleaseFromReadAhead)
#pragma alloc_text(PAGE, FspPropagateTopFlags)
#endif
BOOLEAN FspFastIoCheckIfPossible(
PFILE_OBJECT FileObject,
PLARGE_INTEGER FileOffset,
ULONG Length,
BOOLEAN Wait,
ULONG LockKey,
BOOLEAN CheckForReadOperation,
PIO_STATUS_BLOCK IoStatus,
PDEVICE_OBJECT DeviceObject)
{
FSP_ENTER_BOOL(PAGED_CODE());
Result = FALSE;
FSP_LEAVE_BOOL("FileObject=%p", FileObject);
}
VOID FspAcquireFileForNtCreateSection(
PFILE_OBJECT FileObject)
{
/* Callers:
* CcWriteBehind
*/
FSP_ENTER_VOID(PAGED_CODE());
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FspFileNodeAcquireExclusive(FileNode, Full);
FSP_LEAVE_VOID("FileObject=%p", FileObject);
}
VOID FspReleaseFileForNtCreateSection(
PFILE_OBJECT FileObject)
{
/* Callers:
* CcWriteBehind
*/
FSP_ENTER_VOID(PAGED_CODE());
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FspFileNodeRelease(FileNode, Full);
FSP_LEAVE_VOID("FileObject=%p", FileObject);
}
NTSTATUS FspAcquireForModWrite(
PFILE_OBJECT FileObject,
PLARGE_INTEGER EndingOffset,
PERESOURCE *ResourceToRelease,
PDEVICE_OBJECT DeviceObject)
{
FSP_ENTER(PAGED_CODE());
FSP_FILE_NODE *FileNode = FileObject->FsContext;
BOOLEAN Success;
ASSERT((PIRP)FSRTL_MOD_WRITE_TOP_LEVEL_IRP == IoGetTopLevelIrp());
Success = FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, FALSE);
if (Success)
{
*ResourceToRelease = 0 == FileNode->MainFileNode ?
FileNode->Header.PagingIoResource :
FileNode->MainFileNode->Header.PagingIoResource;
Result = STATUS_SUCCESS;
}
else
{
*ResourceToRelease = 0;
Result = STATUS_CANT_WAIT;
}
FSP_LEAVE("FileObject=%p", FileObject);
}
NTSTATUS FspReleaseForModWrite(
PFILE_OBJECT FileObject,
PERESOURCE ResourceToRelease,
PDEVICE_OBJECT DeviceObject)
{
FSP_ENTER(PAGED_CODE());
FSP_FILE_NODE *FileNode = FileObject->FsContext;
FspFileNodeRelease(FileNode, Full);
ASSERT((PIRP)FSRTL_MOD_WRITE_TOP_LEVEL_IRP == IoGetTopLevelIrp());
FSP_LEAVE("FileObject=%p", FileObject);
}
NTSTATUS FspAcquireForCcFlush(
PFILE_OBJECT FileObject,
PDEVICE_OBJECT DeviceObject)
{
FSP_ENTER(PAGED_CODE());
FSP_FILE_NODE *FileNode = FileObject->FsContext;
PIRP TopLevelIrp = IoGetTopLevelIrp();
ULONG TopFlags;
if ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG >= TopLevelIrp)
{
FspFileNodeAcquireExclusive(FileNode, Full);
ASSERT(0 == FileNode->Tls.CcFlush.TopLevelIrp);
FileNode->Tls.CcFlush.TopLevelIrp = TopLevelIrp;
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
}
else
{
TopFlags = FspIrpTopFlags(TopLevelIrp);
FspIrpSetTopFlags(TopLevelIrp, FspIrpFlags(TopLevelIrp));
FspFileNodeAcquireExclusive(FileNode, Full);
ASSERT(0 == FileNode->Tls.CcFlush.TopFlags);
FileNode->Tls.CcFlush.TopFlags = TopFlags;
}
FSP_LEAVE("FileObject=%p", FileObject);
}
NTSTATUS FspReleaseForCcFlush(
PFILE_OBJECT FileObject,
PDEVICE_OBJECT DeviceObject)
{
FSP_ENTER(PAGED_CODE());
FSP_FILE_NODE *FileNode = FileObject->FsContext;
PIRP TopLevelIrp = IoGetTopLevelIrp();
ULONG TopFlags;
if ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG >= TopLevelIrp)
{
ASSERT(0 == TopLevelIrp || (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == TopLevelIrp);
if ((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == TopLevelIrp)
IoSetTopLevelIrp(FileNode->Tls.CcFlush.TopLevelIrp);
FileNode->Tls.CcFlush.TopLevelIrp = 0;
FspFileNodeRelease(FileNode, Full);
}
else
{
TopFlags = FileNode->Tls.CcFlush.TopFlags;
FileNode->Tls.CcFlush.TopFlags = 0;
FspFileNodeRelease(FileNode, Full);
FspIrpSetTopFlags(TopLevelIrp, TopFlags);
}
FSP_LEAVE("FileObject=%p", FileObject);
}
BOOLEAN FspAcquireForLazyWrite(
PVOID Context,
BOOLEAN Wait)
{
/* Callers:
* CcWriteBehind
*/
FSP_ENTER_BOOL(PAGED_CODE());
FSP_FILE_NODE *FileNode = Context;
ASSERT(0 == IoGetTopLevelIrp());
Result = FspFileNodeTryAcquireExclusiveF(FileNode, FspFileNodeAcquireFull, Wait);
if (Result)
{
ASSERT(0 == FileNode->Tls.LazyWriteThread);
FileNode->Tls.LazyWriteThread = PsGetCurrentThread();
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
}
FSP_LEAVE_BOOL("Context=%p, Wait=%d", Context, Wait);
}
VOID FspReleaseFromLazyWrite(
PVOID Context)
{
/* Callers:
* CcWriteBehind
*/
FSP_ENTER_VOID(PAGED_CODE());
FSP_FILE_NODE *FileNode = Context;
ASSERT((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == IoGetTopLevelIrp());
ASSERT(PsGetCurrentThread() == FileNode->Tls.LazyWriteThread);
IoSetTopLevelIrp(0);
FileNode->Tls.LazyWriteThread = 0;
FspFileNodeRelease(FileNode, Full);
FSP_LEAVE_VOID("Context=%p", Context);
}
BOOLEAN FspAcquireForReadAhead(
PVOID Context,
BOOLEAN Wait)
{
FSP_ENTER_BOOL(PAGED_CODE());
FSP_FILE_NODE *FileNode = Context;
ASSERT(0 == IoGetTopLevelIrp());
Result = FspFileNodeTryAcquireSharedF(FileNode, FspFileNodeAcquireFull, Wait);
if (Result)
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
FSP_LEAVE_BOOL("Context=%p, Wait=%d", Context, Wait);
}
VOID FspReleaseFromReadAhead(
PVOID Context)
{
FSP_ENTER_VOID(PAGED_CODE());
FSP_FILE_NODE *FileNode = Context;
ASSERT((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP == IoGetTopLevelIrp());
IoSetTopLevelIrp(0);
FspFileNodeRelease(FileNode, Full);
FSP_LEAVE_VOID("Context=%p", Context);
}
VOID FspPropagateTopFlags(PIRP Irp, PIRP TopLevelIrp)
{
/*
* We place FspPropagateTopFlags in this file, because the top flags
* are related to the resources acquired in FspAcquire*.
*/
PAGED_CODE();
ASSERT(0 != Irp && 0 != TopLevelIrp);
if ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG >= TopLevelIrp)
{
DEBUGBREAK_EX(iorecu);
FspIrpSetTopFlags(Irp, FspFileNodeAcquireFull);
}
else if (IO_TYPE_IRP == TopLevelIrp->Type)
{
PFILE_OBJECT FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
PFILE_OBJECT TopLevelFileObject = IoGetCurrentIrpStackLocation(TopLevelIrp)->FileObject;
if (0 != FileObject && 0 != TopLevelFileObject &&
FileObject->FsContext == TopLevelFileObject->FsContext &&
FspFileNodeIsValid(FileObject->FsContext))
{
DEBUGBREAK_EX(iorecu);
FspIrpSetTopFlags(Irp, FspIrpFlags(TopLevelIrp));
}
}
}