sys: TopLevelIrp functionality

This commit is contained in:
Bill Zissimopoulos 2016-03-02 12:19:48 -08:00
parent 5b4dd2bb26
commit 498af95e3b
4 changed files with 118 additions and 12 deletions

View File

@ -124,16 +124,26 @@ extern __declspec(selectany) int fsp_bp = 1;
#define FSP_ENTER_MJ(...) \ #define FSP_ENTER_MJ(...) \
NTSTATUS Result = STATUS_SUCCESS; \ NTSTATUS Result = STATUS_SUCCESS; \
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);\ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);\
BOOLEAN fsp_device_deref = FALSE; \ BOOLEAN fsp_device_deref = FALSE; \
PIRP fsp_top_level_irp = IoGetTopLevelIrp();\
FSP_ENTER_(__VA_ARGS__); \ FSP_ENTER_(__VA_ARGS__); \
do \ do \
{ \ { \
if (0 != fsp_top_level_irp) \
{ \
if (FSRTL_MAX_TOP_LEVEL_IRP_FLAG < (UINT_PTR)fsp_top_level_irp &&\
IO_TYPE_IRP == fsp_top_level_irp->Type)\
FspIrpSetTopFlags(Irp, FspIrpFlags(fsp_top_level_irp));\
else \
FspIrpSetTopFlags(Irp, FspFileNodeAcquireFull);\
} \
IoSetTopLevelIrp(Irp); \
if (!FspDeviceReference(IrpSp->DeviceObject))\ if (!FspDeviceReference(IrpSp->DeviceObject))\
{ \ { \
Result = STATUS_CANCELLED; \ Result = STATUS_CANCELLED; \
goto fsp_leave_label; \ goto fsp_leave_label; \
} \ } \
fsp_device_deref = TRUE; \ fsp_device_deref = TRUE; \
} while (0,0) } while (0,0)
#define FSP_LEAVE_MJ(fmt, ...) \ #define FSP_LEAVE_MJ(fmt, ...) \
FSP_LEAVE_( \ FSP_LEAVE_( \
@ -164,6 +174,7 @@ extern __declspec(selectany) int fsp_bp = 1;
else \ else \
FspIopCompleteIrpEx(Irp, Result, fsp_device_deref);\ FspIopCompleteIrpEx(Irp, Result, fsp_device_deref);\
} \ } \
IoSetTopLevelIrp(fsp_top_level_irp);\
); \ ); \
return Result return Result
#define FSP_ENTER_IOC(...) \ #define FSP_ENTER_IOC(...) \
@ -404,8 +415,42 @@ VOID FspQueueDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem, LARGE_INTEG
(*(ULONG *)&(Irp)->Tail.Overlay.DriverContext[0]) (*(ULONG *)&(Irp)->Tail.Overlay.DriverContext[0])
#define FspIrpDictNext(Irp) \ #define FspIrpDictNext(Irp) \
(*(PIRP *)&(Irp)->Tail.Overlay.DriverContext[1]) (*(PIRP *)&(Irp)->Tail.Overlay.DriverContext[1])
#define FspIrpRequest(Irp) \ static inline
(*(FSP_FSCTL_TRANSACT_REQ **)&(Irp)->Tail.Overlay.DriverContext[2]) FSP_FSCTL_TRANSACT_REQ *FspIrpRequest(PIRP Irp)
{
return (PVOID)((UINT_PTR)Irp->Tail.Overlay.DriverContext[2] & ~0xf);
}
static inline
VOID FspIrpSetRequest(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request)
{
ASSERT(0 == ((UINT_PTR)Request & 0xf));
ULONG Flags = (ULONG)((UINT_PTR)Irp->Tail.Overlay.DriverContext[2] & 0xf);
Irp->Tail.Overlay.DriverContext[2] = (PVOID)((UINT_PTR)Request | Flags);
}
static inline
ULONG FspIrpFlags(PIRP Irp)
{
return (ULONG)((UINT_PTR)Irp->Tail.Overlay.DriverContext[2] & 3);
}
static inline
VOID FspIrpSetFlags(PIRP Irp, ULONG Flags)
{
ASSERT(3 > Flags);
FSP_FSCTL_TRANSACT_REQ *Request = (PVOID)((UINT_PTR)Irp->Tail.Overlay.DriverContext[2] & ~3);
Irp->Tail.Overlay.DriverContext[2] = (PVOID)((UINT_PTR)Request | Flags);
}
static inline
ULONG FspIrpTopFlags(PIRP Irp)
{
return (ULONG)((UINT_PTR)Irp->Tail.Overlay.DriverContext[2] & 0xc) >> 2;
}
static inline
VOID FspIrpSetTopFlags(PIRP Irp, ULONG Flags)
{
ASSERT(3 > Flags);
FSP_FSCTL_TRANSACT_REQ *Request = (PVOID)((UINT_PTR)Irp->Tail.Overlay.DriverContext[2] & ~0xc);
Irp->Tail.Overlay.DriverContext[2] = (PVOID)((UINT_PTR)Request | (Flags << 2));
}
/* I/O queue */ /* I/O queue */
#define FspIoqTimeout ((PIRP)1) #define FspIoqTimeout ((PIRP)1)

