sys: FspIopPostWorkRequest()

This commit is contained in:
Bill Zissimopoulos 2015-12-06 23:55:22 -08:00
parent 18025573a3
commit 0fb9de1ebd
8 changed files with 191 additions and 24 deletions

View File

@ -148,6 +148,7 @@
<ClCompile Include="..\..\src\sys\fileobj.c" /> <ClCompile Include="..\..\src\sys\fileobj.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\idevctl.c" />
<ClCompile Include="..\..\src\sys\iop.c" /> <ClCompile Include="..\..\src\sys\iop.c" />
<ClCompile Include="..\..\src\sys\ioq.c" /> <ClCompile Include="..\..\src\sys\ioq.c" />
<ClCompile Include="..\..\src\sys\lockctl.c" /> <ClCompile Include="..\..\src\sys\lockctl.c" />

View File

@ -86,6 +86,9 @@
<ClCompile Include="..\..\src\sys\fileobj.c"> <ClCompile Include="..\..\src\sys\fileobj.c">
<Filter>Source</Filter> <Filter>Source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\sys\idevctl.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\sys\driver.h"> <ClInclude Include="..\..\src\sys\driver.h">

View File

@ -572,16 +572,16 @@ static VOID FspFsvolCreateClose(
/* /*
* This routine handles the case where we must close an open file, * This routine handles the case where we must close an open file,
* because of a failure during Create completion. We simply create * because of a failure during Create completion. We simply create
* a CreateClose request and we post it to our Ioq. * a CreateClose request and we post it as a work item.
* *
* Ideally there would be no failure modes for this routine. Reality is * Ideally there would be no failure modes for this routine. Reality is
* different. * different.
* *
* The more serious (but perhaps non-existent in practice) failure is a * The more serious (but perhaps non-existent in practice) failure is a
* memory allocation failure for the CreateClose request. In this case we * memory allocation failure. In this case we will leak the user-mode
* will leak the user-mode file system handle! * file system handle!
* *
* This routine may also fail if the Ioq was stopped, which means that * This routine may also fail if we cannot post a work item, which means that
* the virtual volume device and the file system volume device are being * the virtual volume device and the file system volume device are being
* deleted. Because it is assumed that only the user-mode file system would * deleted. Because it is assumed that only the user-mode file system would
* initiate a device deletion, this case is more benign (presumably the file * initiate a device deletion, this case is more benign (presumably the file
@ -600,30 +600,29 @@ static VOID FspFsvolCreateClose(
FSP_FSCTL_TRANSACT_REQ *Request; FSP_FSCTL_TRANSACT_REQ *Request;
/* create the user-mode file system request */ /* create the user-mode file system request */
Result = FspIopCreateRequest(Irp, FileNameRequired ? &FsContext->FileName : 0, 0, &Request); Result = FspIopCreateRequest(0, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ goto leak_exit;
DEBUGLOG("FileObject=%p[%p:\"%wZ\"], UserContext=%llx, UserContext2=%p: "
"FspIopCreateRequest failed: the user-mode file system handle will be leaked!",
IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName,
FsContext->UserContext, FileObject->FsContext2);
goto exit;
}
/* populate the Create request */ /* populate the CreateClose request */
Request->Kind = FspFsctlTransactCreateCloseKind; Request->Kind = FspFsctlTransactCreateCloseKind;
Request->Req.Close.UserContext = FsContext->UserContext; Request->Req.Close.UserContext = FsContext->UserContext;
Request->Req.Close.UserContext2 = (UINT_PTR)FileObject->FsContext2; Request->Req.Close.UserContext2 = (UINT_PTR)FileObject->FsContext2;
/* /* post as a work request */
* Post the IRP to our Ioq. if (!FspIopPostWorkRequest(DeviceObject, Request))
*/ /* no need to delete the request here as FspIopPostWorkRequest() will do so in all cases */
if (!FspIoqPostIrp(&FsvrtDeviceExtension->Ioq, Irp)) goto leak_exit;
{
/* this can only happen if the Ioq was stopped */
ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq));
goto exit; goto exit;
}
leak_exit:;
#if DBG
DEBUGLOG("FileObject=%p[%p:\"%wZ\"], UserContext=%llx, UserContext2=%p: "
"error: the user-mode file system handle will be leaked!",
IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName,
FsContext->UserContext, FileObject->FsContext2);
#endif
exit: exit:
FspFileContextDelete(FsContext); FspFileContextDelete(FsContext);

