mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 17:03:12 -05:00
sys: ioq
This commit is contained in:
parent
694a39db9a
commit
175ba3205a
@ -142,6 +142,7 @@
|
|||||||
<ClCompile Include="..\..\src\sys\fileinfo.c" />
|
<ClCompile Include="..\..\src\sys\fileinfo.c" />
|
||||||
<ClCompile Include="..\..\src\sys\flush.c" />
|
<ClCompile Include="..\..\src\sys\flush.c" />
|
||||||
<ClCompile Include="..\..\src\sys\fsctl.c" />
|
<ClCompile Include="..\..\src\sys\fsctl.c" />
|
||||||
|
<ClCompile Include="..\..\src\sys\ioq.c" />
|
||||||
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
<ClCompile Include="..\..\src\sys\lockctl.c" />
|
||||||
<ClCompile Include="..\..\src\sys\misc.c" />
|
<ClCompile Include="..\..\src\sys\misc.c" />
|
||||||
<ClCompile Include="..\..\src\sys\read.c" />
|
<ClCompile Include="..\..\src\sys\read.c" />
|
||||||
|
@ -74,6 +74,9 @@
|
|||||||
<ClCompile Include="..\..\src\sys\misc.c">
|
<ClCompile Include="..\..\src\sys\misc.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\sys\ioq.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\src\sys\driver.h">
|
<ClInclude Include="..\..\src\sys\driver.h">
|
||||||
|
107
src/sys/driver.h
107
src/sys/driver.h
@ -113,51 +113,6 @@
|
|||||||
#pragma warning(disable:4100) /* unreferenced formal parameter */
|
#pragma warning(disable:4100) /* unreferenced formal parameter */
|
||||||
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
||||||
|
|
||||||
/* types */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
FspFsctlDeviceExtensionKind = 'C', /* file system control device (e.g. \Device\WinFsp.Disk) */
|
|
||||||
FspFsvrtDeviceExtensionKind = 'V', /* virtual volume device (e.g. \Device\Volume{GUID}) */
|
|
||||||
FspFsvolDeviceExtensionKind = 'F', /* file system volume device (unnamed) */
|
|
||||||
};
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
UINT8 Kind;
|
|
||||||
} FSP_DEVICE_EXTENSION;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
FSP_DEVICE_EXTENSION Base;
|
|
||||||
} FSP_FSCTL_DEVICE_EXTENSION;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
FSP_DEVICE_EXTENSION Base;
|
|
||||||
UINT8 SecurityDescriptorBuf[];
|
|
||||||
} FSP_FSVRT_DEVICE_EXTENSION;
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
FSP_DEVICE_EXTENSION Base;
|
|
||||||
} FSP_FSVOL_DEVICE_EXTENSION;
|
|
||||||
static inline
|
|
||||||
FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
|
||||||
{
|
|
||||||
return DeviceObject->DeviceExtension;
|
|
||||||
}
|
|
||||||
static inline
|
|
||||||
FSP_FSCTL_DEVICE_EXTENSION *FspFsctlDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
|
||||||
{
|
|
||||||
return DeviceObject->DeviceExtension;
|
|
||||||
}
|
|
||||||
static inline
|
|
||||||
FSP_FSVRT_DEVICE_EXTENSION *FspFsvrtDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
|
||||||
{
|
|
||||||
return DeviceObject->DeviceExtension;
|
|
||||||
}
|
|
||||||
static inline
|
|
||||||
FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
|
||||||
{
|
|
||||||
return DeviceObject->DeviceExtension;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* driver major functions */
|
/* driver major functions */
|
||||||
DRIVER_DISPATCH FspCleanup;
|
DRIVER_DISPATCH FspCleanup;
|
||||||
DRIVER_DISPATCH FspClose;
|
DRIVER_DISPATCH FspClose;
|
||||||
@ -190,6 +145,68 @@ FAST_IO_RELEASE_FOR_MOD_WRITE FspReleaseForModWrite;
|
|||||||
FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush;
|
FAST_IO_ACQUIRE_FOR_CCFLUSH FspAcquireForCcFlush;
|
||||||
FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
|
FAST_IO_RELEASE_FOR_CCFLUSH FspReleaseForCcFlush;
|
||||||
|
|
||||||
|
/* I/O queue */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
KSPIN_LOCK SpinLock;
|
||||||
|
int Enabled;
|
||||||
|
LIST_ENTRY PendingIrpList, ProcessIrpList;
|
||||||
|
IO_CSQ PendingIoCsq, ProcessIoCsq;
|
||||||
|
} FSP_IOQ;
|
||||||
|
VOID FspIoqInitialize(FSP_IOQ *Ioq);
|
||||||
|
VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta);
|
||||||
|
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||||
|
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq);
|
||||||
|
BOOLEAN FspIoqProcessIrp(FSP_IOQ *Ioq, PIRP Irp);
|
||||||
|
PIRP FspIoqRemoveProcessIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
|
||||||
|
VOID FspIoqCancelAll(FSP_IOQ *Ioq);
|
||||||
|
|
||||||
|
/* device extensions */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FspFsctlDeviceExtensionKind = 'C', /* file system control device (e.g. \Device\WinFsp.Disk) */
|
||||||
|
FspFsvrtDeviceExtensionKind = 'V', /* virtual volume device (e.g. \Device\Volume{GUID}) */
|
||||||
|
FspFsvolDeviceExtensionKind = 'F', /* file system volume device (unnamed) */
|
||||||
|
};
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT8 Kind;
|
||||||
|
} FSP_DEVICE_EXTENSION;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FSP_DEVICE_EXTENSION Base;
|
||||||
|
} FSP_FSCTL_DEVICE_EXTENSION;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FSP_DEVICE_EXTENSION Base;
|
||||||
|
FSP_IOQ Ioq;
|
||||||
|
UINT8 SecurityDescriptorBuf[];
|
||||||
|
} FSP_FSVRT_DEVICE_EXTENSION;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FSP_DEVICE_EXTENSION Base;
|
||||||
|
} FSP_FSVOL_DEVICE_EXTENSION;
|
||||||
|
static inline
|
||||||
|
FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
return DeviceObject->DeviceExtension;
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
FSP_FSCTL_DEVICE_EXTENSION *FspFsctlDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
return DeviceObject->DeviceExtension;
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FspFsvrtDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
return DeviceObject->DeviceExtension;
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
return DeviceObject->DeviceExtension;
|
||||||
|
}
|
||||||
|
|
||||||
/* misc */
|
/* misc */
|
||||||
NTSTATUS CreateGuid(GUID *Guid);
|
NTSTATUS CreateGuid(GUID *Guid);
|
||||||
NTSTATUS SecuritySubjectContextAccessCheck(
|
NTSTATUS SecuritySubjectContextAccessCheck(
|
||||||
|
209
src/sys/ioq.c
Normal file
209
src/sys/ioq.c
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/**
|
||||||
|
* @file sys/ioq.c
|
||||||
|
*
|
||||||
|
* @copyright 2015 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/driver.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An FSP_IOQ encapsulates the main FSP mechanism for handling IRP's.
|
||||||
|
* It has two queues: a "pending" queue for managing newly arrived IRP's
|
||||||
|
* and a "processing" queue for managing IRP's currently being processed
|
||||||
|
* (i.e. sent to the user-mode file system for further processing).
|
||||||
|
*
|
||||||
|
* IRP's arrive at a MajorFunction (MJ) and are then posted to the device's
|
||||||
|
* FSP_IOQ and marked pending. When the user-mode file system performs
|
||||||
|
* FSP_FSCTL_TRANSACT, the IRP's are removed from the pending queue and
|
||||||
|
* are then marshalled to the user process; prior to that they are added
|
||||||
|
* to the processing queue. At a later time the user-mode will perform
|
||||||
|
* another FSP_FSCTL_TRANSACT at which time any processed IRP's will be
|
||||||
|
* marshalled back to us and will be then removed from the processing queue
|
||||||
|
* and completed.
|
||||||
|
*
|
||||||
|
* State diagram:
|
||||||
|
* +--------------------+
|
||||||
|
* | | | ProcessIrp
|
||||||
|
* v | v
|
||||||
|
* +------------+ | +------------+
|
||||||
|
* | MJ | | | Processing |
|
||||||
|
* +------------+ | +------------+
|
||||||
|
* | | |
|
||||||
|
* | PostIrp | | RemoveProcessIrp
|
||||||
|
* v | v
|
||||||
|
* +------------+ | +------------+
|
||||||
|
* | Pending | | | TRANSACT |
|
||||||
|
* +------------+ | | IN |
|
||||||
|
* | | +------------+
|
||||||
|
* | NextPendingIrp | |
|
||||||
|
* v | | CompleteIrp
|
||||||
|
* +------------+ | v
|
||||||
|
* | TRANSACT | | +------------+
|
||||||
|
* | OUT | | | Completed |
|
||||||
|
* +------------+ | +------------+
|
||||||
|
* | |
|
||||||
|
* +---------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
|
||||||
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
|
||||||
|
|
||||||
|
if (0 > Ioq->Enabled)
|
||||||
|
return STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
|
InsertTailList(&Ioq->PendingIrpList, &Irp->Tail.Overlay.ListEntry);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspIoqPendingRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
|
||||||
|
{
|
||||||
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PIRP FspIoqPendingPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext)
|
||||||
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
|
||||||
|
PLIST_ENTRY Head, Entry;
|
||||||
|
|
||||||
|
if (!PeekContext && 0 > Ioq->Enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Head = &Ioq->PendingIrpList;
|
||||||
|
if (0 == Irp)
|
||||||
|
Entry = Head->Flink;
|
||||||
|
else
|
||||||
|
Entry = Irp->Tail.Overlay.ListEntry.Flink;
|
||||||
|
|
||||||
|
return Head != Entry ? CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspIoqPendingAcquireLock(PIO_CSQ IoCsq, PKIRQL Irql)
|
||||||
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
|
||||||
|
KeAcquireSpinLock(&Ioq->SpinLock, Irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspIoqPendingReleaseLock(PIO_CSQ IoCsq, KIRQL Irql)
|
||||||
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, PendingIoCsq);
|
||||||
|
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
|
||||||
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
|
||||||
|
|
||||||
|
if (0 > Ioq->Enabled)
|
||||||
|
return STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
|
InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspIoqProcessRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
|
||||||
|
{
|
||||||
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PIRP FspIoqProcessPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext)
|
||||||
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
|
||||||
|
PLIST_ENTRY Head, Entry;
|
||||||
|
|
||||||
|
if (!PeekContext && 0 > Ioq->Enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Head = &Ioq->ProcessIrpList;
|
||||||
|
if (0 == Irp)
|
||||||
|
Entry = Head->Flink;
|
||||||
|
else
|
||||||
|
Entry = Irp->Tail.Overlay.ListEntry.Flink;
|
||||||
|
|
||||||
|
for (; Head != Entry; Entry = Entry->Flink)
|
||||||
|
{
|
||||||
|
Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
|
||||||
|
if (Irp == PeekContext)
|
||||||
|
return Irp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspIoqProcessAcquireLock(PIO_CSQ IoCsq, PKIRQL Irql)
|
||||||
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
|
||||||
|
KeAcquireSpinLock(&Ioq->SpinLock, Irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspIoqProcessReleaseLock(PIO_CSQ IoCsq, KIRQL Irql)
|
||||||
|
{
|
||||||
|
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
|
||||||
|
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspIoqCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, FSP_IO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspIoqInitialize(FSP_IOQ *Ioq)
|
||||||
|
{
|
||||||
|
RtlZeroMemory(Ioq, sizeof *Ioq);
|
||||||
|
KeInitializeSpinLock(&Ioq->SpinLock);
|
||||||
|
InitializeListHead(&Ioq->PendingIrpList);
|
||||||
|
InitializeListHead(&Ioq->ProcessIrpList);
|
||||||
|
IoCsqInitializeEx(&Ioq->PendingIoCsq,
|
||||||
|
FspIoqPendingInsertIrpEx,
|
||||||
|
FspIoqPendingRemoveIrp,
|
||||||
|
FspIoqPendingPeekNextIrp,
|
||||||
|
FspIoqPendingAcquireLock,
|
||||||
|
FspIoqPendingReleaseLock,
|
||||||
|
FspIoqCompleteCanceledIrp);
|
||||||
|
IoCsqInitializeEx(&Ioq->ProcessIoCsq,
|
||||||
|
FspIoqProcessInsertIrpEx,
|
||||||
|
FspIoqProcessRemoveIrp,
|
||||||
|
FspIoqProcessPeekNextIrp,
|
||||||
|
FspIoqProcessAcquireLock,
|
||||||
|
FspIoqProcessReleaseLock,
|
||||||
|
FspIoqCompleteCanceledIrp);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta)
|
||||||
|
{
|
||||||
|
KIRQL Irql;
|
||||||
|
KeAcquireSpinLock(&Ioq->SpinLock, &Irql);
|
||||||
|
Ioq->Enabled += Delta;
|
||||||
|
KeReleaseSpinLock(&Ioq->SpinLock, Irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp)
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS == IoCsqInsertIrpEx(&Ioq->PendingIoCsq, Irp, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq)
|
||||||
|
{
|
||||||
|
return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)1);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN FspIoqProcessIrp(FSP_IOQ *Ioq, PIRP Irp)
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS == IoCsqInsertIrpEx(&Ioq->ProcessIoCsq, Irp, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
PIRP FspIoqRemoveProcessIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint)
|
||||||
|
{
|
||||||
|
return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)IrpHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspIoqCancelAll(FSP_IOQ *Ioq)
|
||||||
|
{
|
||||||
|
PIRP Irp;
|
||||||
|
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, 0)))
|
||||||
|
FspIoqCompleteCanceledIrp(&Ioq->PendingIoCsq, Irp);
|
||||||
|
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->ProcessIoCsq, 0)))
|
||||||
|
FspIoqCompleteCanceledIrp(&Ioq->ProcessIoCsq, Irp);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user