View File

@ -58,6 +58,18 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc);
#pragma alloc_text(PAGE, FspFileDescDelete) #pragma alloc_text(PAGE, FspFileDescDelete)
#endif #endif
#define FSP_FILE_NODE_GET_FLAGS() \
PIRP Irp = IoGetTopLevelIrp(); \
BOOLEAN IrpValid = FSRTL_MAX_TOP_LEVEL_IRP_FLAG < (UINT_PTR)Irp && IO_TYPE_IRP == Irp->Type;\
if (IrpValid) \
Flags &= ~FspIrpTopFlags(Irp);
#define FSP_FILE_NODE_SET_FLAGS() \
if (IrpValid) \
FspIrpSetFlags(Irp, FspIrpFlags(Irp) | Flags);
#define FSP_FILE_NODE_CLR_FLAGS() \
if (IrpValid) \
FspIrpSetFlags(Irp, FspIrpFlags(Irp) & (~Flags & 3));
NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
ULONG ExtraSize, FSP_FILE_NODE **PFileNode) ULONG ExtraSize, FSP_FILE_NODE **PFileNode)
{ {
@ -128,18 +140,24 @@ VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags)
{ {
PAGED_CODE(); PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
if (Flags & FspFileNodeAcquireMain) if (Flags & FspFileNodeAcquireMain)
ExAcquireResourceSharedLite(FileNode->Header.Resource, TRUE); ExAcquireResourceSharedLite(FileNode->Header.Resource, TRUE);
if (Flags & FspFileNodeAcquirePgio) if (Flags & FspFileNodeAcquirePgio)
ExAcquireResourceSharedLite(FileNode->Header.PagingIoResource, TRUE); ExAcquireResourceSharedLite(FileNode->Header.PagingIoResource, TRUE);
FSP_FILE_NODE_SET_FLAGS();
} }
BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLEAN Wait) BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLEAN Wait)
{ {
PAGED_CODE(); PAGED_CODE();
BOOLEAN Result = FALSE; FSP_FILE_NODE_GET_FLAGS();
BOOLEAN Result = TRUE;
if (Flags & FspFileNodeAcquireMain) if (Flags & FspFileNodeAcquireMain)
{ {
@ -159,6 +177,9 @@ BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLE
} }
} }
if (Result)
FSP_FILE_NODE_SET_FLAGS();
return Result; return Result;
} }
@ -166,18 +187,24 @@ VOID FspFileNodeAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags)
{ {
PAGED_CODE(); PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
if (Flags & FspFileNodeAcquireMain) if (Flags & FspFileNodeAcquireMain)
ExAcquireResourceExclusiveLite(FileNode->Header.Resource, TRUE); ExAcquireResourceExclusiveLite(FileNode->Header.Resource, TRUE);
if (Flags & FspFileNodeAcquirePgio) if (Flags & FspFileNodeAcquirePgio)
ExAcquireResourceExclusiveLite(FileNode->Header.PagingIoResource, TRUE); ExAcquireResourceExclusiveLite(FileNode->Header.PagingIoResource, TRUE);
FSP_FILE_NODE_SET_FLAGS();
} }
BOOLEAN FspFileNodeTryAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLEAN Wait) BOOLEAN FspFileNodeTryAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLEAN Wait)
{ {
PAGED_CODE(); PAGED_CODE();
BOOLEAN Result = FALSE; FSP_FILE_NODE_GET_FLAGS();
BOOLEAN Result = TRUE;
if (Flags & FspFileNodeAcquireMain) if (Flags & FspFileNodeAcquireMain)
{ {
@ -197,6 +224,9 @@ BOOLEAN FspFileNodeTryAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags, BO
} }
} }
if (Result)
FSP_FILE_NODE_SET_FLAGS();
return Result; return Result;
} }
@ -204,6 +234,8 @@ VOID FspFileNodeSetOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
{ {
PAGED_CODE(); PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
Owner = (PVOID)((UINT_PTR)Owner | 3); Owner = (PVOID)((UINT_PTR)Owner | 3);
if (Flags & FspFileNodeAcquireMain) if (Flags & FspFileNodeAcquireMain)
@ -217,17 +249,23 @@ VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags)
{ {
PAGED_CODE(); PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
if (Flags & FspFileNodeAcquirePgio) if (Flags & FspFileNodeAcquirePgio)
ExReleaseResourceLite(FileNode->Header.PagingIoResource); ExReleaseResourceLite(FileNode->Header.PagingIoResource);
if (Flags & FspFileNodeAcquireMain) if (Flags & FspFileNodeAcquireMain)
ExReleaseResourceLite(FileNode->Header.Resource); ExReleaseResourceLite(FileNode->Header.Resource);
FSP_FILE_NODE_CLR_FLAGS();
} }
VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner) VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
{ {
PAGED_CODE(); PAGED_CODE();
FSP_FILE_NODE_GET_FLAGS();
Owner = (PVOID)((UINT_PTR)Owner | 3); Owner = (PVOID)((UINT_PTR)Owner | 3);
if (Flags & FspFileNodeAcquirePgio) if (Flags & FspFileNodeAcquirePgio)
@ -245,6 +283,8 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
else else
ExReleaseResourceForThreadLite(FileNode->Header.Resource, (ERESOURCE_THREAD)Owner); ExReleaseResourceForThreadLite(FileNode->Header.Resource, (ERESOURCE_THREAD)Owner);
} }
FSP_FILE_NODE_CLR_FLAGS();
} }
FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,

