windows-nt/Source/XPSP1/NT/base/fs/rdr2/rxce/rxdebug.c

384 lines
9.6 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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