View File

@ -167,6 +167,7 @@ const char *IoctlCodeSym(ULONG ControlCode)
SYM(FSP_FSCTL_CREATE) SYM(FSP_FSCTL_CREATE)
SYM(FSP_FSCTL_DELETE) SYM(FSP_FSCTL_DELETE)
SYM(FSP_FSCTL_TRANSACT) SYM(FSP_FSCTL_TRANSACT)
SYM(FSP_FSCTL_WORK)
default: default:
return "IOCTL:Unknown"; return "IOCTL:Unknown";
} }

View File

@ -56,6 +56,7 @@ NTSTATUS DriverEntry(
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FspDirectoryControl; DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FspDirectoryControl;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFileSystemControl; DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFileSystemControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FspDeviceControl; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FspDeviceControl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = FspInternalDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FspShutdown; DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FspShutdown;
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FspLockControl; DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FspLockControl;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FspCleanup; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FspCleanup;
@ -80,6 +81,7 @@ NTSTATUS DriverEntry(
FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspDirectoryControlComplete; FspIopCompleteFunction[IRP_MJ_DIRECTORY_CONTROL] = FspDirectoryControlComplete;
FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFileSystemControlComplete; FspIopCompleteFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FspFileSystemControlComplete;
FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspDeviceControlComplete; FspIopCompleteFunction[IRP_MJ_DEVICE_CONTROL] = FspDeviceControlComplete;
FspIopCompleteFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = FspFsvolInternalDeviceControlComplete;
FspIopCompleteFunction[IRP_MJ_SHUTDOWN] = FspShutdownComplete; FspIopCompleteFunction[IRP_MJ_SHUTDOWN] = FspShutdownComplete;
FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspLockControlComplete; FspIopCompleteFunction[IRP_MJ_LOCK_CONTROL] = FspLockControlComplete;
FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspCleanupComplete; FspIopCompleteFunction[IRP_MJ_CLEANUP] = FspCleanupComplete;

View File

@ -187,6 +187,7 @@ _Dispatch_type_(IRP_MJ_DEVICE_CONTROL) FSP_DRIVER_DISPATCH FspDeviceControl;
_Dispatch_type_(IRP_MJ_DIRECTORY_CONTROL) FSP_DRIVER_DISPATCH FspDirectoryControl; _Dispatch_type_(IRP_MJ_DIRECTORY_CONTROL) FSP_DRIVER_DISPATCH FspDirectoryControl;
_Dispatch_type_(IRP_MJ_FILE_SYSTEM_CONTROL) FSP_DRIVER_DISPATCH FspFileSystemControl; _Dispatch_type_(IRP_MJ_FILE_SYSTEM_CONTROL) FSP_DRIVER_DISPATCH FspFileSystemControl;
_Dispatch_type_(IRP_MJ_FLUSH_BUFFERS) FSP_DRIVER_DISPATCH FspFlushBuffers; _Dispatch_type_(IRP_MJ_FLUSH_BUFFERS) FSP_DRIVER_DISPATCH FspFlushBuffers;
_Dispatch_type_(IRP_MJ_INTERNAL_DEVICE_CONTROL) FSP_DRIVER_DISPATCH FspInternalDeviceControl;
_Dispatch_type_(IRP_MJ_LOCK_CONTROL) FSP_DRIVER_DISPATCH FspLockControl; _Dispatch_type_(IRP_MJ_LOCK_CONTROL) FSP_DRIVER_DISPATCH FspLockControl;
_Dispatch_type_(IRP_MJ_QUERY_EA) FSP_DRIVER_DISPATCH FspQueryEa; _Dispatch_type_(IRP_MJ_QUERY_EA) FSP_DRIVER_DISPATCH FspQueryEa;
_Dispatch_type_(IRP_MJ_QUERY_INFORMATION) FSP_DRIVER_DISPATCH FspQueryInformation; _Dispatch_type_(IRP_MJ_QUERY_INFORMATION) FSP_DRIVER_DISPATCH FspQueryInformation;
@ -217,6 +218,7 @@ FSP_IOCMPL_DISPATCH FspDeviceControlComplete;
FSP_IOCMPL_DISPATCH FspDirectoryControlComplete; FSP_IOCMPL_DISPATCH FspDirectoryControlComplete;
FSP_IOCMPL_DISPATCH FspFileSystemControlComplete; FSP_IOCMPL_DISPATCH FspFileSystemControlComplete;
FSP_IOCMPL_DISPATCH FspFlushBuffersComplete; FSP_IOCMPL_DISPATCH FspFlushBuffersComplete;
FSP_IOCMPL_DISPATCH FspFsvolInternalDeviceControlComplete;
FSP_IOCMPL_DISPATCH FspLockControlComplete; FSP_IOCMPL_DISPATCH FspLockControlComplete;
FSP_IOCMPL_DISPATCH FspQueryEaComplete; FSP_IOCMPL_DISPATCH FspQueryEaComplete;
FSP_IOCMPL_DISPATCH FspQueryInformationComplete; FSP_IOCMPL_DISPATCH FspQueryInformationComplete;
@ -259,8 +261,11 @@ BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp);
PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint); PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint);
/* I/O processing */ /* I/O processing */
#define FSP_FSCTL_WORK \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'W', METHOD_NEITHER, FILE_ANY_ACCESS)
NTSTATUS FspIopCreateRequest( NTSTATUS FspIopCreateRequest(
PIRP Irp, PUNICODE_STRING FileName, ULONG ExtraSize, FSP_FSCTL_TRANSACT_REQ **PRequest); PIRP Irp, PUNICODE_STRING FileName, ULONG ExtraSize, FSP_FSCTL_TRANSACT_REQ **PRequest);
NTSTATUS FspIopPostWorkRequest(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_TRANSACT_REQ *Request);
VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease); VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease);
static inline static inline
VOID FspIopCompleteIrp(PIRP Irp, NTSTATUS Result) VOID FspIopCompleteIrp(PIRP Irp, NTSTATUS Result)

