nt!CcGetDirtyPages函数分析之Scan to the end of the Bcb list--重要
第一部分:
Bcb = CONTAINING_RECORD( SharedCacheMap->BcbList.Flink, BCB, BcbLinks );
//
// Scan to the end of the Bcb list.
//
while (&Bcb->BcbLinks != &SharedCacheMap->BcbList) {
Bcb = CONTAINING_RECORD( Bcb->BcbLinks.Flink, BCB, BcbLinks );
第二部分:
dv
Bcb = 0x89486ba8
SharedCacheMap = 0x89455c98
BcbToUnpin = 0x89486ba8
LockHandle = struct _KLOCK_QUEUE_HANDLE
OldestLsn = {135193435}
SavedByteLength = 0x1000
1: kd> dx -r1 ((ntkrnlmp!_BCB *)0x89486ba8)
((ntkrnlmp!_BCB *)0x89486ba8) : 0x89486ba8 [Type: _BCB *]
[+0x000] Dummy [Type: _MBCB]
[+0x000] NodeTypeCode : 765 [Type: short]
[+0x002] Dirty : 0x1 [Type: unsigned char]
[+0x003] Reserved : 0x0 [Type: unsigned char]
[+0x004] ByteLength : 0x1000 [Type: unsigned long]
[+0x008] FileOffset : {4096} [Type: _LARGE_INTEGER]
[+0x010] BcbLinks [Type: _LIST_ENTRY]
[+0x018] BeyondLastByte : {8192} [Type: _LARGE_INTEGER]
[+0x020] OldestLsn : {135193435} [Type: _LARGE_INTEGER]
[+0x028] NewestLsn : {135197840} [Type: _LARGE_INTEGER]
[+0x030] Vacb : 0x0 [Type: _VACB *]
[+0x034] PinCount : 0x1 [Type: unsigned long]
[+0x038] Resource [Type: _ERESOURCE]
[+0x070] SharedCacheMap : 0x89455c98 [Type: _SHARED_CACHE_MAP *]
[+0x074] BaseAddress : 0x0 [Type: void *]
1: kd> dx -r1 (*((ntkrnlmp!_LIST_ENTRY *)0x89486bb8))
(*((ntkrnlmp!_LIST_ENTRY *)0x89486bb8)) [Type: _LIST_ENTRY]
[+0x000] Flink : 0x89469228 [Type: _LIST_ENTRY *]
[+0x004] Blink : 0x89455ca8 [Type: _LIST_ENTRY *]
1: kd> dx -r1 ((ntkrnlmp!_LIST_ENTRY *)0x89469228)
((ntkrnlmp!_LIST_ENTRY *)0x89469228) : 0x89469228 [Type: _LIST_ENTRY *]
[+0x000] Flink : 0x89455ca8 [Type: _LIST_ENTRY *]
[+0x004] Blink : 0x89486bb8 [Type: _LIST_ENTRY *]
第三部分:
1: kd> dt _bcb 0x89469228-10
nt!_BCB
+0x000 Dummy : _MBCB
+0x000 NodeTypeCode : 0n765
+0x002 Dirty : 0x1 ''
+0x003 Reserved : 0 ''
+0x004 ByteLength : 0x1000
+0x008 FileOffset : _LARGE_INTEGER 0x0
+0x010 BcbLinks : _LIST_ENTRY [ 0x89455ca8 - 0x89486bb8 ]
+0x018 BeyondLastByte : _LARGE_INTEGER 0x1000
+0x020 OldestLsn : _LARGE_INTEGER 0x80ee220
+0x028 NewestLsn : _LARGE_INTEGER 0x80ee307
+0x030 Vacb : (null)
+0x034 PinCount : 0
+0x038 Resource : _ERESOURCE
+0x070 SharedCacheMap : 0x89455c98 _SHARED_CACHE_MAP
+0x074 BaseAddress : (null)
1: kd> ?0n765
Evaluate expression: 765 = 000002fd
1: kd> p
nt!CcGetDirtyPages+0x15d:
80a15d1b 83ee10 sub esi,10h
1: kd> p
nt!CcGetDirtyPages+0x160:
80a15d1e 33db xor ebx,ebx
1: kd> r
eax=89486bb8 ebx=00001000 ecx=89455d50 edx=00000000 esi=89469218 edi=89455c98
eip=80a15d1e esp=f78d2928 ebp=f78d298c iopl=0 nv up ei ng nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000286
nt!CcGetDirtyPages+0x160:
80a15d1e 33db xor ebx,ebx
1: kd> dt _bcb 0x89469228-10
nt!_BCB
+0x000 Dummy : _MBCB
+0x000 NodeTypeCode : 0n765
+0x002 Dirty : 0x1 ''
if ((Bcb->NodeTypeCode == CACHE_NTC_BCB) && Bcb->Dirty) {
SavedFileOffset = Bcb->FileOffset;
SavedByteLength = Bcb->ByteLength;
SavedOldestLsn = Bcb->OldestLsn;
SavedNewestLsn = Bcb->NewestLsn;
//
// Call the file system. This callback may raise status.
//
(*DirtyPageRoutine)( SharedCacheMap->FileObject,
&SavedFileOffset,
SavedByteLength,
&SavedOldestLsn,
&SavedNewestLsn,
Context1,
Context2 );
第四部分:
1: kd> t
Breakpoint 30 hit
Ntfs!DirtyPageRoutine:
f71451f2 55 push ebp
1: kd> dv
FileObject = 0x89455df0
FileOffset = 0xf78d2940 {0}
Length = 0x1000
OldestLsn = 0xf78d2950 {135193120}
NewestLsn = 0xf78d2948 {135193351}
Context1 = 0xf78d2c28
Context2 = 0xf78d2aa4
PageIndex = 0xf78d2aa4
第五部分:
1: kd> dt DIRTY_PAGE_CONTEXT 0xf78d2aa4
Ntfs!DIRTY_PAGE_CONTEXT
+0x000 DirtyPageTable : 0xf78d2b90 _RESTART_POINTERS
+0x004 DirtyPageIndex : 0x18
+0x008 OldestFileObject : 0x89455df0 _FILE_OBJECT
+0x010 OldestLsn : _LARGE_INTEGER 0x80ee35b
+0x018 Overflow : 0 ''
1: kd> ?0n135193120
Evaluate expression: 135193120 = 080ee220
1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_RESTART_POINTERS *)0xf78d2b90)
((Ntfs!_RESTART_POINTERS *)0xf78d2b90) : 0xf78d2b90 [Type: _RESTART_POINTERS *]
[+0x000] Resource [Type: _ERESOURCE]
[+0x038] Table : 0x895b9840 [Type: _RESTART_TABLE *]
[+0x03c] SpinLock : 0x0 [Type: unsigned long]
[+0x040] ResourceInitialized : 0x1 [Type: unsigned char]
[+0x041] DrainPending : 0x0 [Type: unsigned char]
[+0x042] Unused [Type: unsigned char [6]]
1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_RESTART_TABLE *)0x895b9840)
((Ntfs!_RESTART_TABLE *)0x895b9840) : 0x895b9840 [Type: _RESTART_TABLE *]
[+0x000] EntrySize : 0x2c [Type: unsigned short]
[+0x002] NumberEntries : 0x20 [Type: unsigned short]
[+0x004] NumberAllocated : 0x1 [Type: unsigned short]
[+0x006] Reserved [Type: unsigned short [3]]
[+0x00c] FreeGoal : 0xffffffff [Type: unsigned long]
[+0x010] FirstFree : 0x44 [Type: unsigned long]
[+0x014] LastFree : 0x56c [Type: unsigned long]
1: kd> dt DIRTY_PAGE_ENTRY_V0 0x895b9840+18
Ntfs!DIRTY_PAGE_ENTRY_V0
+0x000 AllocatedOrNextFree : 0xffffffff
+0x004 TargetAttribute : 0x18
+0x008 LengthOfTransfer : 0x1000
+0x00c LcnsToFollow : 0
+0x010 Reserved : 0
+0x014 Vcn : 0n4096
+0x01c OldestLsn : _LARGE_INTEGER 0x80ee35b
+0x024 LcnsForPage : [1] 0n0
第六部分:参考Ntfs!_VCB结构中的OpenAttributeTable
1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_VCB *)0x8962e100)
[+0x218] OpenAttributeTable [Type: _RESTART_POINTERS]
1: kd> dx -id 0,0,899a2278 -r1 (*((Ntfs!_RESTART_POINTERS *)0x8962e318))
(*((Ntfs!_RESTART_POINTERS *)0x8962e318)) [Type: _RESTART_POINTERS]
[+0x000] Resource [Type: _ERESOURCE]
[+0x038] Table : 0x899004c8 [Type: _RESTART_TABLE *]
[+0x03c] SpinLock : 0x0 [Type: unsigned long]
[+0x040] ResourceInitialized : 0x1 [Type: unsigned char]
[+0x041] DrainPending : 0x0 [Type: unsigned char]
[+0x042] Unused [Type: unsigned char [6]]
#define GetRestartEntryFromIndex(TBL,INDX) ( \
(PVOID)((PCHAR)(TBL)->Table + (INDX)) \
)
1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_RESTART_TABLE *)0x899004c8)
((Ntfs!_RESTART_TABLE *)0x899004c8) : 0x899004c8 [Type: _RESTART_TABLE *]
[+0x000] EntrySize : 0x28 [Type: unsigned short]
[+0x002] NumberEntries : 0x28 [Type: unsigned short]
[+0x004] NumberAllocated : 0x1a [Type: unsigned short]
[+0x006] Reserved [Type: unsigned short [3]]
[+0x00c] FreeGoal : 0xffffffff [Type: unsigned long]
[+0x010] FirstFree : 0x428 [Type: unsigned long]
[+0x014] LastFree : 0x630 [Type: unsigned long]
1: kd> dt OPEN_ATTRIBUTE_ENTRY 0x899004c8+18
Ntfs!OPEN_ATTRIBUTE_ENTRY
+0x000 AllocatedOrNextFree : 0xffffffff
+0x004 BytesPerIndexBuffer : 0x1000
+0x008 AttributeTypeCode : 0xa0
+0x00c DirtyPagesSeen : 0 ''
+0x00d Unused : [3] ""
+0x010 FileReference : _MFT_SEGMENT_REFERENCE
+0x018 LsnOfOpenRecord : _LARGE_INTEGER 0x80ee1f3
+0x020 OatData : 0xe1270dc8 OPEN_ATTRIBUTE_DATA
+0x020 Alignment : 0xe1270dc8
1: kd> dx -id 0,0,899a2278 -r1 (*((Ntfs!_MFT_SEGMENT_REFERENCE *)0x899004f0))
(*((Ntfs!_MFT_SEGMENT_REFERENCE *)0x899004f0)) [Type: _MFT_SEGMENT_REFERENCE]
[+0x000] SegmentNumberLowPart : 0x5 [Type: unsigned long]
[+0x004] SegmentNumberHighPart : 0x0 [Type: unsigned short]
[+0x006] SequenceNumber : 0x5 [Type: unsigned short]
1: kd> dt OPEN_ATTRIBUTE_ENTRY 0x899004c8+18+28*1
Ntfs!OPEN_ATTRIBUTE_ENTRY
+0x000 AllocatedOrNextFree : 0xffffffff
+0x004 BytesPerIndexBuffer : 0
+0x008 AttributeTypeCode : 0x80
+0x00c DirtyPagesSeen : 0 ''
+0x00d Unused : [3] ""
+0x010 FileReference : _MFT_SEGMENT_REFERENCE
+0x018 LsnOfOpenRecord : _LARGE_INTEGER 0x80ee239
+0x020 OatData : 0xe12fe870 OPEN_ATTRIBUTE_DATA
+0x020 Alignment : 0xe12fe870
1: kd> dx -id 0,0,899a2278 -r1 (*((Ntfs!_MFT_SEGMENT_REFERENCE *)0x89900518))
(*((Ntfs!_MFT_SEGMENT_REFERENCE *)0x89900518)) [Type: _MFT_SEGMENT_REFERENCE]
[+0x000] SegmentNumberLowPart : 0x0 [Type: unsigned long]
[+0x004] SegmentNumberHighPart : 0x0 [Type: unsigned short]
[+0x006] SequenceNumber : 0x1 [Type: unsigned short]
第七部分:
1: kd> dt SCB_NONPAGED 0x89927294-c
Ntfs!SCB_NONPAGED
+0x000 NodeTypeCode : 0n1799
+0x002 NodeByteSize : 0n28
+0x004 OpenAttributeTableIndex : 0x18
+0x008 OnDiskOatIndex : 0x18
+0x00c SegmentObject : _SECTION_OBJECT_POINTERS
+0x018 Vcb : 0x8962e100 _VCB
//
// Get the Vcb out of the file object.
//
NonpagedScb = CONTAINING_RECORD( FileObject->SectionObjectPointer,
SCB_NONPAGED,
SegmentObject );
1: kd> p
Ntfs!DirtyPageRoutine+0x11:
f7145203 83ef0c sub edi,0Ch
1: kd> r
eax=89455df0 ebx=f78d2aa4 ecx=00000000 edx=00000000 esi=f78d2b90 edi=89927294
第八部分:看看DirtyPageTable是否已经用完
//
// Check for an overrun in the table and stop processing in that case
// The restart table format can't accomodate tables greater than 64k in size
// due to the ushort used for the attribute index
//
if (AllocatedSizeOfRestartTable( DirtyPageTable ) > MAX_RESTART_TABLE_SIZE ){
DirtyPageContext->Overflow = TRUE;
} else {
#define AllocatedSizeOfRestartTable(TBL) ( \
(ULONG)(((TBL)->Table->NumberAllocated * \
(TBL)->Table->EntrySize) + \
sizeof(RESTART_TABLE)) \
)
#define MAX_RESTART_TABLE_SIZE 0xF000
1: kd> dt DIRTY_PAGE_CONTEXT 0xf78d2aa4
Ntfs!DIRTY_PAGE_CONTEXT
+0x000 DirtyPageTable : 0xf78d2b90 _RESTART_POINTERS
+0x004 DirtyPageIndex : 0x18
+0x008 OldestFileObject : 0x89455df0 _FILE_OBJECT
+0x010 OldestLsn : _LARGE_INTEGER 0x80ee35b
+0x018 Overflow : 0 ''
1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_RESTART_POINTERS *)0xf78d2b90)
((Ntfs!_RESTART_POINTERS *)0xf78d2b90) : 0xf78d2b90 [Type: _RESTART_POINTERS *]
[+0x000] Resource [Type: _ERESOURCE]
[+0x038] Table : 0x895b9840 [Type: _RESTART_TABLE *]
[+0x03c] SpinLock : 0x0 [Type: unsigned long]
[+0x040] ResourceInitialized : 0x1 [Type: unsigned char]
[+0x041] DrainPending : 0x0 [Type: unsigned char]
[+0x042] Unused [Type: unsigned char [6]]
1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_RESTART_TABLE *)0x895b9840)
((Ntfs!_RESTART_TABLE *)0x895b9840) : 0x895b9840 [Type: _RESTART_TABLE *]
[+0x000] EntrySize : 0x2c [Type: unsigned short]
[+0x002] NumberEntries : 0x20 [Type: unsigned short]
[+0x004] NumberAllocated : 0x1 [Type: unsigned short]
[+0x006] Reserved [Type: unsigned short [3]]
[+0x00c] FreeGoal : 0xffffffff [Type: unsigned long]
[+0x010] FirstFree : 0x44 [Type: unsigned long]
[+0x014] LastFree : 0x56c [Type: unsigned long]
第九部分:
//
// Get a pointer to the entry we just allocated.
//
PageIndex = NtfsAllocateRestartTableIndex( DirtyPageTable, TRUE );
PageEntry = GetRestartEntryFromIndex( DirtyPageTable, PageIndex );
1: kd> p
Ntfs!DirtyPageRoutine+0x42:
f7145234 e84f0d0100 call Ntfs!NtfsAllocateRestartTableIndex (f7155f88)
1: kd> p
Ntfs!DirtyPageRoutine+0x47:
f7145239 8b7638 mov esi,dword ptr [esi+38h]
1: kd> r
eax=00000044
第十部分:
1: kd> dt DIRTY_PAGE_ENTRY_V0 0x895b9840+44
Ntfs!DIRTY_PAGE_ENTRY_V0
+0x000 AllocatedOrNextFree : 0xffffffff
+0x004 TargetAttribute : 0
+0x008 LengthOfTransfer : 0
+0x00c LcnsToFollow : 0
+0x010 Reserved : 0
+0x014 Vcn : 0n0
+0x01c OldestLsn : _LARGE_INTEGER 0x0
+0x024 LcnsForPage : [1] 0n0
PageEntry->TargetAttribute = NonpagedScb->OpenAttributeTableIndex;
1: kd> dt DIRTY_PAGE_ENTRY_V0 0x895b9840+44
Ntfs!DIRTY_PAGE_ENTRY_V0
+0x000 AllocatedOrNextFree : 0xffffffff
+0x004 TargetAttribute : 0x18
+0x008 LengthOfTransfer : 0
+0x00c LcnsToFollow : 0
+0x010 Reserved : 0
+0x014 Vcn : 0n0
+0x01c OldestLsn : _LARGE_INTEGER 0x0
+0x024 LcnsForPage : [1] 0n0
第十一部分:
PageEntry->LengthOfTransfer = Length;
1: kd> dt DIRTY_PAGE_ENTRY_V0 0x895b9840+44
Ntfs!DIRTY_PAGE_ENTRY_V0
+0x000 AllocatedOrNextFree : 0xffffffff
+0x004 TargetAttribute : 0x18
+0x008 LengthOfTransfer : 0x1000
+0x00c LcnsToFollow : 0
+0x010 Reserved : 0
+0x014 Vcn : 0n0
+0x01c OldestLsn : _LARGE_INTEGER 0x0
+0x024 LcnsForPage : [1] 0n0
第十二部分:
if (NonpagedScb->Vcb->RestartVersion == 0) {
((PDIRTY_PAGE_ENTRY_V0) PageEntry)->Vcn = FileOffset->QuadPart;
((PDIRTY_PAGE_ENTRY_V0) PageEntry)->OldestLsn = *OldestLsn;
1: kd> dt DIRTY_PAGE_ENTRY_V0 0x895b9840+44
Ntfs!DIRTY_PAGE_ENTRY_V0
+0x000 AllocatedOrNextFree : 0xffffffff
+0x004 TargetAttribute : 0x18
+0x008 LengthOfTransfer : 0x1000
+0x00c LcnsToFollow : 0
+0x010 Reserved : 0
+0x014 Vcn : 0n0
+0x01c OldestLsn : _LARGE_INTEGER 0x80ee220
+0x024 LcnsForPage : [1] 0n0
参考第一个:TargetAttribute : 0x18 也是0x18
1: kd> dt DIRTY_PAGE_ENTRY_V0 0x895b9840+18
Ntfs!DIRTY_PAGE_ENTRY_V0
+0x000 AllocatedOrNextFree : 0xffffffff
+0x004 TargetAttribute : 0x18
+0x008 LengthOfTransfer : 0x1000
+0x00c LcnsToFollow : 0
+0x010 Reserved : 0
+0x014 Vcn : 0n4096
+0x01c OldestLsn : _LARGE_INTEGER 0x80ee35b
+0x024 LcnsForPage : [1] 0n0
第十三部分:
DirtyPageContext->DirtyPageIndex = PageIndex;
DirtyPageContext->OldestFileObject = FileObject;
DirtyPageContext->OldestLsn.QuadPart = OldestLsn->QuadPart;
参考以前的:
1: kd> dt DIRTY_PAGE_CONTEXT 0xf78d2aa4
Ntfs!DIRTY_PAGE_CONTEXT
+0x000 DirtyPageTable : 0xf78d2b90 _RESTART_POINTERS
+0x004 DirtyPageIndex : 0x18
+0x008 OldestFileObject : 0x89455df0 _FILE_OBJECT
+0x010 OldestLsn : _LARGE_INTEGER 0x80ee35b
+0x018 Overflow : 0 ''
参考以前的:
1: kd> dt DIRTY_PAGE_CONTEXT 0xf78d2aa4
Ntfs!DIRTY_PAGE_CONTEXT
+0x000 DirtyPageTable : 0xf78d2b90 _RESTART_POINTERS
+0x004 DirtyPageIndex : 0x44
+0x008 OldestFileObject : 0x89455df0 _FILE_OBJECT
+0x010 OldestLsn : _LARGE_INTEGER 0x80ee220
+0x018 Overflow : 0 ''