384 lines
9.6 KiB
C
384 lines
9.6 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
rxdebug.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements functions supporting read/write tracking for help in
|
|||
|
tracking down data corruption problems.
|
|||
|
|
|||
|
Currently it is only implemented for files that are created of drive
|
|||
|
letter X:. For each file that is created there are three additional bitmaps
|
|||
|
are created. The first one marks the ranges of fileoffset, length for which
|
|||
|
write were submitted to rdbss. The second bitmap marks the ranges of the
|
|||
|
file for which write requests were passed onto the mini redirector
|
|||
|
(initiation of Lowio). The third bitmap marks the ranges for which the I/O
|
|||
|
was successfully completed.
|
|||
|
|
|||
|
Each bit map kas 8k bits long enough to accomodate files upto ( 8K * PAGE_SIZE)
|
|||
|
bytes. The FCB contains a pointer to this data structure. The data structure
|
|||
|
is independent of FCB's and a new one is created everytime a new FCB instance
|
|||
|
is created.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Balan Sethu Raman --
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
#include <ntddnfs2.h>
|
|||
|
#include <ntddmup.h>
|
|||
|
#ifdef RDBSSLOG
|
|||
|
#include <stdio.h>
|
|||
|
#endif
|
|||
|
|
|||
|
VOID
|
|||
|
RxInitializeDebugSupport()
|
|||
|
{
|
|||
|
#ifdef RX_WJ_DBG_SUPPORT
|
|||
|
RxdInitializeWriteJournalSupport();
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
RxTearDownDebugSupport()
|
|||
|
{
|
|||
|
#ifdef RX_WJ_DBG_SUPPORT
|
|||
|
RxdTearDownWriteJournalSupport();
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
#ifdef RX_WJ_DBG_SUPPORT
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, RxdInitializeWriteJournalSupport)
|
|||
|
#pragma alloc_text(PAGE, RxdTearDownWriteJournalSupport)
|
|||
|
#pragma alloc_text(PAGE, RxdInitializeFcbWriteJournalDebugSupport)
|
|||
|
#pragma alloc_text(PAGE, RxdTearDownFcbWriteJournalDebugSupport)
|
|||
|
#pragma alloc_text(PAGE, RxdUpdateJournalOnWriteInitiation)
|
|||
|
#pragma alloc_text(PAGE, RxdUpdateJournalOnLowIoWriteInitiation)
|
|||
|
#pragma alloc_text(PAGE, RxdUpdateJournalOnLowIoWriteCompletion)
|
|||
|
#pragma alloc_text(PAGE, RxdFindWriteJournal)
|
|||
|
#pragma alloc_text(PAGE, UpdateBitmap)
|
|||
|
#endif
|
|||
|
|
|||
|
LIST_ENTRY OldWriteJournals;
|
|||
|
LIST_ENTRY ActiveWriteJournals;
|
|||
|
ERESOURCE WriteJournalsResource;
|
|||
|
|
|||
|
extern VOID
|
|||
|
UpdateBitmap(
|
|||
|
PBYTE pBitmap,
|
|||
|
LARGE_INTEGER Offset,
|
|||
|
ULONG Length);
|
|||
|
|
|||
|
extern PFCB_WRITE_JOURNAL
|
|||
|
RxdFindWriteJournal(
|
|||
|
PFCB pFcb);
|
|||
|
|
|||
|
VOID
|
|||
|
RxdInitializeWriteJournalSupport()
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
InitializeListHead(&ActiveWriteJournals);
|
|||
|
InitializeListHead(&OldWriteJournals);
|
|||
|
|
|||
|
ExInitializeResource(&WriteJournalsResource);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
RxdTearDownWriteJournalSupport()
|
|||
|
{
|
|||
|
PLIST_ENTRY pJournalEntry;
|
|||
|
|
|||
|
PFCB_WRITE_JOURNAL pJournal;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
ExAcquireResourceExclusive(&WriteJournalsResource,TRUE);
|
|||
|
|
|||
|
while (ActiveWriteJournals.Flink != &ActiveWriteJournals) {
|
|||
|
pJournalEntry = RemoveHeadList(&ActiveWriteJournals);
|
|||
|
|
|||
|
pJournal = (PFCB_WRITE_JOURNAL)
|
|||
|
CONTAINING_RECORD(
|
|||
|
pJournalEntry,
|
|||
|
FCB_WRITE_JOURNAL,
|
|||
|
JournalsList);
|
|||
|
|
|||
|
RxFreePool(pJournal);
|
|||
|
}
|
|||
|
|
|||
|
while (OldWriteJournals.Flink != &OldWriteJournals) {
|
|||
|
pJournalEntry = RemoveHeadList(&OldWriteJournals);
|
|||
|
|
|||
|
pJournal = (PFCB_WRITE_JOURNAL)
|
|||
|
CONTAINING_RECORD(
|
|||
|
pJournalEntry,
|
|||
|
FCB_WRITE_JOURNAL,
|
|||
|
JournalsList);
|
|||
|
|
|||
|
RxFreePool(pJournal);
|
|||
|
}
|
|||
|
|
|||
|
ExReleaseResource(&WriteJournalsResource);
|
|||
|
|
|||
|
ExDeleteResource(&WriteJournalsResource);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
RxdInitializeFcbWriteJournalDebugSupport(
|
|||
|
PFCB pFcb)
|
|||
|
{
|
|||
|
PFCB_WRITE_JOURNAL pJournal;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
|
|||
|
pJournal = RxAllocatePoolWithTag(
|
|||
|
PagedPool | POOL_COLD_ALLOCATION,
|
|||
|
sizeof(FCB_WRITE_JOURNAL),
|
|||
|
RX_MISC_POOLTAG);
|
|||
|
|
|||
|
if (pJournal != NULL) {
|
|||
|
ULONG PathLength;
|
|||
|
|
|||
|
RtlZeroMemory(
|
|||
|
pJournal,
|
|||
|
sizeof(FCB_WRITE_JOURNAL));
|
|||
|
|
|||
|
pJournal->pName = &pJournal->Path[0];
|
|||
|
|
|||
|
if (pFcb->AlreadyPrefixedName.Length > (MAX_PATH * sizeof(WCHAR))) {
|
|||
|
PathLength = MAX_PATH * sizeof(WCHAR);
|
|||
|
} else {
|
|||
|
PathLength = pFcb->AlreadyPrefixedName.Length;
|
|||
|
}
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
pJournal->pName,
|
|||
|
pFcb->AlreadyPrefixedName.Buffer,
|
|||
|
PathLength);
|
|||
|
|
|||
|
pJournal->pFcb = pFcb;
|
|||
|
|
|||
|
pJournal->pWriteInitiationBitmap = pJournal->WriteInitiationBitmap;
|
|||
|
pJournal->pLowIoWriteInitiationBitmap = pJournal->LowIoWriteInitiationBitmap;
|
|||
|
pJournal->pLowIoWriteCompletionBitmap = pJournal->LowIoWriteCompletionBitmap;
|
|||
|
|
|||
|
ExAcquireResourceExclusive(&WriteJournalsResource,TRUE);
|
|||
|
|
|||
|
InsertHeadList(
|
|||
|
&ActiveWriteJournals,
|
|||
|
&pJournal->JournalsList);
|
|||
|
|
|||
|
ExReleaseResource(&WriteJournalsResource);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
RxdTearDownFcbWriteJournalDebugSupport(
|
|||
|
PFCB pFcb)
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
|
|||
|
PFCB_WRITE_JOURNAL pJournal;
|
|||
|
PLIST_ENTRY pJournalEntry;
|
|||
|
|
|||
|
ExAcquireResourceExclusive(&WriteJournalsResource,TRUE);
|
|||
|
|
|||
|
pJournal = RxdFindWriteJournal(pFcb);
|
|||
|
|
|||
|
if (pJournal != NULL) {
|
|||
|
RemoveEntryList(&pJournal->JournalsList);
|
|||
|
|
|||
|
// InsertHeadList(
|
|||
|
// &OldWriteJournals,
|
|||
|
// &pJournal->JournalsList);
|
|||
|
|
|||
|
RxFreePool(pJournal);
|
|||
|
}
|
|||
|
|
|||
|
ExReleaseResource(&WriteJournalsResource);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
RxdUpdateJournalOnWriteInitiation(
|
|||
|
IN OUT PFCB pFcb,
|
|||
|
IN LARGE_INTEGER Offset,
|
|||
|
IN ULONG Length)
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
|
|||
|
PFCB_WRITE_JOURNAL pJournal;
|
|||
|
PLIST_ENTRY pJournalEntry;
|
|||
|
|
|||
|
ExAcquireResourceExclusive(&WriteJournalsResource, TRUE);
|
|||
|
|
|||
|
pJournal = RxdFindWriteJournal(pFcb);
|
|||
|
|
|||
|
if (pJournal != NULL) {
|
|||
|
UpdateBitmap(
|
|||
|
pJournal->WriteInitiationBitmap,
|
|||
|
Offset,
|
|||
|
Length);
|
|||
|
|
|||
|
pJournal->WritesInitiated++;
|
|||
|
}
|
|||
|
|
|||
|
ExReleaseResource(&WriteJournalsResource);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
RxdUpdateJournalOnLowIoWriteInitiation(
|
|||
|
IN OUT PFCB pFcb,
|
|||
|
IN LARGE_INTEGER Offset,
|
|||
|
IN ULONG Length)
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
|
|||
|
|
|||
|
PFCB_WRITE_JOURNAL pJournal;
|
|||
|
PLIST_ENTRY pJournalEntry;
|
|||
|
|
|||
|
ExAcquireResourceExclusive(&WriteJournalsResource, TRUE);
|
|||
|
|
|||
|
pJournal = RxdFindWriteJournal(pFcb);
|
|||
|
|
|||
|
if (pJournal != NULL) {
|
|||
|
UpdateBitmap(
|
|||
|
pJournal->LowIoWriteInitiationBitmap,
|
|||
|
Offset,
|
|||
|
Length);
|
|||
|
|
|||
|
pJournal->LowIoWritesInitiated++;
|
|||
|
}
|
|||
|
|
|||
|
ExReleaseResource(&WriteJournalsResource);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
RxdUpdateJournalOnLowIoWriteCompletion(
|
|||
|
IN OUT PFCB pFcb,
|
|||
|
IN LARGE_INTEGER Offset,
|
|||
|
IN ULONG Length)
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (pFcb->pNetRoot->DeviceType == RxDeviceType(DISK)) {
|
|||
|
PFCB_WRITE_JOURNAL pJournal;
|
|||
|
PLIST_ENTRY pJournalEntry;
|
|||
|
|
|||
|
ExAcquireResourceExclusive(&WriteJournalsResource, TRUE);
|
|||
|
|
|||
|
pJournal = RxdFindWriteJournal(pFcb);
|
|||
|
|
|||
|
if (pJournal != NULL) {
|
|||
|
UpdateBitmap(
|
|||
|
pJournal->LowIoWriteCompletionBitmap,
|
|||
|
Offset,
|
|||
|
Length);
|
|||
|
|
|||
|
pJournal->LowIoWritesCompleted++;
|
|||
|
}
|
|||
|
|
|||
|
ExReleaseResource(&WriteJournalsResource);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
PFCB_WRITE_JOURNAL
|
|||
|
RxdFindWriteJournal(
|
|||
|
PFCB pFcb)
|
|||
|
{
|
|||
|
PFCB_WRITE_JOURNAL pJournal;
|
|||
|
PLIST_ENTRY pJournalEntry;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
pJournalEntry = ActiveWriteJournals.Flink;
|
|||
|
while (pJournalEntry != &ActiveWriteJournals) {
|
|||
|
pJournal = (PFCB_WRITE_JOURNAL)
|
|||
|
CONTAINING_RECORD(
|
|||
|
pJournalEntry,
|
|||
|
FCB_WRITE_JOURNAL,
|
|||
|
JournalsList);
|
|||
|
|
|||
|
if (pJournal->pFcb == pFcb) {
|
|||
|
break;
|
|||
|
} else {
|
|||
|
pJournalEntry = pJournalEntry->Flink;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pJournalEntry == &ActiveWriteJournals) {
|
|||
|
pJournal = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return pJournal;
|
|||
|
}
|
|||
|
|
|||
|
CHAR PageMask[8] = { 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
|
|||
|
|
|||
|
VOID
|
|||
|
UpdateBitmap(
|
|||
|
PBYTE pBitmap,
|
|||
|
LARGE_INTEGER Offset,
|
|||
|
ULONG Length)
|
|||
|
{
|
|||
|
LONG OffsetIn4kChunks;
|
|||
|
LONG OffsetIn32kChunks;
|
|||
|
LONG NumberOf4kChunks,Starting4kChunk;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
// Each byte in the bit map represents a 32k region since each bit represents
|
|||
|
// a 4k region in the file.
|
|||
|
// we ignore the offset's high part for now because the bitmap's max size is
|
|||
|
// far less than what can be accomodated in the low part.
|
|||
|
|
|||
|
OffsetIn4kChunks = Offset.LowPart / (0x1000);
|
|||
|
OffsetIn32kChunks = Offset.LowPart / (0x8000);
|
|||
|
|
|||
|
Starting4kChunk = ((Offset.LowPart & ~0xfff) - (Offset.LowPart & ~0x7fff)) / 0x1000;
|
|||
|
NumberOf4kChunks = Length / 0x1000;
|
|||
|
|
|||
|
if (NumberOf4kChunks > (8 - Starting4kChunk)) {
|
|||
|
pBitmap[OffsetIn32kChunks++] |= (PageMask[7] & ~PageMask[Starting4kChunk]);
|
|||
|
Length -= (8 - Starting4kChunk) * 0x1000;
|
|||
|
}
|
|||
|
|
|||
|
if (Length > 0x8000) {
|
|||
|
while (Length > (0x8000)) {
|
|||
|
pBitmap[OffsetIn32kChunks++] = PageMask[7];
|
|||
|
Length -= (0x8000);
|
|||
|
}
|
|||
|
|
|||
|
Starting4kChunk = 0;
|
|||
|
}
|
|||
|
|
|||
|
// The final chunk is less then 32k. The byte in the bitmao needs to be
|
|||
|
// updated accordingly.
|
|||
|
|
|||
|
if (Length > 0) {
|
|||
|
NumberOf4kChunks = Length / (0x1000);
|
|||
|
pBitmap[OffsetIn32kChunks] |= PageMask[NumberOf4kChunks + Starting4kChunk];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|