https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c5a35ecd3761b9a4dbdc87...
commit c5a35ecd3761b9a4dbdc87c66447b70fb9d4e785 Author: Pierre Schweitzer pierre@reactos.org AuthorDate: Sat Apr 28 09:34:10 2018 +0200 Commit: Pierre Schweitzer pierre@reactos.org CommitDate: Sun Apr 29 12:15:11 2018 +0200
[FASTFAT] Introduce a KDBG extension.
This is a PoC of what it's possible to realize thanks to an already existing hack in ntoskrnl :-). With this extension, on the kdb:> prompt, you're able to type in commands that will be handled by the FastFAT driver and not by the kernel, allowing internal debug, not possible otherwise.
So far, three commands exist: - ?fat.vols: lists all the mounted volumes by FastFAT - ?fat.files: lists all the files on a specific volume (with their attributes) - ?fat.setdbgfile: allows watching on specifics files lifetime
This is obviously only the begin and could be greatly improved.
For instance, this is what allowed to debug CORE-14557 --- drivers/filesystems/fastfat/CMakeLists.txt | 1 + drivers/filesystems/fastfat/cleanup.c | 3 + drivers/filesystems/fastfat/close.c | 3 + drivers/filesystems/fastfat/fcb.c | 70 ++++++++++++- drivers/filesystems/fastfat/iface.c | 28 +++++ drivers/filesystems/fastfat/kdbg.c | 161 +++++++++++++++++++++++++++++ drivers/filesystems/fastfat/vfat.h | 35 ++++++- 7 files changed, 297 insertions(+), 4 deletions(-)
diff --git a/drivers/filesystems/fastfat/CMakeLists.txt b/drivers/filesystems/fastfat/CMakeLists.txt index 087f9e3f62..cc69334b01 100644 --- a/drivers/filesystems/fastfat/CMakeLists.txt +++ b/drivers/filesystems/fastfat/CMakeLists.txt @@ -15,6 +15,7 @@ list(APPEND SOURCE flush.c fsctl.c iface.c + kdbg.c misc.c pnp.c rw.c diff --git a/drivers/filesystems/fastfat/cleanup.c b/drivers/filesystems/fastfat/cleanup.c index 580ed807a3..3ab4a101d1 100644 --- a/drivers/filesystems/fastfat/cleanup.c +++ b/drivers/filesystems/fastfat/cleanup.c @@ -138,6 +138,9 @@ VfatCleanupFile( }
FileObject->Flags |= FO_CLEANUP_COMPLETE; +#ifdef KDBG + pFcb->Flags |= FCB_CLEANED_UP; +#endif
ExReleaseResourceLite(&pFcb->PagingIoResource); ExReleaseResourceLite(&pFcb->MainResource); diff --git a/drivers/filesystems/fastfat/close.c b/drivers/filesystems/fastfat/close.c index b4e5fda308..992ccac4c2 100644 --- a/drivers/filesystems/fastfat/close.c +++ b/drivers/filesystems/fastfat/close.c @@ -48,6 +48,9 @@ VfatCloseFile( } else { +#ifdef KDBG + pFcb->Flags |= FCB_CLOSED; +#endif vfatReleaseFCB(DeviceExt, pFcb); }
diff --git a/drivers/filesystems/fastfat/fcb.c b/drivers/filesystems/fastfat/fcb.c index f6734a675e..33124bc51b 100644 --- a/drivers/filesystems/fastfat/fcb.c +++ b/drivers/filesystems/fastfat/fcb.c @@ -24,6 +24,10 @@
#define TAG_FCB 'BCFV'
+#ifdef KDBG +extern UNICODE_STRING DebugFile; +#endif + /* -------------------------------------------------------- PUBLICS */
static @@ -267,6 +271,13 @@ VOID vfatDestroyFCB( PVFATFCB pFCB) { +#ifdef KDBG + if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL)) + { + DPRINT1("Destroying: %p (%wZ) %d\n", pFCB, &pFCB->PathNameU, pFCB->RefCount); + } +#endif + FsRtlUninitializeFileLock(&pFCB->FileLock); if (!vfatFCBIsRoot(pFCB) && !BooleanFlagOn(pFCB->Flags, FCB_IS_FAT) && !BooleanFlagOn(pFCB->Flags, FCB_IS_VOLUME)) @@ -288,10 +299,28 @@ vfatFCBIsRoot( }
VOID +#ifndef KDBG vfatGrabFCB( +#else +_vfatGrabFCB( +#endif PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB) + PVFATFCB pFCB +#ifdef KDBG + , + PCSTR File, + ULONG Line, + PCSTR Func +#endif +) { +#ifdef KDBG + if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL)) + { + DPRINT1("Inc ref count (%d, oc: %d) for: %p (%wZ) at: %s(%d) %s\n", pFCB->RefCount, pFCB->OpenHandleCount, pFCB, &pFCB->PathNameU, File, Line, Func); + } +#endif + ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
ASSERT(pFCB != pVCB->VolumeFcb); @@ -300,14 +329,32 @@ vfatGrabFCB( }
VOID +#ifndef KDBG vfatReleaseFCB( +#else +_vfatReleaseFCB( +#endif PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB) + PVFATFCB pFCB +#ifdef KDBG + , + PCSTR File, + ULONG Line, + PCSTR Func +#endif +) { PVFATFCB tmpFcb;
+#ifdef KDBG + if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL)) + { + DPRINT1("Dec ref count (%d, oc: %d) for: %p (%wZ) at: %s(%d) %s\n", pFCB->RefCount, pFCB->OpenHandleCount, pFCB, &pFCB->PathNameU, File, Line, Func); + } +#else DPRINT("releasing FCB at %p: %wZ, refCount:%d\n", pFCB, &pFCB->PathNameU, pFCB->RefCount); +#endif
ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
@@ -605,6 +652,13 @@ vfatFCBInitializeCacheFromVolume(
fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
+#ifdef KDBG + if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &fcb->LongNameU, FALSE, NULL)) + { + DPRINT1("Attaching %p to %p (%d)\n", fcb, fileObject, fcb->RefCount); + } +#endif + newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList); if (newCCB == NULL) { @@ -762,6 +816,13 @@ vfatAttachFCBToFileObject(
UNREFERENCED_PARAMETER(vcb);
+#ifdef KDBG + if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &fcb->LongNameU, FALSE, NULL)) + { + DPRINT1("Attaching %p to %p (%d)\n", fcb, fileObject, fcb->RefCount); + } +#endif + newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList); if (newCCB == NULL) { @@ -774,6 +835,11 @@ vfatAttachFCBToFileObject( fileObject->FsContext2 = newCCB; DPRINT("file open: fcb:%p PathName:%wZ\n", fcb, &fcb->PathNameU);
+#ifdef KDBG + fcb->Flags &= ~FCB_CLEANED_UP; + fcb->Flags &= ~FCB_CLOSED; +#endif + return STATUS_SUCCESS; }
diff --git a/drivers/filesystems/fastfat/iface.c b/drivers/filesystems/fastfat/iface.c index 02e570ea45..b73854dbcd 100644 --- a/drivers/filesystems/fastfat/iface.c +++ b/drivers/filesystems/fastfat/iface.c @@ -34,6 +34,24 @@ #pragma alloc_text(INIT, DriverEntry) #endif
+#ifdef KDBG +NTSTATUS +NTAPI +KdSystemDebugControl(IN ULONG Command, + IN PVOID InputBuffer, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer, + IN ULONG OutputBufferLength, + IN OUT PULONG ReturnLength, + IN KPROCESSOR_MODE PreviousMode); + +BOOLEAN +NTAPI +vfatKdbgHandler( + IN PCHAR Command, + IN ULONG Argc, + IN PCH Argv[]); +#endif
/* GLOBALS *****************************************************************/
@@ -137,6 +155,16 @@ DriverEntry( ExInitializeResourceLite(&VfatGlobalData->VolumeListLock); InitializeListHead(&VfatGlobalData->VolumeListHead); IoRegisterFileSystem(DeviceObject); + +#ifdef KDBG + { + BOOLEAN Registered; + + Registered = KdSystemDebugControl('RbdK', vfatKdbgHandler, FALSE, NULL, 0, NULL, KernelMode); + DPRINT1("FastFAT KDBG extension registered: %s\n", (Registered ? "yes" : "no")); + } +#endif + return STATUS_SUCCESS; }
diff --git a/drivers/filesystems/fastfat/kdbg.c b/drivers/filesystems/fastfat/kdbg.c new file mode 100644 index 0000000000..b278329299 --- /dev/null +++ b/drivers/filesystems/fastfat/kdbg.c @@ -0,0 +1,161 @@ +/* +* FILE: drivers/filesystems/fastfat/kdbg.c +* PURPOSE: KDBG extension. +* COPYRIGHT: See COPYING in the top level directory +* PROJECT: ReactOS kernel +* PROGRAMMER: Pierre Schweitzer (pierre@reactos.org) +*/ + +/* ------------------------------------------------------- INCLUDES */ + +#include "vfat.h" + +#define NDEBUG +#include <debug.h> + +#include <stdio.h> + +/* -------------------------------------------------------- DEFINES */ + +#ifdef KDBG +UNICODE_STRING DebugFile = {0, 0, NULL}; + +BOOLEAN +NTAPI +vfatKdbgHandler( + IN PCHAR Command, + IN ULONG Argc, + IN PCH Argv[]) +{ + ULONG Len; + + Len = strlen(Command); + if (Len < sizeof("?fat.")) + { + return FALSE; + } + + if (Command[0] != '?' || Command[1] != 'f' || + Command[2] != 'a' || Command[3] != 't' || + Command[4] != '.') + { + return FALSE; + } + + Command += (sizeof("?fat.") - sizeof(ANSI_NULL)); + if (strcmp(Command, "vols") == 0) + { + ULONG Count = 0; + PLIST_ENTRY ListEntry; + PDEVICE_EXTENSION DeviceExt; + + for (ListEntry = VfatGlobalData->VolumeListHead.Flink; + ListEntry != &VfatGlobalData->VolumeListHead; + ListEntry = ListEntry->Flink) + { + DeviceExt = CONTAINING_RECORD(ListEntry, DEVICE_EXTENSION, VolumeListEntry); + DPRINT1("Volume: %p with VCB: %p\n", DeviceExt->VolumeDevice, DeviceExt); + ++Count; + } + + if (Count == 0) + { + DPRINT1("No volume found\n"); + } + } + else if (strcmp(Command, "files") == 0) + { + if (Argc != 2) + { + DPRINT1("Please provide a volume or a VCB!\n"); + } + else + { + PLIST_ENTRY ListEntry; + PDEVICE_EXTENSION DeviceExt; + + for (ListEntry = VfatGlobalData->VolumeListHead.Flink; + ListEntry != &VfatGlobalData->VolumeListHead; + ListEntry = ListEntry->Flink) + { + CHAR Volume[17]; + + DeviceExt = CONTAINING_RECORD(ListEntry, DEVICE_EXTENSION, VolumeListEntry); + sprintf(Volume, "%p", DeviceExt); + if (strcmp(Volume, Argv[1]) == 0) + { + break; + } + + sprintf(Volume, "%p", DeviceExt->VolumeDevice); + if (strcmp(Volume, Argv[1]) == 0) + { + break; + } + + DeviceExt = NULL; + } + + if (DeviceExt == NULL) + { + DPRINT1("No volume %s found!\n", Argv[1]); + } + else + { + PVFATFCB Fcb; + + for (ListEntry = DeviceExt->FcbListHead.Flink; + ListEntry != &DeviceExt->FcbListHead; + ListEntry = ListEntry->Flink) + { + Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry); + DPRINT1("FCB %p (ref: %d, oc: %d %s %s) for FO %p with path: %.*S\n", + Fcb, Fcb->RefCount, Fcb->OpenHandleCount, + ((Fcb->Flags & FCB_CLEANED_UP) ? "U" : "NU"), + ((Fcb->Flags & FCB_CLOSED) ? "C" : "NC"), + Fcb->FileObject, Fcb->PathNameU.Length, Fcb->PathNameU.Buffer); + } + } + } + } + else if (strcmp(Command, "setdbgfile") == 0) + { + if (Argc < 2) + { + if (DebugFile.Buffer != NULL) + { + ExFreePool(DebugFile.Buffer); + DebugFile.Length = 0; + DebugFile.MaximumLength = 0; + } + + DPRINT1("Debug file reset\n"); + } + else + { + NTSTATUS Status; + ANSI_STRING Source; + + if (DebugFile.Buffer != NULL) + { + ExFreePool(DebugFile.Buffer); + DebugFile.Length = 0; + DebugFile.MaximumLength = 0; + } + + RtlInitAnsiString(&Source, Argv[1]); + Status = RtlAnsiStringToUnicodeString(&DebugFile, &Source, TRUE); + if (NT_SUCCESS(Status)) + { + DPRINT1("Debug file set to: %.*S\n", DebugFile.Length, DebugFile.Buffer); + } + } + } + else + { + DPRINT1("Unknown command: %s\n", Command); + } + + return TRUE; +} +#endif diff --git a/drivers/filesystems/fastfat/vfat.h b/drivers/filesystems/fastfat/vfat.h index 429120c804..0de6a486a0 100644 --- a/drivers/filesystems/fastfat/vfat.h +++ b/drivers/filesystems/fastfat/vfat.h @@ -409,6 +409,10 @@ extern PVFAT_GLOBAL_DATA VfatGlobalData; #define FCB_IS_PAGE_FILE 0x0008 #define FCB_IS_VOLUME 0x0010 #define FCB_IS_DIRTY 0x0020 +#ifdef KDBG +#define FCB_CLEANED_UP 0x0040 +#define FCB_CLOSED 0x0080 +#endif
#define NODE_TYPE_FCB ((CSHORT)0x0502)
@@ -898,14 +902,41 @@ vfatDestroyCCB( PVFATCCB pCcb);
VOID +#ifndef KDBG vfatGrabFCB( +#else +_vfatGrabFCB( +#endif PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB); + PVFATFCB pFCB +#ifdef KDBG + , + PCSTR File, + ULONG Line, + PCSTR Func +#endif + );
VOID +#ifndef KDBG vfatReleaseFCB( +#else +_vfatReleaseFCB( +#endif PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB); + PVFATFCB pFCB +#ifdef KDBG + , + PCSTR File, + ULONG Line, + PCSTR Func +#endif + ); + +#ifdef KDBG +#define vfatGrabFCB(v, f) _vfatGrabFCB(v, f, __FILE__, __LINE__, __FUNCTION__) +#define vfatReleaseFCB(v, f) _vfatReleaseFCB(v, f, __FILE__, __LINE__, __FUNCTION__) +#endif
PVFATFCB vfatGrabFCBFromTable(