View File

@ -38,6 +38,13 @@ NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response
#pragma alloc_text(PAGE, FspIopDispatchComplete) #pragma alloc_text(PAGE, FspIopDispatchComplete)
#endif #endif
/* Requests (and RequestHeaders) must be 16-byte aligned, because we use the low 4 bits for flags */
#if 16 != MEMORY_ALLOCATION_ALIGNMENT
#define REQ_HEADER_ALIGNMASK 15
#else
#define REQ_HEADER_ALIGNMASK 0
#endif
typedef struct typedef struct
{ {
FSP_IOP_REQUEST_FINI *RequestFini; FSP_IOP_REQUEST_FINI *RequestFini;
@ -66,18 +73,22 @@ NTSTATUS FspIopCreateRequestFunnel(
if (FlagOn(Flags, FspIopRequestMustSucceed)) if (FlagOn(Flags, FspIopRequestMustSucceed))
RequestHeader = FspAllocatePoolMustSucceed( RequestHeader = FspAllocatePoolMustSucceed(
FlagOn(Flags, FspIopRequestNonPaged) ? NonPagedPool : PagedPool, FlagOn(Flags, FspIopRequestNonPaged) ? NonPagedPool : PagedPool,
sizeof *RequestHeader + sizeof *Request + ExtraSize, sizeof *RequestHeader + sizeof *Request + ExtraSize + REQ_HEADER_ALIGNMASK,
FSP_ALLOC_INTERNAL_TAG); FSP_ALLOC_INTERNAL_TAG);
else else
{ {
RequestHeader = ExAllocatePoolWithTag( RequestHeader = ExAllocatePoolWithTag(
FlagOn(Flags, FspIopRequestNonPaged) ? NonPagedPool : PagedPool, FlagOn(Flags, FspIopRequestNonPaged) ? NonPagedPool : PagedPool,
sizeof *RequestHeader + sizeof *Request + ExtraSize, sizeof *RequestHeader + sizeof *Request + ExtraSize + REQ_HEADER_ALIGNMASK,
FSP_ALLOC_INTERNAL_TAG); FSP_ALLOC_INTERNAL_TAG);
if (0 == RequestHeader) if (0 == RequestHeader)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
#if 0 != REQ_HEADER_ALIGNMASK
RequestHeader = (PVOID)(((UINT_PTR)RequestHeader + REQ_HEADER_ALIGNMASK) & REQ_HEADER_ALIGNMASK);
#endif
RtlZeroMemory(RequestHeader, sizeof *RequestHeader + sizeof *Request + ExtraSize); RtlZeroMemory(RequestHeader, sizeof *RequestHeader + sizeof *Request + ExtraSize);
RequestHeader->RequestFini = RequestFini; RequestHeader->RequestFini = RequestFini;
@ -94,7 +105,7 @@ NTSTATUS FspIopCreateRequestFunnel(
} }
if (0 != Irp) if (0 != Irp)
FspIrpRequest(Irp) = Request; FspIrpSetRequest(Irp, Request);
*PRequest = Request; *PRequest = Request;
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -206,7 +217,7 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference)
if (0 != FspIrpRequest(Irp)) if (0 != FspIrpRequest(Irp))
{ {
FspIopDeleteRequest(FspIrpRequest(Irp)); FspIopDeleteRequest(FspIrpRequest(Irp));
FspIrpRequest(Irp) = 0; FspIrpSetRequest(Irp, 0);
} }
/* get the device object out of the IRP before completion */ /* get the device object out of the IRP before completion */
@ -227,7 +238,12 @@ VOID FspIopCompleteCanceledIrp(PIRP Irp)
DEBUGLOGIRP(Irp, STATUS_CANCELLED); DEBUGLOGIRP(Irp, STATUS_CANCELLED);
PIRP TopLevelIrp = IoGetTopLevelIrp();
IoSetTopLevelIrp(Irp);
FspIopCompleteIrpEx(Irp, STATUS_CANCELLED, TRUE); FspIopCompleteIrpEx(Irp, STATUS_CANCELLED, TRUE);
IoSetTopLevelIrp(TopLevelIrp);
} }
BOOLEAN FspIopRetryPrepareIrp(PIRP Irp, NTSTATUS *PResult) BOOLEAN FspIopRetryPrepareIrp(PIRP Irp, NTSTATUS *PResult)

View File

@ -534,6 +534,7 @@ NTSTATUS FspVolumeTransact(
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest; FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
PIRP ProcessIrp, PendingIrp, RetriedIrp, RepostedIrp; PIRP ProcessIrp, PendingIrp, RetriedIrp, RepostedIrp;
LARGE_INTEGER Timeout; LARGE_INTEGER Timeout;
PIRP TopLevelIrp = IoGetTopLevelIrp();
/* process any user-mode file system responses */ /* process any user-mode file system responses */
RepostedIrp = 0; RepostedIrp = 0;
@ -557,6 +558,7 @@ NTSTATUS FspVolumeTransact(
ASSERT((UINT_PTR)ProcessIrp == (UINT_PTR)Response->Hint); ASSERT((UINT_PTR)ProcessIrp == (UINT_PTR)Response->Hint);
ASSERT(FspIrpRequest(ProcessIrp)->Hint == Response->Hint); ASSERT(FspIrpRequest(ProcessIrp)->Hint == Response->Hint);
IoSetTopLevelIrp(ProcessIrp);
Result = FspIopDispatchComplete(ProcessIrp, Response); Result = FspIopDispatchComplete(ProcessIrp, Response);
if (STATUS_PENDING == Result) if (STATUS_PENDING == Result)
{ {
@ -579,6 +581,7 @@ NTSTATUS FspVolumeTransact(
if (0 == RetriedIrp) if (0 == RetriedIrp)
break; break;
IoSetTopLevelIrp(RetriedIrp);
Response = FspIopIrpResponse(RetriedIrp); Response = FspIopIrpResponse(RetriedIrp);
Result = FspIopDispatchComplete(RetriedIrp, Response); Result = FspIopDispatchComplete(RetriedIrp, Response);
if (STATUS_PENDING == Result) if (STATUS_PENDING == Result)
@ -642,6 +645,7 @@ NTSTATUS FspVolumeTransact(
{ {
PendingIrpRequest = FspIrpRequest(PendingIrp); PendingIrpRequest = FspIrpRequest(PendingIrp);
IoSetTopLevelIrp(PendingIrp);
Result = FspIopDispatchPrepare(PendingIrp, PendingIrpRequest); Result = FspIopDispatchPrepare(PendingIrp, PendingIrpRequest);
if (STATUS_PENDING == Result) if (STATUS_PENDING == Result)
{ {
@ -692,6 +696,7 @@ NTSTATUS FspVolumeTransact(
Result = STATUS_SUCCESS; Result = STATUS_SUCCESS;
exit: exit:
IoSetTopLevelIrp(TopLevelIrp);
FspDeviceDereference(FsvolDeviceObject); FspDeviceDereference(FsvolDeviceObject);
return Result; return Result;
} }
@ -737,7 +742,7 @@ NTSTATUS FspVolumeWork(
/* associate the passed Request with our Irp; acquire ownership of the Request */ /* associate the passed Request with our Irp; acquire ownership of the Request */
Request->Hint = (UINT_PTR)Irp; Request->Hint = (UINT_PTR)Irp;
FspIrpRequest(Irp) = Request; FspIrpSetRequest(Irp, Request);
/* /*
* Post the IRP to our Ioq; we do this here instead of at FSP_LEAVE_MJ time, * Post the IRP to our Ioq; we do this here instead of at FSP_LEAVE_MJ time,
@ -747,7 +752,7 @@ NTSTATUS FspVolumeWork(
if (!FspIoqPostIrpEx(FsvolDeviceExtension->Ioq, Irp, BestEffort, &Result)) if (!FspIoqPostIrpEx(FsvolDeviceExtension->Ioq, Irp, BestEffort, &Result))
{ {
Request->Hint = 0; Request->Hint = 0;
FspIrpRequest(Irp) = 0; FspIrpSetRequest(Irp, 0);
} }
DEBUGLOG("%s(Irp=%p) = %s", DEBUGLOG("%s(Irp=%p) = %s",