Index: cc/cacheman.c =================================================================== --- ntoskrnl/cc/cacheman.c (revision 71876) +++ ntoskrnl/cc/cacheman.c (working copy) @@ -14,6 +14,10 @@ #include PFSN_PREFETCHER_GLOBALS CcPfGlobals; +#if CC_PIN_DEBUGGING +extern KGUARDED_MUTEX CcPinnedBcbsMutex; +extern LIST_ENTRY CcPinnedBcbsList; +#endif /* FUNCTIONS *****************************************************************/ @@ -40,6 +44,10 @@ INIT_FUNCTION CcInitializeCacheManager(VOID) { +#if CC_PIN_DEBUGGING + KeInitializeGuardedMutex(&CcPinnedBcbsMutex); + InitializeListHead(&CcPinnedBcbsList); +#endif CcInitView(); return TRUE; } Index: cc/pin.c =================================================================== --- ntoskrnl/cc/pin.c (revision 71883) +++ ntoskrnl/cc/pin.c (working copy) @@ -20,6 +20,11 @@ extern NPAGED_LOOKASIDE_LIST iBcbLookasideList; +#if CC_PIN_DEBUGGING +KGUARDED_MUTEX CcPinnedBcbsMutex; +LIST_ENTRY CcPinnedBcbsList; +#endif + /* FUNCTIONS *****************************************************************/ /* @@ -136,6 +141,10 @@ iBcb->Pinned = FALSE; iBcb->RefCount = 1; ExInitializeResourceLite(&iBcb->Lock); +#if CC_PIN_DEBUGGING + InitializeListHead(&iBcb->PinnedBcbsEntry); + iBcb->LockCount = 0; +#endif *pBcb = (PVOID)iBcb; CCTRACE(CC_API_DEBUG, "FileObject=%p FileOffset=%p Length=%lu Flags=0x%lx -> TRUE Bcb=%p\n", @@ -213,6 +222,29 @@ ExAcquireResourceSharedLite(&iBcb->Lock, TRUE); } +#if CC_PIN_DEBUGGING + KeAcquireGuardedMutex(&CcPinnedBcbsMutex); + if (iBcb->LockCount == 0) + { + InsertTailList(&CcPinnedBcbsList, &iBcb->PinnedBcbsEntry); + RtlZeroMemory(iBcb->Backtrace, sizeof(iBcb->Backtrace)); + RtlCaptureStackBackTrace(0, 16, iBcb->Backtrace, NULL); + } + else + { + PVOID Backtrace[4] = { NULL }; + RtlCaptureStackBackTrace(0, 4, Backtrace, NULL); + DPRINT1("BCB %p pinned multiple times, not keeping track\n", + iBcb); + DPRINT1("Their callers: %p %p %p %p\n", + iBcb->Backtrace[0], iBcb->Backtrace[1], iBcb->Backtrace[2], iBcb->Backtrace[3]); + DPRINT1("Our callers: %p %p %p %p\n", + Backtrace[0], Backtrace[1], Backtrace[2], Backtrace[3]); + } + iBcb->LockCount++; + KeReleaseGuardedMutex(&CcPinnedBcbsMutex); +#endif + return TRUE; } else @@ -278,6 +310,36 @@ CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread()); } +#if CC_PIN_DEBUGGING +VOID +CcDumpPinnedBcbs(VOID) +{ + PLIST_ENTRY Entry; + PINTERNAL_BCB iBcb; + ULONG i; + + KeAcquireGuardedMutex(&CcPinnedBcbsMutex); + Entry = CcPinnedBcbsList.Flink; + while (Entry != &CcPinnedBcbsList) + { + iBcb = CONTAINING_RECORD(Entry, INTERNAL_BCB, PinnedBcbsEntry); + Entry = Entry->Flink; + + DPRINT1("BCB %p held with backtrace:\n", iBcb); + for (i = 0; i < 16; i++) + { + if (iBcb->Backtrace[i] == NULL) + { + break; + } + DPRINT1("%p\n", iBcb->Backtrace[i]); + } + DPRINT1("---end---\n"); + } + KeReleaseGuardedMutex(&CcPinnedBcbsMutex); +} +#endif + /* * @unimplemented */ @@ -293,6 +355,19 @@ if (iBcb->Pinned) { +#if CC_PIN_DEBUGGING + KeAcquireGuardedMutex(&CcPinnedBcbsMutex); + if (iBcb->LockCount == 1) + { + RemoveEntryList(&iBcb->PinnedBcbsEntry); + } + else + { + DPRINT1("Untracked unpin on BCB %p\n", iBcb); + } + iBcb->LockCount--; + KeReleaseGuardedMutex(&CcPinnedBcbsMutex); +#endif ExReleaseResourceForThreadLite(&iBcb->Lock, ResourceThreadId); iBcb->Pinned = FALSE; if (InterlockedDecrement(&iBcb->Vacb->PinCount) == 0) Index: include/internal/cc.h =================================================================== --- ntoskrnl/include/internal/cc.h (revision 71876) +++ ntoskrnl/include/internal/cc.h (working copy) @@ -191,6 +191,7 @@ /* Pointer to the next VACB in a chain. */ } ROS_VACB, *PROS_VACB; +#define CC_PIN_DEBUGGING 1 typedef struct _INTERNAL_BCB { /* Lock */ @@ -200,6 +201,11 @@ BOOLEAN Dirty; BOOLEAN Pinned; CSHORT RefCount; /* (At offset 0x34 on WinNT4) */ +#if CC_PIN_DEBUGGING + ULONG LockCount; + LIST_ENTRY PinnedBcbsEntry; + PVOID Backtrace[16]; +#endif } INTERNAL_BCB, *PINTERNAL_BCB; VOID Index: io/iomgr/irp.c =================================================================== --- ntoskrnl/io/iomgr/irp.c (revision 71876) +++ ntoskrnl/io/iomgr/irp.c (working copy) @@ -1185,6 +1185,8 @@ IoQueueThreadIrp(Irp); } +VOID CcDumpPinnedBcbs(VOID); + /* * @implemented */ @@ -1218,8 +1220,40 @@ StackPtr->DeviceObject = DeviceObject; /* Call it */ +#if DBG + { + KIRQL OldIrql; + PKTHREAD Thread; + ULONG CombinedApcDisable; + NTSTATUS Status; + UCHAR MajorFunction; + + Thread = KeGetCurrentThread(); + OldIrql = KeGetCurrentIrql(); + CombinedApcDisable = Thread->CombinedApcDisable; + MajorFunction = StackPtr->MajorFunction; + + Status = DriverObject->MajorFunction[MajorFunction](DeviceObject, + Irp); + if (KeGetCurrentIrql() != OldIrql || + Thread->CombinedApcDisable != CombinedApcDisable) + { + DPRINT1("Dispatch function %p (major %u) changed IRQL (%u -> %u) or APC state (0x%lx -> 0x%lx)\n", + DriverObject->MajorFunction[MajorFunction], MajorFunction, OldIrql, KeGetCurrentIrql(), CombinedApcDisable, Thread->CombinedApcDisable); + DPRINT1("%wZ: Major: %x, minor: %x\n", &DriverObject->DriverName, StackPtr->MajorFunction, StackPtr->MinorFunction); + if (StackPtr->FileObject) DPRINT1("Involved FN: %wZ\n", &StackPtr->FileObject->FileName); +#if CC_PIN_DEBUGGING + CcDumpPinnedBcbs(); +#endif + NT_ASSERT(KeGetCurrentIrql() == OldIrql); + NT_ASSERT(Thread->CombinedApcDisable == CombinedApcDisable); + } + return Status; + } +#else return DriverObject->MajorFunction[StackPtr->MajorFunction](DeviceObject, Irp); +#endif } FORCEINLINE