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
|
||
|