00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "cc.h"
00025
00026
00027
00028
00029
00030 #define me 0x000000040
00031
00032
00033
00034
00035
00036
VOID
00037
CcUnmapVacb (
00038 IN
PVACB Vacb,
00039 IN
PSHARED_CACHE_MAP SharedCacheMap,
00040 IN BOOLEAN UnmapBehind
00041 );
00042
00043
PVACB
00044
CcGetVacbMiss (
00045 IN
PSHARED_CACHE_MAP SharedCacheMap,
00046 IN LARGE_INTEGER FileOffset,
00047 IN OUT PKIRQL OldIrql
00048 );
00049
00050
VOID
00051
CcCalculateVacbLevelLockCount (
00052 IN
PSHARED_CACHE_MAP SharedCacheMap,
00053 IN
PVACB *VacbArray,
00054 IN ULONG Level
00055 );
00056
00057
PVACB
00058
CcGetVacbLargeOffset (
00059 IN
PSHARED_CACHE_MAP SharedCacheMap,
00060 IN LONGLONG FileOffset
00061 );
00062
00063
VOID
00064
CcSetVacbLargeOffset (
00065 IN
PSHARED_CACHE_MAP SharedCacheMap,
00066 IN LONGLONG FileOffset,
00067 IN
PVACB Vacb
00068 );
00069
00070
#ifdef ALLOC_PRAGMA
00071
#pragma alloc_text(INIT, CcInitializeVacbs)
00072
#endif
00073
00074
00075
00076
00077
00078 #define GetVacb(SCM,OFF) ( \
00079
((SCM)->SectionSize.QuadPart > VACB_SIZE_OF_FIRST_LEVEL) ? \
00080
CcGetVacbLargeOffset((SCM),(OFF).QuadPart) : \
00081
(SCM)->Vacbs[(OFF).LowPart >> VACB_OFFSET_SHIFT] \
00082
)
00083
00084 _inline
00085
VOID
00086 SetVacb (
00087 IN
PSHARED_CACHE_MAP SharedCacheMap,
00088 IN LARGE_INTEGER Offset,
00089 IN
PVACB Vacb
00090 )
00091 {
00092
if (SharedCacheMap->SectionSize.QuadPart >
VACB_SIZE_OF_FIRST_LEVEL) {
00093
CcSetVacbLargeOffset(SharedCacheMap,
Offset.QuadPart, Vacb);
00094
#ifdef VACB_DBG
00095
ASSERT(Vacb >=
VACB_SPECIAL_FIRST_VALID ||
CcGetVacbLargeOffset(SharedCacheMap,
Offset.QuadPart) == Vacb);
00096
#endif // VACB_DBG
00097
}
else if (Vacb <
VACB_SPECIAL_FIRST_VALID) {
00098 SharedCacheMap->Vacbs[
Offset.LowPart >>
VACB_OFFSET_SHIFT] = Vacb;
00099 }
00100
#ifdef VACB_DBG
00101
00102
00103
00104
00105
00106
if (Vacb <
VACB_SPECIAL_FIRST_VALID) {
00107
if (Vacb !=
NULL) {
00108 SharedCacheMap->ReservedForAlignment++;
00109 }
else {
00110 SharedCacheMap->ReservedForAlignment--;
00111 }
00112 }
00113
ASSERT((SharedCacheMap->SectionSize.QuadPart <=
VACB_SIZE_OF_FIRST_LEVEL) ||
00114 (SharedCacheMap->ReservedForAlignment == 0) ||
00115
IsVacbLevelReferenced( SharedCacheMap, SharedCacheMap->Vacbs, 1 ));
00116
#endif // VACB_DBG
00117
}
00118
00119
00120
00121
00122
00123 _inline
00124
VOID
00125 ReferenceVacbLevel (
00126 IN
PSHARED_CACHE_MAP SharedCacheMap,
00127 IN
PVACB *VacbArray,
00128 IN ULONG Level,
00129 IN LONG Amount,
00130 IN BOOLEAN Special
00131 )
00132 {
00133
PVACB_LEVEL_REFERENCE VacbReference =
VacbLevelReference( SharedCacheMap, VacbArray, Level );
00134
00135
ASSERT( Amount > 0 ||
00136 (!Special && VacbReference->
Reference >= (0 - Amount)) ||
00137 ( Special && VacbReference->
SpecialReference >= (0 - Amount)));
00138
00139
if (Special) {
00140 VacbReference->
SpecialReference += Amount;
00141 }
else {
00142 VacbReference->
Reference += Amount;
00143 }
00144
00145
#ifdef VACB_DBG
00146
00147
00148
00149
00150
00151 {
00152 LONG Current = VacbReference->
Reference;
00153
CcCalculateVacbLevelLockCount( SharedCacheMap, VacbArray, Level );
00154
ASSERT( Current == VacbReference->
Reference );
00155 }
00156
#endif // VACB_DBG
00157
}
00158
00159
00160
00161
00162
00163 #define CcMoveVacbToReuseHead(V) RemoveEntryList( &(V)->LruList ); \
00164
InsertHeadList( &CcVacbLru, &(V)->LruList );
00165
00166 #define CcMoveVacbToReuseTail(V) RemoveEntryList( &(V)->LruList ); \
00167
InsertTailList( &CcVacbLru, &(V)->LruList );
00168
00169
00170
00171
00172
00173
00174 #define SizeOfVacbArray(LSZ) ( \
00175
((LSZ).HighPart != 0) ? MAXULONG : \
00176
((LSZ).LowPart > (PREALLOCATED_VACBS * VACB_MAPPING_GRANULARITY) ? \
00177
(((LSZ).LowPart >> VACB_OFFSET_SHIFT) * sizeof(PVACB)) : \
00178
(PREALLOCATED_VACBS * sizeof(PVACB))) \
00179
)
00180
00181 #define CheckedDec(N) { \
00182
ASSERT((N) != 0); \
00183
(N) -= 1; \
00184
}
00185
00186
00187
VOID
00188 CcInitializeVacbs(
00189 )
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 {
00209 ULONG VacbBytes;
00210
PVACB NextVacb;
00211
00212
CcNumberVacbs = (
MmSizeOfSystemCacheInPages >> (
VACB_OFFSET_SHIFT -
PAGE_SHIFT)) - 2;
00213 VacbBytes =
CcNumberVacbs *
sizeof(
VACB);
00214
00215
KeInitializeSpinLock( &
CcVacbSpinLock );
00216
CcVacbs = (
PVACB)
FsRtlAllocatePoolWithTag(
NonPagedPool, VacbBytes, 'aVcC' );
00217
CcBeyondVacbs = (
PVACB)((PCHAR)
CcVacbs + VacbBytes);
00218 RtlZeroMemory(
CcVacbs, VacbBytes );
00219
00220 InitializeListHead( &
CcVacbLru );
00221
00222
for (NextVacb =
CcVacbs; NextVacb <
CcBeyondVacbs; NextVacb++) {
00223
00224 InsertTailList( &
CcVacbLru, &NextVacb->
LruList );
00225 }
00226 }
00227
00228
00229 PVOID
00230 CcGetVirtualAddressIfMapped (
00231 IN
PSHARED_CACHE_MAP SharedCacheMap,
00232 IN LONGLONG FileOffset,
00233 OUT
PVACB *Vacb,
00234 OUT PULONG ReceivedLength
00235 )
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 {
00266 KIRQL OldIrql;
00267 ULONG VacbOffset = (ULONG)FileOffset & (
VACB_MAPPING_GRANULARITY - 1);
00268 PVOID Value =
NULL;
00269
00270
ASSERT(KeGetCurrentIrql() <
DISPATCH_LEVEL);
00271
00272
00273
00274
00275
00276 *ReceivedLength =
VACB_MAPPING_GRANULARITY - VacbOffset;
00277
00278
00279
00280
00281
00282
CcAcquireVacbLock( &OldIrql );
00283
00284
ASSERT( FileOffset <= SharedCacheMap->SectionSize.QuadPart );
00285
00286
if ((*Vacb =
GetVacb( SharedCacheMap, *(PLARGE_INTEGER)&FileOffset )) !=
NULL) {
00287
00288
if ((*Vacb)->Overlay.ActiveCount == 0) {
00289 SharedCacheMap->VacbActiveCount += 1;
00290 }
00291
00292 (*Vacb)->Overlay.ActiveCount += 1;
00293
00294
00295
00296
00297
00298
00299
CcMoveVacbToReuseTail( *Vacb );
00300
00301 Value = (PVOID)((PCHAR)(*Vacb)->BaseAddress + VacbOffset);
00302 }
00303
00304
CcReleaseVacbLock( OldIrql );
00305
return Value;
00306 }
00307
00308
00309 PVOID
00310 CcGetVirtualAddress (
00311 IN
PSHARED_CACHE_MAP SharedCacheMap,
00312 IN LARGE_INTEGER FileOffset,
00313 OUT
PVACB *Vacb,
00314 IN OUT PULONG ReceivedLength
00315 )
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 {
00351 KIRQL OldIrql;
00352
PVACB TempVacb;
00353 ULONG VacbOffset = FileOffset.LowPart & (
VACB_MAPPING_GRANULARITY - 1);
00354
00355
ASSERT(KeGetCurrentIrql() <
DISPATCH_LEVEL);
00356
00357
00358
00359
00360
00361
CcAcquireVacbLock( &OldIrql );
00362
00363
ASSERT( FileOffset.QuadPart <= SharedCacheMap->SectionSize.QuadPart );
00364
00365
if ((TempVacb =
GetVacb( SharedCacheMap, FileOffset )) ==
NULL) {
00366
00367 TempVacb =
CcGetVacbMiss( SharedCacheMap, FileOffset, &OldIrql );
00368
00369 }
else {
00370
00371
if (TempVacb->
Overlay.ActiveCount == 0) {
00372 SharedCacheMap->VacbActiveCount += 1;
00373 }
00374
00375 TempVacb->
Overlay.ActiveCount += 1;
00376 }
00377
00378
00379
00380
00381
00382
00383
CcMoveVacbToReuseTail( TempVacb );
00384
00385
CcReleaseVacbLock( OldIrql );
00386
00387
00388
00389
00390
00391 *Vacb = TempVacb;
00392 *ReceivedLength =
VACB_MAPPING_GRANULARITY - VacbOffset;
00393
00394
ASSERT(KeGetCurrentIrql() <
DISPATCH_LEVEL);
00395
00396
return (PVOID)((PCHAR)TempVacb->BaseAddress + VacbOffset);
00397 }
00398
00399
00400
PVACB
00401 CcGetVacbMiss (
00402 IN
PSHARED_CACHE_MAP SharedCacheMap,
00403 IN LARGE_INTEGER FileOffset,
00404 IN OUT PKIRQL OldIrql
00405 )
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 {
00437
PSHARED_CACHE_MAP OldSharedCacheMap;
00438
PVACB Vacb, TempVacb;
00439 LARGE_INTEGER MappedLength;
00440 LARGE_INTEGER NormalOffset;
00441
NTSTATUS Status;
00442 ULONG ActivePage;
00443 ULONG PageIsDirty;
00444
PVACB ActiveVacb =
NULL;
00445 ULONG VacbOffset = FileOffset.LowPart & (
VACB_MAPPING_GRANULARITY - 1);
00446
00447 NormalOffset = FileOffset;
00448 NormalOffset.LowPart -= VacbOffset;
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
if (!
FlagOn(SharedCacheMap->Flags,
RANDOM_ACCESS_SEEN) &&
00476 ((NormalOffset.LowPart & (
SEQUENTIAL_MAP_LIMIT - 1)) == 0) &&
00477 (NormalOffset.QuadPart >= (
SEQUENTIAL_MAP_LIMIT * 2))) {
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
CcReleaseVacbLock( *OldIrql );
00494 MappedLength.QuadPart = NormalOffset.QuadPart - (
SEQUENTIAL_MAP_LIMIT * 2);
00495
CcUnmapVacbArray( SharedCacheMap, &MappedLength, (
SEQUENTIAL_MAP_LIMIT * 2),
TRUE );
00496
CcAcquireVacbLock( OldIrql );
00497 }
00498
00499
00500
00501
00502
00503 Vacb = CONTAINING_RECORD(
CcVacbLru.Flink,
VACB, LruList );
00504
00505
while (
TRUE) {
00506
00507
00508
00509
00510
00511
00512
00513 OldSharedCacheMap = Vacb->
SharedCacheMap;
00514
if ((Vacb->
Overlay.ActiveCount == 0) ||
00515 ((ActiveVacb ==
NULL) &&
00516 (OldSharedCacheMap !=
NULL) &&
00517 (OldSharedCacheMap->
ActiveVacb == Vacb))) {
00518
00519
00520
00521
00522
00523
00524
00525
if (Vacb->
BaseAddress !=
NULL) {
00526
00527
00528
00529
00530
00531
00532
if (Vacb->
Overlay.ActiveCount != 0) {
00533
00534
00535
00536
00537
00538
GetActiveVacbAtDpcLevel( Vacb->
SharedCacheMap, ActiveVacb, ActivePage, PageIsDirty );
00539
00540
00541
00542
00543
00544
00545
00546 }
else {
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
CcAcquireMasterLockAtDpcLevel();
00557
if (Vacb->
SharedCacheMap->
FileObject->
SectionObjectPointer->
SharedCacheMap ==
00558 Vacb->
SharedCacheMap) {
00559
00560
CcIncrementOpenCount( Vacb->
SharedCacheMap, 'mvGS' );
00561
CcReleaseMasterLockFromDpcLevel();
00562
break;
00563 }
00564
CcReleaseMasterLockFromDpcLevel();
00565 }
00566 }
else {
00567
break;
00568 }
00569 }
00570
00571
00572
00573
00574
00575
00576
if (Vacb->
LruList.Flink != &
CcVacbLru) {
00577
00578 Vacb = CONTAINING_RECORD( Vacb->
LruList.Flink,
VACB, LruList );
00579
00580 }
else {
00581
00582
CcReleaseVacbLock( *OldIrql );
00583
00584
00585
00586
00587
00588
00589
if (ActiveVacb !=
NULL) {
00590
CcFreeActiveVacb( ActiveVacb->
SharedCacheMap, ActiveVacb, ActivePage, PageIsDirty );
00591 ActiveVacb =
NULL;
00592
00593
00594
00595
00596
00597
00598
CcAcquireVacbLock( OldIrql );
00599
00600 Vacb = CONTAINING_RECORD(
CcVacbLru.Flink,
VACB, LruList );
00601
00602 }
else {
00603
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
00604 }
00605 }
00606 }
00607
00608
00609
00610
00611
00612
00613
if (Vacb->
SharedCacheMap !=
NULL) {
00614
00615 OldSharedCacheMap = Vacb->
SharedCacheMap;
00616
SetVacb( OldSharedCacheMap, Vacb->
Overlay.FileOffset,
NULL );
00617 Vacb->
SharedCacheMap =
NULL;
00618 }
00619
00620
00621
00622
00623
00624
00625 Vacb->
Overlay.ActiveCount = 1;
00626 SharedCacheMap->VacbActiveCount += 1;
00627
00628
CcReleaseVacbLock( *OldIrql );
00629
00630
00631
00632
00633
00634
if (Vacb->
BaseAddress !=
NULL) {
00635
00636
00637
00638
00639
00640
CcDrainVacbLevelZone();
00641
00642
CcUnmapVacb( Vacb, OldSharedCacheMap,
FALSE );
00643
00644
00645
00646
00647
00648
00649
CcAcquireMasterLock( OldIrql );
00650
00651
00652
00653
00654
00655
CcDecrementOpenCount( OldSharedCacheMap, 'mvGF' );
00656
00657
if ((OldSharedCacheMap->
OpenCount == 0) &&
00658 !
FlagOn(OldSharedCacheMap->
Flags,
WRITE_QUEUED) &&
00659 (OldSharedCacheMap->
DirtyPages == 0)) {
00660
00661
00662
00663
00664
00665 RemoveEntryList( &OldSharedCacheMap->
SharedCacheMapLinks );
00666 InsertTailList( &
CcDirtySharedCacheMapList.
SharedCacheMapLinks,
00667 &OldSharedCacheMap->
SharedCacheMapLinks );
00668
00669
00670
00671
00672
00673
00674
LazyWriter.
OtherWork =
TRUE;
00675
if (!
LazyWriter.
ScanActive) {
00676
CcScheduleLazyWriteScan();
00677 }
00678 }
00679
00680
CcReleaseMasterLock( *OldIrql );
00681 }
00682
00683
00684
00685
00686
00687
00688
try {
00689
00690
00691
00692
00693
00694
00695
00696 MappedLength.QuadPart = SharedCacheMap->SectionSize.QuadPart - NormalOffset.QuadPart;
00697
00698
if ((MappedLength.HighPart != 0) ||
00699 (MappedLength.LowPart >
VACB_MAPPING_GRANULARITY)) {
00700
00701 MappedLength.LowPart =
VACB_MAPPING_GRANULARITY;
00702 }
00703
00704
00705
00706
00707
00708
DebugTrace( 0,
mm,
"MmMapViewInSystemCache:\n", 0 );
00709
DebugTrace( 0,
mm,
" Section = %08lx\n", SharedCacheMap->Section );
00710
DebugTrace2(0,
mm,
" Offset = %08lx, %08lx\n",
00711 NormalOffset.LowPart,
00712 NormalOffset.HighPart );
00713
DebugTrace( 0,
mm,
" ViewSize = %08lx\n", MappedLength.LowPart );
00714
00715
Status =
00716
MmMapViewInSystemCache( SharedCacheMap->Section,
00717 &Vacb->
BaseAddress,
00718 &NormalOffset,
00719 &MappedLength.LowPart );
00720
00721
DebugTrace( 0,
mm,
" <BaseAddress = %08lx\n", Vacb->
BaseAddress );
00722
DebugTrace( 0,
mm,
" <ViewSize = %08lx\n", MappedLength.LowPart );
00723
00724
if (!
NT_SUCCESS(
Status )) {
00725
00726
DebugTrace( 0, 0,
"Error from Map, Status = %08lx\n",
Status );
00727
00728
ExRaiseStatus(
FsRtlNormalizeNtstatus(
Status,
00729 STATUS_UNEXPECTED_MM_MAP_ERROR ));
00730 }
00731
00732 } finally {
00733
00734
00735
00736
00737
00738
if (ActiveVacb !=
NULL) {
00739
00740
CcFreeActiveVacb( ActiveVacb->
SharedCacheMap, ActiveVacb, ActivePage, PageIsDirty );
00741 }
00742
00743
00744
00745
00746
00747
if (AbnormalTermination()) {
00748
00749
CcAcquireVacbLock( OldIrql );
00750
00751
00752
00753
00754
00755
00756
00757 Vacb->
BaseAddress =
NULL;
00758
00759
CheckedDec(Vacb->
Overlay.ActiveCount);
00760
CheckedDec(SharedCacheMap->VacbActiveCount);
00761
00762
00763
00764
00765
00766
00767
if (SharedCacheMap->WaitOnActiveCount !=
NULL) {
00768
KeSetEvent( SharedCacheMap->WaitOnActiveCount, 0,
FALSE );
00769 }
00770
00771
CcReleaseVacbLock( *OldIrql );
00772 }
00773 }
00774
00775
00776
00777
00778
00779
if (SharedCacheMap->SectionSize.QuadPart >
VACB_SIZE_OF_FIRST_LEVEL) {
00780
00781
00782
00783
00784
00785
if (!
CcPrefillVacbLevelZone(
CcMaxVacbLevelsSeen - 1,
00786 OldIrql,
00787
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED) )) {
00788
00789
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
00790 }
00791
00792 }
else {
00793
00794
CcAcquireVacbLock( OldIrql );
00795 }
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
if ((TempVacb =
GetVacb( SharedCacheMap, NormalOffset )) ==
NULL) {
00807
00808 Vacb->
SharedCacheMap = SharedCacheMap;
00809 Vacb->
Overlay.FileOffset = NormalOffset;
00810 Vacb->
Overlay.ActiveCount = 1;
00811
00812
SetVacb( SharedCacheMap, NormalOffset, Vacb );
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 }
else {
00824
00825
00826
00827
00828
00829
00830
if (TempVacb->
Overlay.ActiveCount == 0) {
00831 SharedCacheMap->VacbActiveCount += 1;
00832 }
00833
00834 TempVacb->
Overlay.ActiveCount += 1;
00835
00836
00837
00838
00839
00840
00841
00842
CcReleaseVacbLock( *OldIrql );
00843
00844
CcUnmapVacb( Vacb, SharedCacheMap,
FALSE );
00845
00846
CcAcquireVacbLock( OldIrql );
00847
CheckedDec(Vacb->
Overlay.ActiveCount);
00848
CheckedDec(SharedCacheMap->VacbActiveCount);
00849 Vacb->
SharedCacheMap =
NULL;
00850
00851
CcMoveVacbToReuseHead( Vacb );
00852
00853 Vacb = TempVacb;
00854 }
00855
00856
return Vacb;
00857 }
00858
00859
00860
VOID
00861
FASTCALL
00862 CcFreeVirtualAddress (
00863 IN
PVACB Vacb
00864 )
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883 {
00884 KIRQL OldIrql;
00885
PSHARED_CACHE_MAP SharedCacheMap = Vacb->SharedCacheMap;
00886
00887
CcAcquireVacbLock( &OldIrql );
00888
00889
CheckedDec(Vacb->Overlay.ActiveCount);
00890
00891
00892
00893
00894
00895
00896
if (Vacb->Overlay.ActiveCount == 0) {
00897
00898
00899
00900
00901
00902
00903
00904
if (SharedCacheMap !=
NULL) {
00905
00906
CheckedDec(SharedCacheMap->
VacbActiveCount);
00907
00908
00909
00910
00911
00912
00913
if (SharedCacheMap->
WaitOnActiveCount !=
NULL) {
00914
KeSetEvent( SharedCacheMap->
WaitOnActiveCount, 0,
FALSE );
00915 }
00916
00917
00918
00919
00920
00921
CcMoveVacbToReuseTail( Vacb );
00922
00923 }
else {
00924
00925
00926
00927
00928
00929
CcMoveVacbToReuseHead( Vacb );
00930 }
00931
00932 }
else {
00933
00934
00935
00936
00937
00938
00939
CcMoveVacbToReuseTail( Vacb );
00940 }
00941
00942
CcReleaseVacbLock( OldIrql );
00943 }
00944
00945
00946
VOID
00947 CcReferenceFileOffset (
00948 IN
PSHARED_CACHE_MAP SharedCacheMap,
00949 IN LARGE_INTEGER FileOffset
00950 )
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 {
00972 KIRQL OldIrql;
00973
00974
ASSERT(KeGetCurrentIrql() <
DISPATCH_LEVEL);
00975
00976
00977
00978
00979
00980
if (SharedCacheMap->SectionSize.QuadPart >
VACB_SIZE_OF_FIRST_LEVEL) {
00981
00982
00983
00984
00985
00986
if (!
CcPrefillVacbLevelZone(
CcMaxVacbLevelsSeen - 1,
00987 &OldIrql,
00988
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED) )) {
00989
00990
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
00991 }
00992
00993
ASSERT( FileOffset.QuadPart <= SharedCacheMap->SectionSize.QuadPart );
00994
00995
SetVacb( SharedCacheMap, FileOffset,
VACB_SPECIAL_REFERENCE );
00996
00997
CcReleaseVacbLock( OldIrql );
00998 }
00999
01000
ASSERT(KeGetCurrentIrql() <
DISPATCH_LEVEL);
01001
01002
return;
01003 }
01004
01005
01006
VOID
01007 CcDereferenceFileOffset (
01008 IN
PSHARED_CACHE_MAP SharedCacheMap,
01009 IN LARGE_INTEGER FileOffset
01010 )
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031 {
01032 KIRQL OldIrql;
01033
01034
ASSERT(KeGetCurrentIrql() <
DISPATCH_LEVEL);
01035
01036
01037
01038
01039
01040
if (SharedCacheMap->SectionSize.QuadPart >
VACB_SIZE_OF_FIRST_LEVEL) {
01041
01042
01043
01044
01045
01046
CcAcquireVacbLock( &OldIrql );
01047
01048
ASSERT( FileOffset.QuadPart <= SharedCacheMap->SectionSize.QuadPart );
01049
01050
SetVacb( SharedCacheMap, FileOffset,
VACB_SPECIAL_DEREFERENCE );
01051
01052
CcReleaseVacbLock( OldIrql );
01053 }
01054
01055
ASSERT(KeGetCurrentIrql() <
DISPATCH_LEVEL);
01056
01057
return;
01058 }
01059
01060
01061
VOID
01062 CcWaitOnActiveCount (
01063 IN
PSHARED_CACHE_MAP SharedCacheMap
01064 )
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093 {
01094 KIRQL OldIrql;
01095
PKEVENT Event;
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
CcAcquireVacbLock( &OldIrql );
01107
01108
01109
01110
01111
01112
01113
if (SharedCacheMap->VacbActiveCount != 0) {
01114
01115
if ((
Event = SharedCacheMap->WaitOnActiveCount) ==
NULL) {
01116
01117
01118
01119
01120
01121
Event = InterlockedExchangePointer( &SharedCacheMap->LocalEvent,
NULL );
01122
01123
if (
Event ==
NULL) {
01124
01125
Event = (
PKEVENT)
ExAllocatePoolWithTag(
NonPagedPoolMustSucceed,
01126
sizeof(
KEVENT),
01127 'vEcC' );
01128 }
01129 }
01130
01131
KeInitializeEvent(
Event,
01132 NotificationEvent,
01133
FALSE );
01134
01135 SharedCacheMap->WaitOnActiveCount =
Event;
01136
01137
CcReleaseVacbLock( OldIrql );
01138
01139
KeWaitForSingleObject(
Event,
01140
Executive,
01141
KernelMode,
01142
FALSE,
01143 (PLARGE_INTEGER)
NULL);
01144 }
else {
01145
01146
CcReleaseVacbLock( OldIrql );
01147 }
01148 }
01149
01150
01151
01152
01153
01154
01155
VOID
01156 CcUnmapVacb (
01157 IN
PVACB Vacb,
01158 IN
PSHARED_CACHE_MAP SharedCacheMap,
01159 IN BOOLEAN UnmapBehind
01160 )
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182 {
01183
01184
01185
01186
01187
ASSERT(SharedCacheMap !=
NULL);
01188
ASSERT(Vacb->BaseAddress !=
NULL);
01189
01190
01191
01192
01193
01194
DebugTrace( 0,
mm,
"MmUnmapViewInSystemCache:\n", 0 );
01195
DebugTrace( 0,
mm,
" BaseAddress = %08lx\n", Vacb->BaseAddress );
01196
01197
MmUnmapViewInSystemCache( Vacb->BaseAddress,
01198 SharedCacheMap->Section,
01199 UnmapBehind &&
01200
FlagOn(SharedCacheMap->Flags,
ONLY_SEQUENTIAL_ONLY_SEEN) );
01201
01202 Vacb->BaseAddress =
NULL;
01203 }
01204
01205
01206
VOID
01207
FASTCALL
01208 CcCreateVacbArray (
01209 IN
PSHARED_CACHE_MAP SharedCacheMap,
01210 IN LARGE_INTEGER NewSectionSize
01211 )
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234 {
01235
PVACB *NewAddresses;
01236 ULONG NewSize, SizeToAllocate;
01237 PLIST_ENTRY BcbListHead;
01238 BOOLEAN CreateBcbListHeads =
FALSE, CreateReference =
FALSE;
01239
01240 NewSize = SizeToAllocate =
SizeOfVacbArray(NewSectionSize);
01241
01242
01243
01244
01245
01246
01247
01248
01249
if (NewSectionSize.HighPart & ~(
PAGE_SIZE - 1)) {
01250
ExRaiseStatus(STATUS_SECTION_TOO_BIG);
01251 }
01252
01253
01254
01255
01256
01257
if (NewSize == (
PREALLOCATED_VACBS *
sizeof(
PVACB))) {
01258
01259 NewAddresses = &SharedCacheMap->InitialVacbs[0];
01260
01261
01262
01263
01264
01265 }
else {
01266
01267
01268
01269
01270
01271
01272
01273
ASSERT(
SIZE_PER_BCB_LIST == (
VACB_MAPPING_GRANULARITY * 2));
01274
01275
01276
01277
01278
01279
01280
if (NewSize >
VACB_LEVEL_BLOCK_SIZE) {
01281
01282 ULONG Level = 0;
01283 ULONG Shift =
VACB_OFFSET_SHIFT +
VACB_LEVEL_SHIFT;
01284
01285 NewSize = SizeToAllocate =
VACB_LEVEL_BLOCK_SIZE;
01286 SizeToAllocate +=
sizeof(
VACB_LEVEL_REFERENCE);
01287 CreateReference =
TRUE;
01288
01289
01290
01291
01292
01293
01294
do {
01295
01296 Level += 1;
01297 Shift +=
VACB_LEVEL_SHIFT;
01298
01299 }
while ((NewSectionSize.QuadPart > ((LONGLONG)1 << Shift)) != 0);
01300
01301
01302
01303
01304
01305
if (Level >=
CcMaxVacbLevelsSeen) {
01306
ASSERT(Level <=
VACB_NUMBER_OF_LEVELS);
01307
CcMaxVacbLevelsSeen = Level + 1;
01308 }
01309
01310 }
else {
01311
01312
01313
01314
01315
01316
if (
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED) &&
01317 (NewSectionSize.QuadPart >
BEGIN_BCB_LIST_ARRAY)) {
01318
01319 SizeToAllocate *= 2;
01320 CreateBcbListHeads =
TRUE;
01321 }
01322
01323
01324
01325
01326
01327
01328
01329
01330
if (NewSize ==
VACB_LEVEL_BLOCK_SIZE) {
01331
01332 SizeToAllocate +=
sizeof(
VACB_LEVEL_REFERENCE);
01333 CreateReference =
TRUE;
01334 }
01335 }
01336
01337 NewAddresses =
ExAllocatePoolWithTag(
NonPagedPool, SizeToAllocate, 'pVcC' );
01338
if (NewAddresses ==
NULL) {
01339 SharedCacheMap->Status = STATUS_INSUFFICIENT_RESOURCES;
01340
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
01341 }
01342 }
01343
01344
01345
01346
01347
01348 RtlZeroMemory( (PCHAR)NewAddresses, NewSize );
01349
01350
if (CreateReference) {
01351
01352 SizeToAllocate -=
sizeof(
VACB_LEVEL_REFERENCE);
01353 RtlZeroMemory( (PCHAR)NewAddresses + SizeToAllocate,
sizeof(
VACB_LEVEL_REFERENCE) );
01354 }
01355
01356
01357
01358
01359
01360
01361
if (CreateBcbListHeads) {
01362
01363
for (BcbListHead = (PLIST_ENTRY)((PCHAR)NewAddresses + NewSize);
01364 BcbListHead < (PLIST_ENTRY)((PCHAR)NewAddresses + SizeToAllocate);
01365 BcbListHead++) {
01366
01367 InsertHeadList( &SharedCacheMap->BcbList, BcbListHead );
01368 }
01369 }
01370
01371 SharedCacheMap->Vacbs = NewAddresses;
01372 SharedCacheMap->SectionSize = NewSectionSize;
01373 }
01374
01375
01376
VOID
01377 CcExtendVacbArray (
01378 IN
PSHARED_CACHE_MAP SharedCacheMap,
01379 IN LARGE_INTEGER NewSectionSize
01380 )
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403 {
01404 KIRQL OldIrql;
01405
PVACB *OldAddresses;
01406
PVACB *NewAddresses;
01407 ULONG OldSize;
01408 ULONG NewSize, SizeToAllocate;
01409 LARGE_INTEGER NextLevelSize;
01410 BOOLEAN GrowingBcbListHeads =
FALSE, CreateReference =
FALSE;
01411
01412
01413
01414
01415
01416
01417
01418
01419
if (NewSectionSize.HighPart & ~(
PAGE_SIZE - 1)) {
01420
ExRaiseStatus(STATUS_SECTION_TOO_BIG);
01421 }
01422
01423
01424
01425
01426
01427
01428
if (
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED) &&
01429 (NewSectionSize.QuadPart >
BEGIN_BCB_LIST_ARRAY)) {
01430
01431 GrowingBcbListHeads =
TRUE;
01432 }
01433
01434
01435
01436
01437
01438
if (NewSectionSize.QuadPart > SharedCacheMap->SectionSize.QuadPart) {
01439
01440
01441
01442
01443
01444
if (SharedCacheMap->SectionSize.QuadPart <
VACB_SIZE_OF_FIRST_LEVEL) {
01445
01446 NextLevelSize = NewSectionSize;
01447
01448
01449
01450
01451
01452
if (NextLevelSize.QuadPart >=
VACB_SIZE_OF_FIRST_LEVEL) {
01453 NextLevelSize.QuadPart =
VACB_SIZE_OF_FIRST_LEVEL;
01454 CreateReference =
TRUE;
01455 }
01456
01457
01458
01459
01460
01461
01462
01463 NewSize = SizeToAllocate =
SizeOfVacbArray(NextLevelSize);
01464 OldSize =
SizeOfVacbArray(SharedCacheMap->SectionSize);
01465
01466
01467
01468
01469
01470
if (NewSize > OldSize) {
01471
01472
01473
01474
01475
01476
if (GrowingBcbListHeads) {
01477 SizeToAllocate *= 2;
01478 }
01479
01480
01481
01482
01483
01484
if (CreateReference) {
01485 SizeToAllocate +=
sizeof(
VACB_LEVEL_REFERENCE);
01486 }
01487
01488 NewAddresses =
FsRtlAllocatePoolWithTag(
NonPagedPool, SizeToAllocate, 'pVcC' );
01489
01490
01491
01492
01493
01494
01495
if (GrowingBcbListHeads) {
01496
01497 ExAcquireSpinLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
01498
CcAcquireVacbLockAtDpcLevel();
01499
01500 }
else {
01501
01502
01503
01504
01505
01506
01507
CcAcquireVacbLock( &OldIrql );
01508 }
01509
01510 OldAddresses = SharedCacheMap->Vacbs;
01511
if (OldAddresses !=
NULL) {
01512 RtlCopyMemory( NewAddresses, OldAddresses, OldSize );
01513 }
else {
01514 OldSize = 0;
01515 }
01516
01517 RtlZeroMemory( (PCHAR)NewAddresses + OldSize, NewSize - OldSize );
01518
01519
if (CreateReference) {
01520
01521 SizeToAllocate -=
sizeof(
VACB_LEVEL_REFERENCE);
01522 RtlZeroMemory( (PCHAR)NewAddresses + SizeToAllocate,
sizeof(
VACB_LEVEL_REFERENCE) );
01523 }
01524
01525
01526
01527
01528
01529
if (GrowingBcbListHeads) {
01530
01531 LARGE_INTEGER
Offset;
01532 PLIST_ENTRY BcbListHeadNew, TempEntry;
01533
01534
Offset.QuadPart = 0;
01535 BcbListHeadNew = (PLIST_ENTRY)((PCHAR)NewAddresses + NewSize );
01536
01537
01538
01539
01540
01541
if ((SharedCacheMap->SectionSize.QuadPart >
BEGIN_BCB_LIST_ARRAY) &&
01542 (OldAddresses !=
NULL)) {
01543
01544 PLIST_ENTRY BcbListHeadOld;
01545
01546 BcbListHeadOld = (PLIST_ENTRY)((PCHAR)OldAddresses + OldSize);
01547
01548
01549
01550
01551
01552
01553
do {
01554 TempEntry = BcbListHeadOld->Flink;
01555 RemoveEntryList( BcbListHeadOld );
01556 InsertTailList( TempEntry, BcbListHeadNew );
01557
Offset.QuadPart +=
SIZE_PER_BCB_LIST;
01558 BcbListHeadOld += 1;
01559 BcbListHeadNew += 1;
01560 }
while (
Offset.QuadPart < SharedCacheMap->SectionSize.QuadPart);
01561
01562
01563
01564
01565
01566
01567 }
else {
01568
01569 TempEntry = SharedCacheMap->BcbList.Blink;
01570
01571
01572
01573
01574
01575
while (TempEntry != &SharedCacheMap->BcbList) {
01576
01577
01578
01579
01580
01581
01582
while (
Offset.QuadPart <= ((
PBCB)CONTAINING_RECORD(TempEntry,
BCB, BcbLinks))->FileOffset.QuadPart) {
01583
01584 InsertHeadList(TempEntry, BcbListHeadNew);
01585
Offset.QuadPart +=
SIZE_PER_BCB_LIST;
01586 BcbListHeadNew += 1;
01587 }
01588 TempEntry = TempEntry->Blink;
01589 }
01590 }
01591
01592
01593
01594
01595
01596
01597
while (
Offset.QuadPart < NextLevelSize.QuadPart) {
01598
01599 InsertHeadList(&SharedCacheMap->BcbList, BcbListHeadNew);
01600
Offset.QuadPart +=
SIZE_PER_BCB_LIST;
01601 BcbListHeadNew += 1;
01602 }
01603 }
01604
01605
01606
01607
01608
01609 SharedCacheMap->Vacbs = NewAddresses;
01610 SharedCacheMap->SectionSize = NextLevelSize;
01611
01612
01613
01614
01615
01616
if (GrowingBcbListHeads) {
01617
CcReleaseVacbLockFromDpcLevel();
01618 ExReleaseSpinLock( &SharedCacheMap->BcbSpinLock, OldIrql );
01619 }
else {
01620
CcReleaseVacbLock( OldIrql );
01621 }
01622
01623
if ((OldAddresses != &SharedCacheMap->InitialVacbs[0]) &&
01624 (OldAddresses !=
NULL)) {
01625
ExFreePool( OldAddresses );
01626 }
01627 }
01628
01629
01630
01631
01632
01633
01634
01635 SharedCacheMap->SectionSize = NextLevelSize;
01636 }
01637
01638
01639
01640
01641
01642
01643
01644
01645
if (NewSectionSize.QuadPart > SharedCacheMap->SectionSize.QuadPart) {
01646
01647
PVACB *NextVacbArray;
01648 ULONG NewLevel;
01649 ULONG Level = 1;
01650 ULONG Shift =
VACB_OFFSET_SHIFT +
VACB_LEVEL_SHIFT;
01651
01652
01653
01654
01655
01656
while (SharedCacheMap->SectionSize.QuadPart > ((LONGLONG)1 << Shift)) {
01657
01658 Level += 1;
01659 Shift +=
VACB_LEVEL_SHIFT;
01660 }
01661
01662 NewLevel = Level;
01663
01664
01665
01666
01667
01668
while (((NewSectionSize.QuadPart - 1) >> Shift) != 0) {
01669
01670 NewLevel += 1;
01671 Shift +=
VACB_LEVEL_SHIFT;
01672 }
01673
01674
01675
01676
01677
01678
if (NewLevel > Level) {
01679
01680
01681
01682
01683
01684
if (NewLevel >=
CcMaxVacbLevelsSeen) {
01685
ASSERT(NewLevel <=
VACB_NUMBER_OF_LEVELS);
01686
CcMaxVacbLevelsSeen = NewLevel + 1;
01687 }
01688
01689
01690
01691
01692
01693
if (!
CcPrefillVacbLevelZone( NewLevel - Level, &OldIrql,
FALSE )) {
01694
01695
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
01696 }
01697
01698
01699
01700
01701
01702
01703
01704
if (Level == 1) {
01705
01706
01707
01708
01709
01710
CcCalculateVacbLevelLockCount( SharedCacheMap, SharedCacheMap->Vacbs, 0 );
01711 }
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
if (
IsVacbLevelReferenced( SharedCacheMap, SharedCacheMap->Vacbs, Level - 1 )) {
01722
01723
while (NewLevel > Level++) {
01724
01725
ASSERT(
CcVacbLevelEntries != 0);
01726 NextVacbArray =
CcAllocateVacbLevel(
FALSE);
01727
01728 NextVacbArray[0] = (
PVACB)SharedCacheMap->Vacbs;
01729
ReferenceVacbLevel( SharedCacheMap, NextVacbArray, Level, 1,
FALSE );
01730
01731 SharedCacheMap->Vacbs = NextVacbArray;
01732 }
01733
01734 }
else {
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
if (Level == 1 &&
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED)) {
01746
01747 PLIST_ENTRY PredecessorListHead, SuccessorListHead;
01748
01749 NextVacbArray = SharedCacheMap->Vacbs;
01750 SharedCacheMap->Vacbs =
CcAllocateVacbLevel(
FALSE);
01751
01752 PredecessorListHead = ((PLIST_ENTRY)((PCHAR)NextVacbArray +
VACB_LEVEL_BLOCK_SIZE))->Flink;
01753 SuccessorListHead = ((PLIST_ENTRY)((PCHAR)NextVacbArray + (
VACB_LEVEL_BLOCK_SIZE * 2) -
sizeof(LIST_ENTRY)))->Blink;
01754 PredecessorListHead->Blink = SuccessorListHead;
01755 SuccessorListHead->Flink = PredecessorListHead;
01756
01757
CcDeallocateVacbLevel( NextVacbArray,
TRUE );
01758 }
01759 }
01760
01761
01762
01763
01764
01765
01766 SharedCacheMap->SectionSize = NewSectionSize;
01767
CcReleaseVacbLock( OldIrql );
01768 }
01769
01770
01771
01772
01773
01774
01775
01776 SharedCacheMap->SectionSize = NewSectionSize;
01777 }
01778 }
01779 }
01780
01781
01782 BOOLEAN
01783
FASTCALL
01784 CcUnmapVacbArray (
01785 IN
PSHARED_CACHE_MAP SharedCacheMap,
01786 IN PLARGE_INTEGER FileOffset OPTIONAL,
01787 IN ULONG Length,
01788 IN BOOLEAN UnmapBehind
01789 )
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817 {
01818
PVACB Vacb;
01819 KIRQL OldIrql;
01820 LARGE_INTEGER StartingFileOffset = {0,0};
01821 LARGE_INTEGER EndingFileOffset = SharedCacheMap->SectionSize;
01822
01823
01824
01825
01826
01827
if (SharedCacheMap->Vacbs ==
NULL) {
01828
return TRUE;
01829 }
01830
01831
01832
01833
01834
01835
01836
if (ARGUMENT_PRESENT(FileOffset)) {
01837 StartingFileOffset.QuadPart = ((FileOffset->QuadPart) & (~((LONGLONG)
VACB_MAPPING_GRANULARITY - 1)));
01838
if (Length != 0) {
01839
01840 EndingFileOffset.QuadPart = FileOffset->QuadPart + Length;
01841
01842 }
01843 }
01844
01845
01846
01847
01848
01849
CcAcquireVacbLock( &OldIrql );
01850
01851
while (StartingFileOffset.QuadPart < EndingFileOffset.QuadPart) {
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
if ((StartingFileOffset.QuadPart < SharedCacheMap->SectionSize.QuadPart) &&
01864 ((Vacb =
GetVacb( SharedCacheMap, StartingFileOffset )) !=
NULL)) {
01865
01866
01867
01868
01869
01870
01871
01872
if (Vacb->
Overlay.ActiveCount != 0) {
01873
01874
CcReleaseVacbLock( OldIrql );
01875
return FALSE;
01876 }
01877
01878
01879
01880
01881
01882
01883
SetVacb( SharedCacheMap, StartingFileOffset,
NULL );
01884 Vacb->
SharedCacheMap =
NULL;
01885
01886
01887
01888
01889
01890
01891 Vacb->
Overlay.ActiveCount += 1;
01892
01893
01894
01895
01896
01897
CcReleaseVacbLock( OldIrql );
01898
01899
01900
01901
01902
01903
CcUnmapVacb( Vacb, SharedCacheMap, UnmapBehind );
01904
01905
01906
01907
01908
01909
CcAcquireVacbLock( &OldIrql );
01910 Vacb->
Overlay.ActiveCount -= 1;
01911
01912
01913
01914
01915
01916
CcMoveVacbToReuseHead( Vacb );
01917 }
01918
01919 StartingFileOffset.QuadPart = StartingFileOffset.QuadPart +
VACB_MAPPING_GRANULARITY;
01920 }
01921
01922
CcReleaseVacbLock( OldIrql );
01923
01924
CcDrainVacbLevelZone();
01925
01926
return TRUE;
01927 }
01928
01929
01930 ULONG
01931 CcPrefillVacbLevelZone (
01932 IN ULONG NumberNeeded,
01933 OUT PKIRQL OldIrql,
01934 IN ULONG NeedBcbListHeads
01935 )
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968 {
01969
PVACB *NextVacbArray;
01970
01971
CcAcquireVacbLock( OldIrql );
01972
01973
01974
01975
01976
01977
while ((NumberNeeded >
CcVacbLevelEntries) ||
01978 (NeedBcbListHeads && (
CcVacbLevelWithBcbsFreeList ==
NULL))) {
01979
01980
01981
01982
01983
01984
01985
CcReleaseVacbLock( *OldIrql );
01986
01987
01988
01989
01990
01991
01992
if (NeedBcbListHeads && (
CcVacbLevelWithBcbsFreeList ==
NULL)) {
01993
01994
01995
01996
01997
01998
01999 NextVacbArray =
02000 (
PVACB *)
ExAllocatePoolWithTag(
NonPagedPool, (
VACB_LEVEL_BLOCK_SIZE * 2) +
sizeof(
VACB_LEVEL_REFERENCE), 'lVcC' );
02001
02002
if (NextVacbArray ==
NULL) {
02003
return FALSE;
02004 }
02005
02006 RtlZeroMemory( (PCHAR)NextVacbArray,
VACB_LEVEL_BLOCK_SIZE );
02007 RtlZeroMemory( (PCHAR)NextVacbArray + (
VACB_LEVEL_BLOCK_SIZE * 2),
sizeof(
VACB_LEVEL_REFERENCE) );
02008
02009
CcAcquireVacbLock( OldIrql );
02010
02011 NextVacbArray[0] = (
PVACB)
CcVacbLevelWithBcbsFreeList;
02012
CcVacbLevelWithBcbsFreeList = NextVacbArray;
02013
CcVacbLevelWithBcbsEntries += 1;
02014
02015 }
else {
02016
02017
02018
02019
02020
02021
02022 NextVacbArray =
02023 (
PVACB *)
ExAllocatePoolWithTag(
NonPagedPool,
VACB_LEVEL_BLOCK_SIZE +
sizeof(
VACB_LEVEL_REFERENCE), 'lVcC' );
02024
02025
if (NextVacbArray ==
NULL) {
02026
return FALSE;
02027 }
02028
02029 RtlZeroMemory( (PCHAR)NextVacbArray,
VACB_LEVEL_BLOCK_SIZE +
sizeof(
VACB_LEVEL_REFERENCE) );
02030
02031
CcAcquireVacbLock( OldIrql );
02032
02033 NextVacbArray[0] = (
PVACB)
CcVacbLevelFreeList;
02034
CcVacbLevelFreeList = NextVacbArray;
02035
CcVacbLevelEntries += 1;
02036 }
02037 }
02038
02039
return TRUE;
02040 }
02041
02042
02043
VOID
02044 CcDrainVacbLevelZone (
02045 )
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066 {
02067 KIRQL OldIrql;
02068
PVACB *NextVacbArray;
02069
02070
02071
02072
02073
02074
02075
while ((
CcVacbLevelEntries > (
CcMaxVacbLevelsSeen * 4)) ||
02076 (
CcVacbLevelWithBcbsEntries > 2)) {
02077
02078
02079
02080
02081
02082 NextVacbArray =
NULL;
02083
CcAcquireVacbLock( &OldIrql );
02084
if (
CcVacbLevelEntries > (
CcMaxVacbLevelsSeen * 4)) {
02085 NextVacbArray =
CcVacbLevelFreeList;
02086
CcVacbLevelFreeList = (
PVACB *)NextVacbArray[0];
02087
CcVacbLevelEntries -= 1;
02088 }
else if (
CcVacbLevelWithBcbsEntries > 2) {
02089 NextVacbArray =
CcVacbLevelWithBcbsFreeList;
02090
CcVacbLevelWithBcbsFreeList = (
PVACB *)NextVacbArray[0];
02091
CcVacbLevelWithBcbsEntries -= 1;
02092 }
02093
CcReleaseVacbLock( OldIrql );
02094
02095
02096
02097
02098
02099
if (NextVacbArray !=
NULL) {
02100
ExFreePool(NextVacbArray);
02101 }
02102 }
02103 }
02104
02105
02106 PLIST_ENTRY
02107 CcGetBcbListHeadLargeOffset (
02108 IN
PSHARED_CACHE_MAP SharedCacheMap,
02109 IN LONGLONG FileOffset,
02110 IN BOOLEAN FailToSuccessor
02111 )
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141 {
02142 ULONG Level, Shift;
02143
PVACB *VacbArray, *NextVacbArray;
02144 ULONG
Index;
02145 ULONG SavedIndexes[
VACB_NUMBER_OF_LEVELS];
02146
PVACB *SavedVacbArrays[
VACB_NUMBER_OF_LEVELS];
02147 ULONG SavedLevels = 0;
02148
02149
02150
02151
02152
02153 Level = 0;
02154 Shift =
VACB_OFFSET_SHIFT +
VACB_LEVEL_SHIFT;
02155 VacbArray = SharedCacheMap->Vacbs;
02156
02157
02158
02159
02160
02161
02162
ASSERT(SharedCacheMap->SectionSize.QuadPart >
VACB_SIZE_OF_FIRST_LEVEL);
02163
02164
02165
02166
02167
02168
02169
do {
02170
02171 Level += 1;
02172 Shift +=
VACB_LEVEL_SHIFT;
02173
02174 }
while (SharedCacheMap->SectionSize.QuadPart > ((LONGLONG)1 << Shift));
02175
02176
02177
02178
02179
02180
02181
if (FileOffset >= ((LONGLONG)1 << Shift)) {
02182
return &SharedCacheMap->BcbList;
02183 }
02184
02185
02186
02187
02188
02189 Shift -=
VACB_LEVEL_SHIFT;
02190
do {
02191
02192
02193
02194
02195
02196 Level -= 1;
02197
02198
02199
02200
02201
02202
Index = (ULONG)(FileOffset >> Shift);
02203
ASSERT(
Index <=
VACB_LAST_INDEX_FOR_LEVEL);
02204
02205
02206
02207
02208
02209 NextVacbArray = (
PVACB *)VacbArray[
Index];
02210
02211
02212
02213
02214
02215
02216
if (NextVacbArray ==
NULL) {
02217
02218
02219
02220
02221
02222
02223
while (
TRUE) {
02224
02225
02226
02227
02228
02229
if (FailToSuccessor) {
02230
02231
if (
Index !=
VACB_LAST_INDEX_FOR_LEVEL) {
02232
02233
while ((
Index !=
VACB_LAST_INDEX_FOR_LEVEL) && (VacbArray[++
Index] ==
NULL)) {
02234
continue;
02235 }
02236
02237
02238
02239
02240
02241
02242
if ((NextVacbArray = (
PVACB *)VacbArray[
Index]) !=
NULL) {
02243
break;
02244 }
02245 }
02246
02247 }
else {
02248
02249
if (
Index != 0) {
02250
02251
while ((
Index != 0) && (VacbArray[--
Index] ==
NULL)) {
02252
continue;
02253 }
02254
02255
02256
02257
02258
02259
02260
if ((NextVacbArray = (
PVACB *)VacbArray[
Index]) !=
NULL) {
02261
break;
02262 }
02263 }
02264 }
02265
02266
02267
02268
02269
02270
02271
if (SavedLevels == 0) {
02272
return &SharedCacheMap->BcbList;
02273 }
02274
02275
02276
02277
02278
02279
02280 Level += 1;
02281
Index = SavedIndexes[--SavedLevels];
02282 VacbArray = SavedVacbArrays[SavedLevels];
02283 }
02284
02285
02286
02287
02288
02289
02290
02291
if (FailToSuccessor) {
02292 FileOffset = 0;
02293 }
else {
02294 FileOffset = MAXLONGLONG;
02295 }
02296 }
02297
02298
02299
02300
02301
02302
02303 SavedIndexes[SavedLevels] =
Index;
02304 SavedVacbArrays[SavedLevels] = VacbArray;
02305 SavedLevels += 1;
02306
02307
02308
02309
02310
02311
02312 VacbArray = NextVacbArray;
02313 FileOffset &= ((LONGLONG)1 << Shift) - 1;
02314 Shift -=
VACB_LEVEL_SHIFT;
02315
02316
02317
02318
02319
02320 }
while (Level != 0);
02321
02322
02323
02324
02325
02326
02327
02328
02329
Index = (ULONG)(FileOffset >> Shift);
02330
return (PLIST_ENTRY)((PCHAR)&VacbArray[
Index & ~1] +
VACB_LEVEL_BLOCK_SIZE);
02331 }
02332
02333
02334
VOID
02335 CcAdjustVacbLevelLockCount (
02336 IN
PSHARED_CACHE_MAP SharedCacheMap,
02337 IN LONGLONG FileOffset,
02338 IN LONG Adjustment
02339 )
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368 {
02369 ULONG Level, Shift;
02370
PVACB *VacbArray;
02371 LONGLONG OriginalFileOffset = FileOffset;
02372
02373
02374
02375
02376
02377 Level = 0;
02378 Shift =
VACB_OFFSET_SHIFT +
VACB_LEVEL_SHIFT;
02379
02380 VacbArray = SharedCacheMap->Vacbs;
02381
02382
02383
02384
02385
02386
02387
ASSERT(SharedCacheMap->SectionSize.QuadPart >
VACB_SIZE_OF_FIRST_LEVEL);
02388
02389
02390
02391
02392
02393
02394
do {
02395
02396 Level += 1;
02397 Shift +=
VACB_LEVEL_SHIFT;
02398
02399 }
while (SharedCacheMap->SectionSize.QuadPart > ((LONGLONG)1 << Shift));
02400
02401
02402
02403
02404
02405 Shift -=
VACB_LEVEL_SHIFT;
02406
do {
02407
02408 VacbArray = (
PVACB *)VacbArray[(ULONG)(FileOffset >> Shift)];
02409
02410 Level -= 1;
02411
02412 FileOffset &= ((LONGLONG)1 << Shift) - 1;
02413
02414 Shift -=
VACB_LEVEL_SHIFT;
02415
02416 }
while (Level != 0);
02417
02418
02419
02420
02421
02422
ReferenceVacbLevel( SharedCacheMap, VacbArray, Level, Adjustment,
FALSE );
02423
02424
02425
02426
02427
02428
02429
02430
if (!
IsVacbLevelReferenced( SharedCacheMap, VacbArray, Level )) {
02431
ReferenceVacbLevel( SharedCacheMap, VacbArray, Level, 1,
TRUE );
02432 OriginalFileOffset &= ~(
VACB_SIZE_OF_FIRST_LEVEL - 1);
02433
CcSetVacbLargeOffset( SharedCacheMap, OriginalFileOffset,
VACB_SPECIAL_DEREFERENCE );
02434 }
02435 }
02436
02437
02438
VOID
02439 CcCalculateVacbLevelLockCount (
02440 IN
PSHARED_CACHE_MAP SharedCacheMap,
02441 IN
PVACB *VacbArray,
02442 IN ULONG Level
02443 )
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473 {
02474
PBCB Bcb;
02475 ULONG
Index;
02476 LONG
Count = 0;
02477
PVACB *VacbTemp = VacbArray;
02478
PVACB_LEVEL_REFERENCE VacbReference;
02479
02480
02481
02482
02483
02484
for (
Index = 0;
Index <=
VACB_LAST_INDEX_FOR_LEVEL;
Index++) {
02485
if (*(VacbTemp++) !=
NULL) {
02486
Count += 1;
02487 }
02488 }
02489
02490
02491
02492
02493
02494
02495
if (
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED) && (Level == 0)) {
02496
02497
02498
02499
02500
02501 Bcb = (
PBCB)CONTAINING_RECORD(((PLIST_ENTRY)VacbTemp)->Blink,
BCB, BcbLinks);
02502
Index = 0;
02503
02504
02505
02506
02507
02508
02509
02510
02511
do {
02512
02513
if (Bcb->
NodeTypeCode ==
CACHE_NTC_BCB) {
02514
Count += 1;
02515 }
else {
02516
Index += 1;
02517 }
02518
02519 Bcb = (
PBCB)CONTAINING_RECORD(Bcb->
BcbLinks.Blink,
BCB, BcbLinks);
02520
02521 }
while (
Index <= (
VACB_LAST_INDEX_FOR_LEVEL / 2));
02522 }
02523
02524
02525
02526
02527
02528 VacbReference =
VacbLevelReference( SharedCacheMap, VacbArray, Level );
02529 VacbReference->
Reference =
Count;
02530 }
02531
02532
02533
PVACB
02534 CcGetVacbLargeOffset (
02535 IN
PSHARED_CACHE_MAP SharedCacheMap,
02536 IN LONGLONG FileOffset
02537 )
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563 {
02564 ULONG Level, Shift;
02565
PVACB *VacbArray;
02566
PVACB Vacb;
02567
02568
02569
02570
02571
02572 Level = 0;
02573 Shift =
VACB_OFFSET_SHIFT +
VACB_LEVEL_SHIFT;
02574 VacbArray = SharedCacheMap->Vacbs;
02575
02576
02577
02578
02579
02580
02581
ASSERT(SharedCacheMap->SectionSize.QuadPart >
VACB_SIZE_OF_FIRST_LEVEL);
02582
02583
02584
02585
02586
02587
02588
do {
02589
02590 Level += 1;
02591 Shift +=
VACB_LEVEL_SHIFT;
02592
02593 }
while (SharedCacheMap->SectionSize.QuadPart > ((LONGLONG)1 << Shift));
02594
02595
02596
02597
02598
02599 Shift -=
VACB_LEVEL_SHIFT;
02600
while (((Vacb = (
PVACB)VacbArray[FileOffset >> Shift]) !=
NULL) && (Level != 0)) {
02601
02602 Level -= 1;
02603
02604 VacbArray = (
PVACB *)Vacb;
02605 FileOffset &= ((LONGLONG)1 << Shift) - 1;
02606
02607 Shift -=
VACB_LEVEL_SHIFT;
02608 }
02609
02610
02611
02612
02613
02614
ASSERT(Vacb ==
NULL || ((Vacb >=
CcVacbs) && (Vacb <
CcBeyondVacbs)));
02615
02616
return Vacb;
02617 }
02618
02619
02620
VOID
02621 CcSetVacbLargeOffset (
02622 IN
PSHARED_CACHE_MAP SharedCacheMap,
02623 IN LONGLONG FileOffset,
02624 IN
PVACB Vacb
02625 )
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661 {
02662 ULONG Level, Shift;
02663
PVACB *VacbArray, *NextVacbArray;
02664 ULONG
Index;
02665 ULONG SavedIndexes[
VACB_NUMBER_OF_LEVELS];
02666
PVACB *SavedVacbArrays[
VACB_NUMBER_OF_LEVELS];
02667 PLIST_ENTRY PredecessorListHead, SuccessorListHead, CurrentListHead;
02668 BOOLEAN AllocatingBcbListHeads, Special =
FALSE;
02669 LONGLONG OriginalFileOffset = FileOffset;
02670 ULONG SavedLevels = 0;
02671
02672
02673
02674
02675
02676 Level = 0;
02677 Shift =
VACB_OFFSET_SHIFT +
VACB_LEVEL_SHIFT;
02678 VacbArray = SharedCacheMap->Vacbs;
02679
02680
02681
02682
02683
02684
02685
ASSERT(SharedCacheMap->SectionSize.QuadPart >
VACB_SIZE_OF_FIRST_LEVEL);
02686
02687
02688
02689
02690
02691
02692
do {
02693
02694 Level += 1;
02695 Shift +=
VACB_LEVEL_SHIFT;
02696
02697 }
while (SharedCacheMap->SectionSize.QuadPart > ((LONGLONG)1 << Shift));
02698
02699
02700
02701
02702
02703 Shift -=
VACB_LEVEL_SHIFT;
02704
do {
02705
02706
02707
02708
02709
02710 Level -= 1;
02711
02712
02713
02714
02715
02716
Index = (ULONG)(FileOffset >> Shift);
02717
ASSERT(
Index <=
VACB_LAST_INDEX_FOR_LEVEL);
02718
02719
02720
02721
02722
02723
02724 SavedIndexes[SavedLevels] =
Index;
02725 SavedVacbArrays[SavedLevels] = VacbArray;
02726 SavedLevels += 1;
02727
02728
02729
02730
02731
02732 NextVacbArray = (
PVACB *)VacbArray[
Index];
02733
02734
02735
02736
02737
02738
if (NextVacbArray ==
NULL) {
02739
02740
02741
02742
02743
02744
02745
ASSERT( Vacb !=
VACB_SPECIAL_DEREFERENCE );
02746
02747 AllocatingBcbListHeads =
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED) && (Level == 0);
02748
02749
02750
02751
02752
02753
ASSERT(Vacb !=
NULL);
02754
02755 NextVacbArray =
CcAllocateVacbLevel(AllocatingBcbListHeads);
02756
02757
02758
02759
02760
02761
if (AllocatingBcbListHeads) {
02762
02763 ULONG i;
02764
02765
02766
02767
02768
02769 PredecessorListHead =
CcGetBcbListHeadLargeOffset( SharedCacheMap, OriginalFileOffset,
FALSE );
02770
02771
02772
02773
02774
02775
02776
while (((
PBCB)CONTAINING_RECORD(PredecessorListHead->Blink,
BCB, BcbLinks))->NodeTypeCode ==
02777
CACHE_NTC_BCB) {
02778 PredecessorListHead = (PLIST_ENTRY)PredecessorListHead->Blink;
02779 }
02780
02781
02782
02783
02784
02785 CurrentListHead = (PLIST_ENTRY)((PCHAR)NextVacbArray +
VACB_LEVEL_BLOCK_SIZE);
02786
02787
02788
02789
02790
02791 SuccessorListHead = PredecessorListHead->Blink;
02792 PredecessorListHead->Blink = CurrentListHead;
02793 CurrentListHead->Flink = PredecessorListHead;
02794
02795
02796
02797
02798
02799
for (i = 0; i < ((
VACB_LEVEL_BLOCK_SIZE /
sizeof(LIST_ENTRY) - 1)); i++) {
02800
02801 CurrentListHead->Blink = CurrentListHead + 1;
02802 CurrentListHead += 1;
02803 CurrentListHead->Flink = CurrentListHead - 1;
02804 }
02805
02806
02807
02808
02809
02810 CurrentListHead->Blink = SuccessorListHead;
02811 SuccessorListHead->Flink = CurrentListHead;
02812 }
02813
02814 VacbArray[
Index] = (
PVACB)NextVacbArray;
02815
02816
02817
02818
02819
02820
02821
ReferenceVacbLevel( SharedCacheMap, VacbArray, Level + 1, 1,
FALSE );
02822 }
02823
02824
02825
02826
02827
02828
02829 VacbArray = NextVacbArray;
02830 FileOffset &= ((LONGLONG)1 << Shift) - 1;
02831 Shift -=
VACB_LEVEL_SHIFT;
02832
02833
02834
02835
02836
02837 }
while (Level != 0);
02838
02839
if (Vacb <
VACB_SPECIAL_FIRST_VALID) {
02840
02841
02842
02843
02844
02845
Index = (ULONG)(FileOffset >> Shift);
02846 VacbArray[
Index] = Vacb;
02847
02848
02849
02850
02851
02852 }
else {
02853
02854 Special =
TRUE;
02855
02856
02857
02858
02859
02860
if (Vacb ==
VACB_SPECIAL_DEREFERENCE) {
02861
02862 Vacb =
NULL;
02863 }
02864 }
02865
02866
02867
02868
02869
02870
if (Vacb !=
NULL) {
02871
02872
ASSERT( !(Special && Level != 0) );
02873
02874
ReferenceVacbLevel( SharedCacheMap, VacbArray, Level, 1, Special );
02875
02876
02877
02878
02879
02880
02881 }
else {
02882
02883
02884
02885
02886
02887
while (
TRUE) {
02888
02889
ReferenceVacbLevel( SharedCacheMap, VacbArray, Level, -1, Special );
02890
02891
02892
02893
02894
02895
02896
02897 Special =
FALSE;
02898
02899
02900
02901
02902
02903
02904
if (!
IsVacbLevelReferenced( SharedCacheMap, VacbArray, Level ) && (SavedLevels != 0)) {
02905
02906 SavedLevels -= 1;
02907
02908
02909
02910
02911
02912
02913 AllocatingBcbListHeads =
FALSE;
02914
if ((Level++ == 0) &&
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED)) {
02915
02916 AllocatingBcbListHeads =
TRUE;
02917 PredecessorListHead = ((PLIST_ENTRY)((PCHAR)VacbArray +
VACB_LEVEL_BLOCK_SIZE))->Flink;
02918 SuccessorListHead = ((PLIST_ENTRY)((PCHAR)VacbArray + (
VACB_LEVEL_BLOCK_SIZE * 2) -
sizeof(LIST_ENTRY)))->Blink;
02919 PredecessorListHead->Blink = SuccessorListHead;
02920 SuccessorListHead->Flink = PredecessorListHead;
02921 }
02922
02923
02924
02925
02926
02927
02928
CcDeallocateVacbLevel( VacbArray, AllocatingBcbListHeads );
02929
Index = SavedIndexes[SavedLevels];
02930 VacbArray = SavedVacbArrays[SavedLevels];
02931 VacbArray[
Index] =
NULL;
02932
02933
02934
02935
02936
02937 }
else {
02938
break;
02939 }
02940 }
02941 }
02942 }
02943