98
src/sys/idevctl.c Normal file
View File

@ -0,0 +1,98 @@
/**
* @file sys/idevctl.c
*
* @copyright 2015 Bill Zissimopoulos
*/
#include <sys/driver.h>
static NTSTATUS FspFsvolInternalDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOCMPL_DISPATCH FspFsvolInternalDeviceControlComplete;
FSP_DRIVER_DISPATCH FspInternalDeviceControl;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFsvolInternalDeviceControl)
#pragma alloc_text(PAGE, FspFsvolInternalDeviceControlComplete)
#pragma alloc_text(PAGE, FspInternalDeviceControl)
#endif
static NTSTATUS FspFsvolInternalDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
case FSP_FSCTL_WORK:
{
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject);
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
if (!FspDeviceRetain(FsvrtDeviceObject))
return STATUS_CANCELLED;
try
{
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension =
FspFsvrtDeviceExtension(FsvrtDeviceObject);
FSP_FSCTL_TRANSACT_REQ *Request = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
ASSERT(0 == Request->Hint);
/* associate the passed Request with our Irp; acquire ownership of the Request */
Request->Hint = (UINT_PTR)Irp;
Irp->Tail.Overlay.DriverContext[0] = Request;
if (!FspIoqPostIrp(&FsvrtDeviceExtension->Ioq, Irp))
{
/* this can only happen if the Ioq was stopped */
ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq));
/* disocciate the Request from our Irp; release ownership back to caller */
Request->Hint = 0;
Irp->Tail.Overlay.DriverContext[0] = 0;
Result = STATUS_CANCELLED;
goto exit;
}
Result = STATUS_PENDING;
exit:;
}
finally
{
FspDeviceRelease(FsvrtDeviceObject);
}
}
break;
}
return Result;
}
VOID FspFsvolInternalDeviceControlComplete(
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
{
FSP_ENTER_IOC(PAGED_CODE());
FSP_LEAVE_IOC("%s", IoctlCodeSym(IrpSp->Parameters.DeviceIoControl.IoControlCode));
}
NTSTATUS FspInternalDeviceControl(
PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
FSP_ENTER_MJ(PAGED_CODE());
ASSERT(IRP_MJ_INTERNAL_DEVICE_CONTROL == IrpSp->MajorFunction);
switch (FspDeviceExtension(DeviceObject)->Kind)
{
case FspFsvolDeviceExtensionKind:
FSP_RETURN(Result = FspFsvolInternalDeviceControl(DeviceObject, Irp, IrpSp));
default:
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
}
FSP_LEAVE_MJ("%s", IoctlCodeSym(IrpSp->Parameters.DeviceIoControl.IoControlCode));
}

View File

@ -8,11 +8,14 @@
NTSTATUS FspIopCreateRequest( NTSTATUS FspIopCreateRequest(
PIRP Irp, PUNICODE_STRING FileName, ULONG ExtraSize, FSP_FSCTL_TRANSACT_REQ **PRequest); PIRP Irp, PUNICODE_STRING FileName, ULONG ExtraSize, FSP_FSCTL_TRANSACT_REQ **PRequest);
NTSTATUS FspIopPostWorkRequest(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_TRANSACT_REQ *Request);
static IO_COMPLETION_ROUTINE FspIopPostWorkRequestCompletion;
NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request); NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request);
VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspIopCreateRequest) #pragma alloc_text(PAGE, FspIopCreateRequest)
#pragma alloc_text(PAGE, FspIopPostWorkRequest)
#pragma alloc_text(PAGE, FspIopDispatchPrepare) #pragma alloc_text(PAGE, FspIopDispatchPrepare)
#pragma alloc_text(PAGE, FspIopDispatchComplete) #pragma alloc_text(PAGE, FspIopDispatchComplete)
#endif #endif
@ -54,12 +57,67 @@ NTSTATUS FspIopCreateRequest(
Request->FileName.Size = 0; Request->FileName.Size = 0;
} }
if (0 != Irp)
Irp->Tail.Overlay.DriverContext[0] = Request; Irp->Tail.Overlay.DriverContext[0] = Request;
*PRequest = Request; *PRequest = Request;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static inline
VOID FspIopDeleteRequest(FSP_FSCTL_TRANSACT_REQ *Request)
{
ExFreePoolWithTag(Request, FSP_TAG);
}
NTSTATUS FspIopPostWorkRequest(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_TRANSACT_REQ *Request)
{
PAGED_CODE();
ASSERT(0 == Request->Hint);
NTSTATUS Result;
PIRP Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if (0 == Irp)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
PIO_STACK_LOCATION IrpSp = IoGetNextIrpStackLocation(Irp);
IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IrpSp->Parameters.DeviceIoControl.IoControlCode = FSP_FSCTL_WORK;
IrpSp->Parameters.DeviceIoControl.InputBufferLength = Request->Size;
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = Request;
ASSERT(METHOD_NEITHER == (IrpSp->Parameters.DeviceIoControl.IoControlCode & 3));
IoSetCompletionRoutine(Irp, FspIopPostWorkRequestCompletion, 0, TRUE, TRUE, TRUE);
Result = IoCallDriver(DeviceObject, Irp);
if (STATUS_PENDING == Result)
return STATUS_SUCCESS;
/*
* If we did not receive STATUS_PENDING, we still own the Request and must delete it!
*/
exit:
FspIopDeleteRequest(Request);
return Result;
}
static NTSTATUS FspIopPostWorkRequestCompletion(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
// !PAGED_CODE();
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease) VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease)
{ {
// !PAGED_CODE(); // !PAGED_CODE();
@ -69,7 +127,7 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease)
if (0 != Irp->Tail.Overlay.DriverContext[0]) if (0 != Irp->Tail.Overlay.DriverContext[0])
{ {
ExFreePoolWithTag(Irp->Tail.Overlay.DriverContext[0], FSP_TAG); FspIopDeleteRequest(Irp->Tail.Overlay.DriverContext[0]);
Irp->Tail.Overlay.DriverContext[0] = 0; Irp->Tail.Overlay.DriverContext[0] = 0;
} }