00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "cc.h"
00022
00023
00024
00025
00026
00027 #define BugCheckFileId (CACHE_BUG_CHECK_CACHESUB)
00028
00029
00030
00031
00032
00033 #define me 0x00000002
00034
00035
00036
00037
00038
00039 #define RetryError(STS) (((STS) == STATUS_VERIFY_REQUIRED) || ((STS) == STATUS_FILE_LOCK_CONFLICT))
00040
00041 ULONG
CcMaxDirtyWrite = 0x10000;
00042
00043
00044
00045
00046
00047 BOOLEAN
00048
CcFindBcb (
00049 IN
PSHARED_CACHE_MAP SharedCacheMap,
00050 IN PLARGE_INTEGER FileOffset,
00051 IN OUT PLARGE_INTEGER BeyondLastByte,
00052 OUT
PBCB *Bcb
00053 );
00054
00055
PBCB
00056
CcAllocateInitializeBcb (
00057 IN OUT
PSHARED_CACHE_MAP SharedCacheMap OPTIONAL,
00058 IN OUT
PBCB AfterBcb,
00059 IN PLARGE_INTEGER FileOffset,
00060 IN PLARGE_INTEGER Length
00061 );
00062
00063
NTSTATUS
00064
CcSetValidData (
00065 IN
PFILE_OBJECT FileObject,
00066 IN PLARGE_INTEGER ValidDataLength
00067 );
00068
00069 BOOLEAN
00070
CcAcquireByteRangeForWrite (
00071 IN
PSHARED_CACHE_MAP SharedCacheMap,
00072 IN PLARGE_INTEGER TargetOffset OPTIONAL,
00073 IN ULONG TargetLength,
00074 OUT PLARGE_INTEGER FileOffset,
00075 OUT PULONG Length,
00076 OUT
PBCB *FirstBcb
00077 );
00078
00079
VOID
00080
CcReleaseByteRangeFromWrite (
00081 IN
PSHARED_CACHE_MAP SharedCacheMap,
00082 IN PLARGE_INTEGER FileOffset,
00083 IN ULONG Length,
00084 IN
PBCB FirstBcb,
00085 IN BOOLEAN VerifyRequired
00086 );
00087
00088
PBITMAP_RANGE
00089
CcFindBitmapRangeToDirty (
00090 IN
PMBCB Mbcb,
00091 IN LONGLONG Page,
00092 IN PULONG *FreePageForSetting
00093 );
00094
00095
PBITMAP_RANGE
00096
CcFindBitmapRangeToClean (
00097 IN
PMBCB Mbcb,
00098 IN LONGLONG Page
00099 );
00100
00101 BOOLEAN
00102
CcLogError(
00103 IN
PDEVICE_OBJECT Device,
00104 IN NTSTATUS Error,
00105 IN NTSTATUS DeviceError,
00106 IN PUNICODE_STRING FileName
00107 );
00108
00109
00110
00111
00112
00113
00114
00115 BOOLEAN
00116 CcPinFileData (
00117 IN
PFILE_OBJECT FileObject,
00118 IN PLARGE_INTEGER FileOffset,
00119 IN ULONG Length,
00120 IN BOOLEAN ReadOnly,
00121 IN BOOLEAN WriteOnly,
00122 IN ULONG Flags,
00123 OUT
PBCB *Bcb,
00124 OUT PVOID *BaseAddress,
00125 OUT PLARGE_INTEGER BeyondLastByte
00126 )
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 {
00222
PSHARED_CACHE_MAP SharedCacheMap;
00223 LARGE_INTEGER TrialBound;
00224 KIRQL OldIrql;
00225
PBCB BcbOut =
NULL;
00226 ULONG ZeroFlags = 0;
00227 BOOLEAN SpinLockAcquired =
FALSE;
00228 BOOLEAN Result =
FALSE;
00229
00230 ULONG ReceivedLength;
00231 ULONG ActivePage;
00232 ULONG PageIsDirty;
00233
PVACB Vacb =
NULL;
00234
00235
DebugTrace(+1,
me,
"CcPinFileData:\n", 0 );
00236
DebugTrace( 0,
me,
" FileObject = %08lx\n", FileObject );
00237
DebugTrace2(0,
me,
" FileOffset = %08lx, %08lx\n", FileOffset->LowPart,
00238 FileOffset->HighPart );
00239
DebugTrace( 0,
me,
" Length = %08lx\n", Length );
00240
DebugTrace( 0,
me,
" Flags = %02lx\n", Flags );
00241
00242
00243
00244
00245
00246 SharedCacheMap = *(
PSHARED_CACHE_MAP *)((PCHAR)FileObject->SectionObjectPointer
00247 +
sizeof(PVOID));
00248
00249
00250
00251
00252
00253
GetActiveVacb( SharedCacheMap, OldIrql, Vacb, ActivePage, PageIsDirty );
00254
00255
00256
00257
00258
00259
00260
00261
if ((Vacb !=
NULL) || (SharedCacheMap->
NeedToZero !=
NULL)) {
00262
00263
CcFreeActiveVacb( SharedCacheMap, Vacb, ActivePage, PageIsDirty );
00264 Vacb =
NULL;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
ASSERT( ( FileOffset->QuadPart + (LONGLONG)Length ) <=
00274 SharedCacheMap->
SectionSize.QuadPart );
00275
00276
00277
00278
00279
00280 *Bcb =
NULL;
00281 *BaseAddress =
NULL;
00282
00283
if (!
FlagOn(Flags,
PIN_NO_READ)) {
00284
00285 *BaseAddress =
CcGetVirtualAddress( SharedCacheMap,
00286 *FileOffset,
00287 &Vacb,
00288 &ReceivedLength );
00289
00290 }
else {
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 ReceivedLength =
VACB_MAPPING_GRANULARITY -
00301 (ULONG)(FileOffset->QuadPart & (
VACB_MAPPING_GRANULARITY - 1));
00302
00303
00304
00305
00306
00307
CcReferenceFileOffset( SharedCacheMap, *FileOffset );
00308 }
00309
00310
00311
00312
00313
00314 ExAcquireSpinLock( &SharedCacheMap->
BcbSpinLock, &OldIrql );
00315 SpinLockAcquired =
TRUE;
00316
00317
00318
00319
00320
00321
try {
00322
00323 BOOLEAN Found;
00324 LARGE_INTEGER FOffset;
00325 LARGE_INTEGER TLength;
00326
00327
00328
00329
00330
00331
00332 TrialBound.QuadPart = FileOffset->QuadPart + (LONGLONG)Length;
00333 Found =
CcFindBcb( SharedCacheMap, FileOffset, &TrialBound, &BcbOut );
00334
00335
00336
00337
00338
00339
00340
00341
00342
if (!Found) {
00343
00344
00345
00346
00347
00348
if (
FlagOn(Flags,
PIN_IF_BCB)) {
00349
00350
00351
00352
00353
00354
00355 BcbOut =
NULL;
00356
try_return( Result =
FALSE );
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 FOffset = *FileOffset;
00368 TLength.QuadPart = TrialBound.QuadPart - FOffset.QuadPart;
00369
00370 TLength.LowPart += FOffset.LowPart & (
PAGE_SIZE - 1);
00371 ReceivedLength += FOffset.LowPart & (
PAGE_SIZE - 1);
00372
00373
00374
00375
00376
00377
00378
00379
if ((!ReadOnly && !
FlagOn(SharedCacheMap->
Flags,
PIN_ACCESS)) || WriteOnly) {
00380
00381
00382
00383
00384
00385 ZeroFlags =
ZERO_MIDDLE_PAGES;
00386
00387
if (((FOffset.LowPart & (
PAGE_SIZE - 1)) == 0) &&
00388 (Length >=
PAGE_SIZE)) {
00389 ZeroFlags |=
ZERO_FIRST_PAGE;
00390 }
00391
00392
if ((TLength.LowPart & (
PAGE_SIZE - 1)) == 0) {
00393 ZeroFlags |=
ZERO_LAST_PAGE;
00394 }
00395 }
00396
00397
00398
00399
00400
00401
00402
if (!
FlagOn(SharedCacheMap->
Flags,
MODIFIED_WRITE_DISABLED)) {
00403 ReadOnly =
TRUE;
00404 }
00405
00406 TLength.LowPart = (ULONG)
ROUND_TO_PAGES( TLength.LowPart );
00407
00408
00409
00410
00411
00412 *BaseAddress = ((PCHAR)*BaseAddress - (FileOffset->LowPart & (
PAGE_SIZE - 1)));
00413 FOffset.LowPart &= ~(
PAGE_SIZE - 1);
00414
00415
00416
00417
00418
00419
00420
if (FOffset.QuadPart >= SharedCacheMap->
ValidDataGoal.QuadPart) {
00421
00422 ZeroFlags |=
ZERO_FIRST_PAGE |
ZERO_MIDDLE_PAGES |
ZERO_LAST_PAGE;
00423
00424 }
else if ((FOffset.QuadPart + (LONGLONG)
PAGE_SIZE) >=
00425 SharedCacheMap->
ValidDataGoal.QuadPart) {
00426
00427 ZeroFlags |=
ZERO_MIDDLE_PAGES |
ZERO_LAST_PAGE;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
if (TLength.LowPart > ReceivedLength) {
00437 TLength.LowPart = ReceivedLength;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
if (
FlagOn(Flags,
PIN_WAIT)) {
00456
00457 BcbOut =
CcAllocateInitializeBcb( SharedCacheMap,
00458 BcbOut,
00459 &FOffset,
00460 &TLength );
00461
00462
if (BcbOut ==
NULL) {
00463
DebugTrace( 0, 0,
"Bcb allocation failure\n", 0 );
00464 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00465 SpinLockAcquired =
FALSE;
00466
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
00467 }
00468
00469
00470
00471
00472
00473
00474
if (!ReadOnly) {
00475
if (
FlagOn(Flags,
PIN_EXCLUSIVE)) {
00476 (
VOID)
ExAcquireResourceExclusive( &BcbOut->
Resource,
TRUE );
00477 }
else {
00478 (
VOID)
ExAcquireSharedStarveExclusive( &BcbOut->
Resource,
TRUE );
00479 }
00480 }
00481 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00482 SpinLockAcquired =
FALSE;
00483
00484
00485
00486
00487
00488
if (!
FlagOn(Flags,
PIN_NO_READ)) {
00489
00490 (
VOID)
CcMapAndRead( SharedCacheMap,
00491 &FOffset,
00492 TLength.LowPart,
00493 ZeroFlags,
00494
TRUE,
00495 *BaseAddress );
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 ExAcquireSpinLock( &SharedCacheMap->
BcbSpinLock, &OldIrql );
00506
00507
if (BcbOut->
BaseAddress ==
NULL) {
00508
00509 BcbOut->
BaseAddress = *BaseAddress;
00510 BcbOut->
Vacb = Vacb;
00511 Vacb =
NULL;
00512 }
00513
00514 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00515
00516
00517
00518
00519
00520 *BaseAddress = (PCHAR)BcbOut->
BaseAddress +
00521 (ULONG)( FileOffset->QuadPart - BcbOut->
FileOffset.QuadPart );
00522 }
00523
00524
00525
00526
00527
00528
try_return( Result =
TRUE );
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
else {
00543
00544
00545
00546
00547
00548
00549
00550
00551 BcbOut =
CcAllocateInitializeBcb( SharedCacheMap,
00552 BcbOut,
00553 &FOffset,
00554 &TLength );
00555
00556
if (BcbOut ==
NULL) {
00557
00558
try_return( Result =
FALSE );
00559 }
00560
00561
00562
00563
00564
00565
00566
if (!ReadOnly) {
00567
ExAcquireSharedStarveExclusive( &BcbOut->
Resource,
TRUE );
00568 }
00569 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00570 SpinLockAcquired =
FALSE;
00571
00572
00573
00574
00575
00576
00577
ASSERT( !
FlagOn(Flags,
PIN_NO_READ) );
00578
if (!
CcMapAndRead( SharedCacheMap,
00579 &FOffset,
00580 TLength.LowPart,
00581 ZeroFlags,
00582
FALSE,
00583 *BaseAddress )) {
00584
00585
try_return( Result =
FALSE );
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 ExAcquireSpinLock( &SharedCacheMap->
BcbSpinLock, &OldIrql );
00597
00598
if (BcbOut->
BaseAddress ==
NULL) {
00599
00600 BcbOut->
BaseAddress = *BaseAddress;
00601 BcbOut->
Vacb = Vacb;
00602 Vacb =
NULL;
00603 }
00604
00605 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00606
00607
00608
00609
00610
00611 *BaseAddress = (PCHAR)BcbOut->
BaseAddress +
00612 (ULONG)( FileOffset->QuadPart - BcbOut->
FileOffset.QuadPart );
00613
00614
00615
00616
00617
00618
try_return( Result =
TRUE );
00619 }
00620
00621 }
else {
00622
00623
00624
00625
00626
00627
00628
if (!
FlagOn(SharedCacheMap->
Flags,
MODIFIED_WRITE_DISABLED)) {
00629 ReadOnly =
TRUE;
00630 }
00631 }
00632
00633
00634
00635
00636
00637
00638
if (BcbOut->
BaseAddress ==
NULL) {
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 *BaseAddress = ((PCHAR)*BaseAddress - (FileOffset->LowPart - BcbOut->
FileOffset.LowPart));
00654 FOffset = BcbOut->
FileOffset;
00655 TLength.QuadPart = (LONGLONG)BcbOut->
ByteLength;
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
if (
FlagOn(Flags,
PIN_WAIT)) {
00668
00669 BcbOut->
PinCount += 1;
00670
00671
00672
00673
00674
00675
00676 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00677 SpinLockAcquired =
FALSE;
00678
if (!ReadOnly) {
00679
if (
FlagOn(Flags,
PIN_EXCLUSIVE)) {
00680 (
VOID)
ExAcquireResourceExclusive( &BcbOut->
Resource,
TRUE );
00681 }
else {
00682 (
VOID)
ExAcquireSharedStarveExclusive( &BcbOut->
Resource,
TRUE );
00683 }
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
if (!
FlagOn(Flags,
PIN_NO_READ)) {
00693
00694 (
VOID)
CcMapAndRead( SharedCacheMap,
00695 &FOffset,
00696 TLength.LowPart,
00697 ZeroFlags,
00698
TRUE,
00699 *BaseAddress );
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 ExAcquireSpinLock( &SharedCacheMap->
BcbSpinLock, &OldIrql );
00710
00711
if (BcbOut->
BaseAddress ==
NULL) {
00712
00713 BcbOut->
BaseAddress = *BaseAddress;
00714 BcbOut->
Vacb = Vacb;
00715 Vacb =
NULL;
00716 }
00717
00718 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00719
00720
00721
00722
00723
00724
00725 *BaseAddress = (PCHAR)BcbOut->
BaseAddress +
00726 (ULONG)( FileOffset->QuadPart - BcbOut->
FileOffset.QuadPart );
00727 }
00728
00729
00730
00731
00732
00733
try_return( Result =
TRUE );
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
else {
00748
00749
if (!ReadOnly && !
ExAcquireSharedStarveExclusive( &BcbOut->
Resource,
FALSE )) {
00750
00751
00752
00753
00754
00755
00756 BcbOut =
NULL;
00757
try_return( Result =
FALSE );
00758 }
00759
00760 BcbOut->
PinCount += 1;
00761
00762 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00763 SpinLockAcquired =
FALSE;
00764
00765
00766
00767
00768
00769
00770
ASSERT( !
FlagOn(Flags,
PIN_NO_READ) );
00771
if (!
CcMapAndRead( SharedCacheMap,
00772 &BcbOut->
FileOffset,
00773 BcbOut->
ByteLength,
00774 ZeroFlags,
00775
FALSE,
00776 *BaseAddress )) {
00777
00778
try_return( Result =
FALSE );
00779 }
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 ExAcquireSpinLock( &SharedCacheMap->
BcbSpinLock, &OldIrql );
00790
00791
if (BcbOut->
BaseAddress ==
NULL) {
00792
00793 BcbOut->
BaseAddress = *BaseAddress;
00794 BcbOut->
Vacb = Vacb;
00795 Vacb =
NULL;
00796 }
00797
00798 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00799
00800
00801
00802
00803
00804 *BaseAddress = (PCHAR)BcbOut->
BaseAddress +
00805 (ULONG)( FileOffset->QuadPart - BcbOut->
FileOffset.QuadPart );
00806
00807
00808
00809
00810
00811
try_return( Result =
TRUE );
00812 }
00813 }
00814
00815
00816
00817
00818
00819
00820
else {
00821
00822
00823
00824
00825
00826
00827
00828
00829
if (
FlagOn(Flags,
PIN_WAIT)) {
00830
00831 BcbOut->
PinCount += 1;
00832 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00833 SpinLockAcquired =
FALSE;
00834
00835
00836
00837
00838
00839
if (!ReadOnly) {
00840
if (
FlagOn(Flags,
PIN_EXCLUSIVE)) {
00841 (
VOID)
ExAcquireResourceExclusive( &BcbOut->
Resource,
TRUE );
00842 }
else {
00843 (
VOID)
ExAcquireSharedStarveExclusive( &BcbOut->
Resource,
TRUE );
00844 }
00845 }
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
else {
00858
00859
00860
00861
00862
00863
if (!ReadOnly && !
ExAcquireSharedStarveExclusive( &BcbOut->
Resource,
FALSE )) {
00864
00865
00866
00867
00868
00869
00870 BcbOut =
NULL;
00871
try_return( Result =
FALSE );
00872 }
00873
00874 BcbOut->
PinCount += 1;
00875 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00876 SpinLockAcquired =
FALSE;
00877 }
00878
00879
00880
00881
00882
00883 *BaseAddress = (PCHAR)BcbOut->
BaseAddress +
00884 (ULONG)( FileOffset->QuadPart - BcbOut->
FileOffset.QuadPart );
00885
00886
00887
00888
00889
00890
try_return( Result =
TRUE );
00891 }
00892
00893
00894 try_exit: NOTHING;
00895
00896
if (
FlagOn(Flags,
PIN_NO_READ) &&
00897
FlagOn(Flags,
PIN_EXCLUSIVE) &&
00898 (BcbOut !=
NULL) &&
00899 (BcbOut->
BaseAddress !=
NULL)) {
00900
00901
00902
00903
00904
00905
00906
00907
00908
CcFreeVirtualAddress( BcbOut->
Vacb );
00909
00910 BcbOut->
BaseAddress =
NULL;
00911 BcbOut->
Vacb =
NULL;
00912 }
00913
00914 } finally {
00915
00916
00917
00918
00919
00920
if (SpinLockAcquired) {
00921 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
00922 }
00923
00924
00925
00926
00927
00928
if (Vacb !=
NULL) {
00929
CcFreeVirtualAddress( Vacb );
00930 }
00931
00932
00933
00934
00935
00936
if (
FlagOn(Flags,
PIN_NO_READ)) {
00937
00938
CcDereferenceFileOffset( SharedCacheMap, *FileOffset );
00939 }
00940
00941
if (Result) {
00942
00943 *Bcb = BcbOut;
00944 *BeyondLastByte = BcbOut->
BeyondLastByte;
00945
00946
00947
00948
00949
00950
00951 }
else {
00952
00953 *BaseAddress =
NULL;
00954
if (BcbOut !=
NULL) {
00955
CcUnpinFileData( BcbOut, ReadOnly,
UNPIN );
00956 }
00957 }
00958
00959
DebugTrace( 0,
me,
" <Bcb = %08lx\n", *Bcb );
00960
DebugTrace( 0,
me,
" <BaseAddress = %08lx\n", *BaseAddress );
00961
DebugTrace(-1,
me,
"CcPinFileData -> %02lx\n", Result );
00962 }
00963
00964
return Result;
00965 }
00966
00967
00968
00969
00970
00971
00972
VOID
00973
FASTCALL
00974 CcUnpinFileData (
00975 IN OUT
PBCB Bcb,
00976 IN BOOLEAN ReadOnly,
00977 IN UNMAP_ACTIONS UnmapAction
00978 )
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 {
01003 KIRQL OldIrql;
01004
PSHARED_CACHE_MAP SharedCacheMap;
01005
01006
DebugTrace(+1,
me,
"CcUnpinFileData >Bcb = %08lx\n", Bcb );
01007
01008
01009
01010
01011
01012
01013
01014
01015
ASSERT( (
CACHE_NTC_BCB & 0xFF) != 0 );
01016
01017
if (Bcb->NodeTypeCode !=
CACHE_NTC_BCB) {
01018
01019
ASSERT(((
PVACB)Bcb >=
CcVacbs) && ((
PVACB)Bcb <
CcBeyondVacbs));
01020
ASSERT(((
PVACB)Bcb)->SharedCacheMap->
NodeTypeCode ==
CACHE_NTC_SHARED_CACHE_MAP);
01021
01022
CcFreeVirtualAddress( (
PVACB)Bcb );
01023
01024
DebugTrace(-1,
me,
"CcUnpinFileData -> VOID (simple release)\n", 0 );
01025
01026
return;
01027 }
01028
01029 SharedCacheMap = Bcb->SharedCacheMap;
01030
01031
01032
01033
01034
01035
01036
if (!
FlagOn(SharedCacheMap->
Flags,
MODIFIED_WRITE_DISABLED) ||
01037 UnmapAction ==
UNREF) {
01038 ReadOnly =
TRUE;
01039 }
01040
01041
01042
01043
01044
01045 ExAcquireSpinLock( &SharedCacheMap->
BcbSpinLock, &OldIrql );
01046
01047
switch (UnmapAction) {
01048
01049
case UNPIN:
01050
case UNREF:
01051
01052
ASSERT( Bcb->PinCount > 0 );
01053
01054 Bcb->PinCount -= 1;
01055
break;
01056
01057
case SET_CLEAN:
01058
01059
if (Bcb->Dirty) {
01060
01061 ULONG Pages = Bcb->ByteLength >>
PAGE_SHIFT;
01062
01063
01064
01065
01066
01067 Bcb->Dirty =
FALSE;
01068
01069
CcAcquireMasterLockAtDpcLevel();
01070
01071 SharedCacheMap->
DirtyPages -= Pages;
01072
CcTotalDirtyPages -= Pages;
01073
01074
01075
01076
01077
01078
if (
CcPagesYetToWrite > Pages) {
01079
CcPagesYetToWrite -= Pages;
01080 }
else {
01081
CcPagesYetToWrite = 0;
01082 }
01083
01084
01085
01086
01087
01088
01089
if ((SharedCacheMap->
DirtyPages == 0) &&
01090 (SharedCacheMap->
OpenCount != 0)) {
01091
01092 RemoveEntryList( &SharedCacheMap->
SharedCacheMapLinks );
01093 InsertTailList( &
CcCleanSharedCacheMapList,
01094 &SharedCacheMap->
SharedCacheMapLinks );
01095 }
01096
01097
CcReleaseMasterLockFromDpcLevel();
01098 }
01099
01100
break;
01101
01102
default:
01103
CcBugCheck( UnmapAction, 0, 0 );
01104 }
01105
01106
01107
01108
01109
01110
if (Bcb->PinCount == 0) {
01111
01112
01113
01114
01115
01116
if (Bcb->Dirty) {
01117
01118
if (Bcb->BaseAddress !=
NULL) {
01119
01120
01121
01122
01123
01124
01125
01126
01127
CcFreeVirtualAddress( Bcb->Vacb );
01128
01129 Bcb->BaseAddress =
NULL;
01130 Bcb->Vacb =
NULL;
01131 }
01132
01133
if (!ReadOnly) {
01134
ExReleaseResource( &Bcb->Resource );
01135 }
01136
01137 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
01138 }
01139
01140
01141
01142
01143
01144
else {
01145
01146
01147
01148
01149
01150
01151
01152
CcAcquireVacbLockAtDpcLevel();
01153 RemoveEntryList( &Bcb->BcbLinks );
01154
01155
01156
01157
01158
01159
CcUnlockVacbLevel( SharedCacheMap, Bcb->FileOffset.QuadPart );
01160
CcReleaseVacbLockFromDpcLevel();
01161
01162
01163
01164
01165
01166
#if LIST_DBG
01167
01168 ExAcquireSpinLockAtDpcLevel( &
CcBcbSpinLock );
01169
01170
if (Bcb->CcBcbLinks.Flink !=
NULL) {
01171
01172 RemoveEntryList( &Bcb->CcBcbLinks );
01173 CcBcbCount -= 1;
01174 }
01175
01176 ExReleaseSpinLockFromDpcLevel( &
CcBcbSpinLock );
01177
01178
#endif
01179
01180
if (Bcb->BaseAddress !=
NULL) {
01181
01182
CcFreeVirtualAddress( Bcb->Vacb );
01183 }
01184
#if DBG
01185
if (!ReadOnly) {
01186
ExReleaseResource( &Bcb->Resource );
01187 }
01188
01189
01190
01191
01192
01193
ASSERT( Bcb->Resource.ActiveCount == 0 );
01194
#endif
01195
ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
01196
CcDeallocateBcb( Bcb );
01197 }
01198 }
01199
01200
01201
01202
01203
01204
01205
01206
else {
01207
01208
if (!ReadOnly) {
01209
ExReleaseResource( &Bcb->Resource );
01210 }
01211
01212 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
01213 }
01214
01215
DebugTrace(-1,
me,
"CcUnpinFileData -> VOID\n", 0 );
01216
01217
return;
01218 }
01219
01220
01221
VOID
01222 CcSetReadAheadGranularity (
01223 IN
PFILE_OBJECT FileObject,
01224 IN ULONG Granularity
01225 )
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247 {
01248 ((
PPRIVATE_CACHE_MAP)FileObject->PrivateCacheMap)->ReadAheadMask = Granularity - 1;
01249 }
01250
01251
01252
VOID
01253 CcScheduleReadAhead (
01254 IN
PFILE_OBJECT FileObject,
01255 IN PLARGE_INTEGER FileOffset,
01256 IN ULONG Length
01257 )
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296 {
01297 LARGE_INTEGER NewOffset;
01298 LARGE_INTEGER NewBeyond;
01299 LARGE_INTEGER FileOffset1, FileOffset2;
01300 KIRQL OldIrql;
01301
PSHARED_CACHE_MAP SharedCacheMap;
01302
PPRIVATE_CACHE_MAP PrivateCacheMap;
01303
PWORK_QUEUE_ENTRY WorkQueueEntry;
01304 ULONG ReadAheadSize;
01305 BOOLEAN Changed =
FALSE;
01306
01307
DebugTrace(+1,
me,
"CcScheduleReadAhead:\n", 0 );
01308
DebugTrace2(0,
me,
" FileOffset = %08lx, %08lx\n", FileOffset->LowPart,
01309 FileOffset->HighPart );
01310
DebugTrace( 0,
me,
" Length = %08lx\n", Length );
01311
01312 SharedCacheMap = *(
PSHARED_CACHE_MAP *)((PCHAR)FileObject->SectionObjectPointer
01313 +
sizeof(PVOID));
01314 PrivateCacheMap = FileObject->PrivateCacheMap;
01315
01316
if ((PrivateCacheMap ==
NULL) ||
01317 (SharedCacheMap ==
NULL) ||
01318
FlagOn(SharedCacheMap->
Flags,
DISABLE_READ_AHEAD)) {
01319
01320
DebugTrace(-1,
me,
"CcScheduleReadAhead -> VOID (Nooped)\n", 0 );
01321
01322
return;
01323 }
01324
01325
01326
01327
01328
01329
01330
01331 NewOffset = *FileOffset;
01332 NewBeyond.QuadPart = FileOffset->QuadPart + (LONGLONG)Length;
01333
01334
01335
01336
01337
01338 ReadAheadSize = (Length + PrivateCacheMap->
ReadAheadMask) & ~PrivateCacheMap->
ReadAheadMask;
01339 FileOffset2.QuadPart = NewBeyond.QuadPart + (LONGLONG)ReadAheadSize;
01340 FileOffset2.LowPart &= ~PrivateCacheMap->
ReadAheadMask;
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350 ExAcquireSpinLock( &PrivateCacheMap->
ReadAheadSpinLock, &OldIrql );
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
if (
FlagOn(FileObject->Flags,
FO_SEQUENTIAL_ONLY)) {
01364
01365
01366
01367
01368
01369
01370
if (FileOffset2.QuadPart >= PrivateCacheMap->
ReadAheadOffset[1].QuadPart) {
01371
01372
01373
01374
01375
01376
01377
01378
if ((FileOffset->QuadPart == 0)
01379
01380 &&
01381
01382 (PrivateCacheMap->
ReadAheadMask > (
PAGE_SIZE - 1))
01383
01384 &&
01385
01386 ((Length +
PAGE_SIZE - 1) <= PrivateCacheMap->
ReadAheadMask)) {
01387
01388 FileOffset1.QuadPart = (LONGLONG)(
ROUND_TO_PAGES(Length) );
01389 PrivateCacheMap->
ReadAheadLength[0] = ReadAheadSize - FileOffset1.LowPart;
01390 FileOffset2.QuadPart = (LONGLONG)ReadAheadSize;
01391
01392
01393
01394
01395
01396 }
else {
01397
01398 FileOffset1.QuadPart = PrivateCacheMap->
ReadAheadOffset[1].QuadPart +
01399 (LONGLONG)ReadAheadSize;
01400
01401
01402
01403
01404
01405
01406
01407
if (FileOffset2.QuadPart > FileOffset1.QuadPart) {
01408 FileOffset1 = FileOffset2;
01409 }
01410 PrivateCacheMap->
ReadAheadLength[0] = ReadAheadSize;
01411 FileOffset2.QuadPart = FileOffset1.QuadPart + (LONGLONG)ReadAheadSize;
01412 }
01413
01414
01415
01416
01417
01418 PrivateCacheMap->
ReadAheadOffset[0] = FileOffset1;
01419
01420 PrivateCacheMap->
ReadAheadOffset[1] = FileOffset2;
01421 PrivateCacheMap->
ReadAheadLength[1] = ReadAheadSize;
01422
01423 Changed =
TRUE;
01424 }
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434 }
else if ((NewOffset.HighPart == PrivateCacheMap->
BeyondLastByte2.HighPart)
01435
01436 &&
01437
01438 ((NewOffset.LowPart & ~
NOISE_BITS)
01439 == (PrivateCacheMap->
BeyondLastByte2.LowPart & ~
NOISE_BITS))
01440
01441 &&
01442
01443 (PrivateCacheMap->
FileOffset2.HighPart
01444 == PrivateCacheMap->
BeyondLastByte1.HighPart)
01445
01446 &&
01447
01448 ((PrivateCacheMap->
FileOffset2.LowPart & ~
NOISE_BITS)
01449 == (PrivateCacheMap->
BeyondLastByte1.LowPart & ~
NOISE_BITS))) {
01450
01451
01452
01453
01454
01455
01456
01457
if ((FileOffset->QuadPart == 0)
01458
01459 &&
01460
01461 (PrivateCacheMap->
ReadAheadMask > (
PAGE_SIZE - 1))
01462
01463 &&
01464
01465 ((Length +
PAGE_SIZE - 1) <= PrivateCacheMap->
ReadAheadMask)) {
01466
01467 FileOffset2.QuadPart = (LONGLONG)(
ROUND_TO_PAGES(Length) );
01468 }
01469
01470
01471
01472
01473
01474
else {
01475 FileOffset2.QuadPart = NewBeyond.QuadPart + (LONGLONG)ReadAheadSize;
01476
01477 FileOffset2.LowPart &= ~PrivateCacheMap->
ReadAheadMask;
01478 }
01479
01480
01481
01482
01483
01484
01485
if (FileOffset2.QuadPart != PrivateCacheMap->
ReadAheadOffset[1].QuadPart) {
01486
01487
ASSERT( FileOffset2.HighPart >= 0 );
01488
01489 Changed =
TRUE;
01490 PrivateCacheMap->
ReadAheadOffset[1] = FileOffset2;
01491 PrivateCacheMap->
ReadAheadLength[1] = ReadAheadSize;
01492 }
01493 }
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
else if ( ( NewOffset.QuadPart -
01505 PrivateCacheMap->
FileOffset2.QuadPart ) ==
01506 ( PrivateCacheMap->
FileOffset2.QuadPart -
01507 PrivateCacheMap->
FileOffset1.QuadPart )) {
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519 FileOffset2.QuadPart = ( NewOffset.QuadPart << 1 ) - PrivateCacheMap->
FileOffset2.QuadPart;
01520
01521
01522
01523
01524
01525
01526
if (FileOffset2.HighPart >= 0) {
01527
01528
01529
01530
01531
01532
01533 Length += FileOffset2.LowPart & (
PAGE_SIZE - 1);
01534
01535
01536
01537
01538
01539 FileOffset2.LowPart &= ~(
PAGE_SIZE - 1);
01540 PrivateCacheMap->
ReadAheadOffset[1] = FileOffset2;
01541
01542
01543
01544
01545
01546 PrivateCacheMap->
ReadAheadLength[1] = (ULONG)
ROUND_TO_PAGES(Length);
01547 Changed =
TRUE;
01548 }
01549 }
01550
01551
01552
01553
01554
01555
if (!Changed || PrivateCacheMap->
ReadAheadActive) {
01556
01557
DebugTrace( 0,
me,
"Read ahead already in progress or no change\n", 0 );
01558
01559 ExReleaseSpinLock( &PrivateCacheMap->
ReadAheadSpinLock, OldIrql );
01560
return;
01561 }
01562
01563
01564
01565
01566
01567
01568 PrivateCacheMap->
ReadAheadActive =
TRUE;
01569
01570
01571
01572
01573
01574 ExReleaseSpinLock( &PrivateCacheMap->
ReadAheadSpinLock, OldIrql );
01575
01576
01577
01578
01579
01580
DebugTrace( 0,
me,
"Queueing read ahead to worker thread\n", 0 );
01581
01582 WorkQueueEntry =
CcAllocateWorkQueueEntry();
01583
01584
01585
01586
01587
01588
01589
01590
if (WorkQueueEntry !=
NULL) {
01591
01592
01593
01594
01595
01596
01597
ObReferenceObject ( FileObject );
01598
01599
01600
01601
01602
01603
CcAcquireMasterLock( &OldIrql );
01604
CcIncrementOpenCount( SharedCacheMap, 'adRQ' );
01605
CcReleaseMasterLock( OldIrql );
01606
01607 WorkQueueEntry->
Function = (UCHAR)
ReadAhead;
01608 WorkQueueEntry->
Parameters.Read.FileObject = FileObject;
01609
01610
CcPostWorkQueue( WorkQueueEntry, &
CcExpressWorkQueue );
01611 }
01612
01613
01614
01615
01616
01617
01618
else {
01619
01620 ExAcquireFastLock( &PrivateCacheMap->
ReadAheadSpinLock, &OldIrql );
01621 PrivateCacheMap->
ReadAheadActive =
FALSE;
01622 ExReleaseFastLock( &PrivateCacheMap->
ReadAheadSpinLock, OldIrql );
01623 }
01624
01625
DebugTrace(-1,
me,
"CcScheduleReadAhead -> VOID\n", 0 );
01626
01627
return;
01628 }
01629
01630
01631
VOID
01632
FASTCALL
01633 CcPerformReadAhead (
01634 IN
PFILE_OBJECT FileObject
01635 )
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654 {
01655 KIRQL OldIrql;
01656
PSHARED_CACHE_MAP SharedCacheMap;
01657
PPRIVATE_CACHE_MAP PrivateCacheMap;
01658 ULONG i;
01659 LARGE_INTEGER ReadAheadOffset[2];
01660 ULONG ReadAheadLength[2];
01661
PCACHE_MANAGER_CALLBACKS Callbacks;
01662 PVOID Context;
01663 ULONG SavedState;
01664 BOOLEAN Done;
01665 BOOLEAN HitEof =
FALSE;
01666 BOOLEAN ReadAheadPerformed =
FALSE;
01667 ULONG FaultOccurred = 0;
01668
PETHREAD Thread =
PsGetCurrentThread();
01669
PVACB Vacb =
NULL;
01670
01671 BOOLEAN ResourceHeld =
FALSE;
01672
01673
DebugTrace(+1,
me,
"CcPerformReadAhead:\n", 0 );
01674
DebugTrace( 0,
me,
" FileObject = %08lx\n", FileObject );
01675
01676
MmSavePageFaultReadAhead( Thread, &SavedState );
01677
01678
try {
01679
01680
01681
01682
01683
01684
01685 SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
01686
01687 Callbacks = SharedCacheMap->
Callbacks;
01688 Context = SharedCacheMap->
LazyWriteContext;
01689
01690
01691
01692
01693
01694
01695
while (
TRUE) {
01696
01697
01698
01699
01700
01701
01702
CcAcquireMasterLock( &OldIrql );
01703
01704 PrivateCacheMap = FileObject->PrivateCacheMap;
01705
01706
01707
01708
01709
01710
01711
01712
if (PrivateCacheMap !=
NULL) {
01713
01714 ExAcquireSpinLockAtDpcLevel( &PrivateCacheMap->
ReadAheadSpinLock );
01715
01716
01717
01718
01719
01720 Done = ((PrivateCacheMap->
ReadAheadLength[0] |
01721 PrivateCacheMap->
ReadAheadLength[1]) == 0);
01722
01723 ReadAheadOffset[0] = PrivateCacheMap->
ReadAheadOffset[0];
01724 ReadAheadOffset[1] = PrivateCacheMap->
ReadAheadOffset[1];
01725 ReadAheadLength[0] = PrivateCacheMap->
ReadAheadLength[0];
01726 ReadAheadLength[1] = PrivateCacheMap->
ReadAheadLength[1];
01727 PrivateCacheMap->
ReadAheadLength[0] = 0;
01728 PrivateCacheMap->
ReadAheadLength[1] = 0;
01729
01730 ExReleaseSpinLockFromDpcLevel( &PrivateCacheMap->
ReadAheadSpinLock );
01731 }
01732
01733
CcReleaseMasterLock( OldIrql );
01734
01735
01736
01737
01738
01739 (*Callbacks->
AcquireForReadAhead)( Context,
TRUE );
01740 ResourceHeld =
TRUE;
01741
01742
if ((PrivateCacheMap ==
NULL) || Done) {
01743
01744
try_return( NOTHING );
01745 }
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755 i = 0;
01756
01757
do {
01758
01759 LARGE_INTEGER
Offset, SavedOffset;
01760 ULONG Length, SavedLength;
01761
01762
Offset = ReadAheadOffset[i];
01763 Length = ReadAheadLength[i];
01764 SavedOffset =
Offset;
01765 SavedLength = Length;
01766
01767
if ((Length != 0)
01768
01769 &&
01770
01771 (
Offset.QuadPart <= SharedCacheMap->
FileSize.QuadPart )) {
01772
01773 ReadAheadPerformed =
TRUE;
01774
01775
01776
01777
01778
01779
if ( (
Offset.QuadPart + (LONGLONG)Length ) >= SharedCacheMap->
FileSize.QuadPart ) {
01780
01781 Length = (ULONG)( SharedCacheMap->
FileSize.QuadPart -
Offset.QuadPart );
01782 HitEof =
TRUE;
01783
01784 }
01785
if (Length >
MAX_READ_AHEAD) {
01786 Length =
MAX_READ_AHEAD;
01787 }
01788
01789
01790
01791
01792
01793
01794
01795
01796
while (Length != 0) {
01797
01798 ULONG ReceivedLength;
01799 PVOID CacheBuffer;
01800 ULONG PagesToGo;
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814 CacheBuffer =
CcGetVirtualAddress( SharedCacheMap,
01815
Offset,
01816 &Vacb,
01817 &ReceivedLength );
01818
01819
01820
01821
01822
01823
01824
if (ReceivedLength > Length) {
01825 ReceivedLength = Length;
01826 }
01827
01828
01829
01830
01831
01832
01833
01834 PagesToGo =
COMPUTE_PAGES_SPANNED( CacheBuffer,
01835 ReceivedLength );
01836
01837
CcMissCounter = &
CcReadAheadIos;
01838
01839
while (PagesToGo) {
01840
01841
MmSetPageFaultReadAhead( Thread, (PagesToGo - 1) );
01842 FaultOccurred |= !
MmCheckCachedPageState(CacheBuffer,
FALSE);
01843
01844 CacheBuffer = (PCHAR)CacheBuffer +
PAGE_SIZE;
01845 PagesToGo -= 1;
01846 }
01847
CcMissCounter = &
CcThrowAway;
01848
01849
01850
01851
01852
01853 Length -= ReceivedLength;
01854
01855
01856
01857
01858
01859
01860
Offset.QuadPart =
Offset.QuadPart + (LONGLONG)ReceivedLength;
01861
01862
01863
01864
01865
01866
01867
CcFreeVirtualAddress( Vacb );
01868 Vacb =
NULL;
01869 }
01870 }
01871 i += 1;
01872 }
while (i <= 1);
01873
01874
01875
01876
01877
01878 (*Callbacks->
ReleaseFromReadAhead)( Context );
01879 ResourceHeld =
FALSE;
01880 }
01881
01882 try_exit: NOTHING;
01883 }
01884 finally {
01885
01886
MmResetPageFaultReadAhead(Thread, SavedState);
01887
CcMissCounter = &
CcThrowAway;
01888
01889
01890
01891
01892
01893
01894
01895
if (Vacb !=
NULL) {
01896
CcFreeVirtualAddress( Vacb );
01897 }
01898
01899
01900
01901
01902
01903
if (ResourceHeld) {
01904 (*Callbacks->
ReleaseFromReadAhead)( Context );
01905 }
01906
01907
01908
01909
01910
01911
01912
CcAcquireMasterLock( &OldIrql );
01913
01914 PrivateCacheMap = FileObject->PrivateCacheMap;
01915
01916
01917
01918
01919
01920
if (PrivateCacheMap !=
NULL) {
01921
01922 ExAcquireSpinLockAtDpcLevel( &PrivateCacheMap->
ReadAheadSpinLock );
01923 PrivateCacheMap->
ReadAheadActive =
FALSE;
01924
01925
01926
01927
01928
01929
01930
01931
if (HitEof &&
FlagOn(FileObject->Flags,
FO_SEQUENTIAL_ONLY)) {
01932 PrivateCacheMap->
ReadAheadOffset[1].LowPart =
01933 PrivateCacheMap->
ReadAheadOffset[1].HighPart = 0;
01934 }
01935
01936
01937
01938
01939
01940
if (ReadAheadPerformed && !FaultOccurred) {
01941 PrivateCacheMap->
ReadAheadEnabled =
FALSE;
01942 }
01943
01944 ExReleaseSpinLockFromDpcLevel( &PrivateCacheMap->
ReadAheadSpinLock );
01945 }
01946
01947
01948
01949
01950
01951
CcReleaseMasterLock( OldIrql );
01952
01953
ObDereferenceObject( FileObject );
01954
01955
01956
01957
01958
01959
CcAcquireMasterLock( &OldIrql );
01960
01961
CcDecrementOpenCount( SharedCacheMap, 'adRP' );
01962
01963
if ((SharedCacheMap->
OpenCount == 0) &&
01964 !
FlagOn(SharedCacheMap->
Flags,
WRITE_QUEUED) &&
01965 (SharedCacheMap->
DirtyPages == 0)) {
01966
01967
01968
01969
01970
01971 RemoveEntryList( &SharedCacheMap->
SharedCacheMapLinks );
01972 InsertTailList( &
CcDirtySharedCacheMapList.
SharedCacheMapLinks,
01973 &SharedCacheMap->
SharedCacheMapLinks );
01974
01975
01976
01977
01978
01979
01980
LazyWriter.
OtherWork =
TRUE;
01981
if (!
LazyWriter.
ScanActive) {
01982
CcScheduleLazyWriteScan();
01983 }
01984 }
01985
01986
CcReleaseMasterLock( OldIrql );
01987 }
01988
01989
DebugTrace(-1,
me,
"CcPerformReadAhead -> VOID\n", 0 );
01990
01991
return;
01992 }
01993
01994
01995
PBITMAP_RANGE
01996 CcFindBitmapRangeToDirty (
01997 IN
PMBCB Mbcb,
01998 IN LONGLONG Page,
01999 IN PULONG *FreePageForSetting
02000 )
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032 {
02033
PBITMAP_RANGE BitmapRange, FreeRange;
02034 PLIST_ENTRY InsertPoint;
02035 LONGLONG BasePage;
02036
02037
02038
02039
02040
02041
02042 FreeRange =
NULL;
02043 InsertPoint = &Mbcb->BitmapRanges;
02044
02045
02046
02047
02048
02049 BitmapRange = (
PBITMAP_RANGE)InsertPoint->Flink;
02050
02051
02052
02053
02054
02055 BasePage = (Page & ~(LONGLONG)((
MBCB_BITMAP_BLOCK_SIZE * 8) - 1));
02056
02057
02058
02059
02060
02061
02062
do {
02063
02064
02065
02066
02067
02068
02069
if (BasePage == BitmapRange->
BasePage) {
02070
return BitmapRange;
02071
02072
02073
02074
02075
02076
02077 }
else if ((BitmapRange->
DirtyPages == 0) && (FreeRange ==
NULL)) {
02078 FreeRange = BitmapRange;
02079
02080
02081
02082
02083
02084
02085 }
else if (BasePage > BitmapRange->
BasePage) {
02086 InsertPoint = &BitmapRange->
Links;
02087 }
02088
02089
02090
02091
02092
02093 BitmapRange = (
PBITMAP_RANGE)BitmapRange->
Links.Flink;
02094
02095
02096
02097
02098
02099
02100 }
while ((BitmapRange != (
PBITMAP_RANGE)&Mbcb->BitmapRanges) &&
02101 ((BasePage >= BitmapRange->
BasePage) ||
02102 (FreeRange ==
NULL)));
02103
02104
02105
02106
02107
02108
if (FreeRange !=
NULL) {
02109 RemoveEntryList( &FreeRange->
Links );
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124 }
else {
02125 FreeRange =
ExAllocatePoolWithTag(
NonPagedPool,
sizeof(
BITMAP_RANGE), 'rBcC' );
02126
if (FreeRange ==
NULL) {
02127
return NULL;
02128 }
02129 RtlZeroMemory( FreeRange,
sizeof(
BITMAP_RANGE) );
02130 }
02131
02132
02133
02134
02135
02136 InsertHeadList( InsertPoint, &FreeRange->
Links );
02137 FreeRange->
BasePage = BasePage;
02138 FreeRange->
FirstDirtyPage = MAXULONG;
02139 FreeRange->
LastDirtyPage = 0;
02140
02141
02142
02143
02144
02145
02146
if (FreeRange->
Bitmap ==
NULL) {
02147
ASSERT(*FreePageForSetting !=
NULL);
02148 FreeRange->
Bitmap = *FreePageForSetting;
02149 *FreePageForSetting =
NULL;
02150 }
02151
02152
return FreeRange;
02153 }
02154
02155
02156
PBITMAP_RANGE
02157 CcFindBitmapRangeToClean (
02158 IN
PMBCB Mbcb,
02159 IN LONGLONG Page
02160 )
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187 {
02188
PBITMAP_RANGE BitmapRange;
02189
02190
02191
02192
02193
02194 BitmapRange = (
PBITMAP_RANGE)Mbcb->BitmapRanges.Flink;
02195
02196
02197
02198
02199
02200
do {
02201
02202
02203
02204
02205
02206
if (BitmapRange == (
PBITMAP_RANGE)&Mbcb->BitmapRanges) {
02207
02208
02209
02210
02211
02212
ASSERT(Page != 0);
02213
02214
02215
02216
02217
02218 Page = 0;
02219
02220
02221
02222
02223
02224
02225
02226 }
else if ((Page <= (BitmapRange->
BasePage + BitmapRange->
LastDirtyPage)) &&
02227 (BitmapRange->
DirtyPages != 0)) {
02228
return BitmapRange;
02229 }
02230
02231
02232
02233
02234
02235 BitmapRange = (
PBITMAP_RANGE)BitmapRange->
Links.Flink;
02236
02237 }
while (
TRUE);
02238 }
02239
02240
02241
VOID
02242 CcSetDirtyInMask (
02243 IN
PSHARED_CACHE_MAP SharedCacheMap,
02244 IN PLARGE_INTEGER FileOffset,
02245 IN ULONG Length
02246 )
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281 {
02282 KIRQL OldIrql;
02283
PMBCB Mbcb;
02284
PBITMAP_RANGE BitmapRange;
02285 LONGLONG FirstPage;
02286 LONGLONG LastPage;
02287 PULONG MaskPtr;
02288 ULONG Mask = 0;
02289 PULONG Bitmap =
NULL;
02290 ULONG AllocationError =
FALSE;
02291
02292
02293
02294
02295
02296
02297
ASSERT((FileOffset->QuadPart /
MBCB_BITMAP_RANGE) ==
02298 ((FileOffset->QuadPart + Length - 1) /
MBCB_BITMAP_RANGE));
02299
02300
02301
02302
02303
02304 FirstPage = FileOffset->QuadPart >>
PAGE_SHIFT;
02305 LastPage = ((FileOffset->QuadPart + Length - 1) >>
PAGE_SHIFT);
02306
02307
02308
02309
02310
02311
02312
do {
02313
02314
02315
02316
02317
02318
02319
02320
02321
if (SharedCacheMap->SectionSize.QuadPart > (
MBCB_BITMAP_INITIAL_SIZE * 8 *
PAGE_SIZE)) {
02322
02323
02324
02325
02326
02327
02328
if (!
CcPrefillVacbLevelZone( 1, &OldIrql,
FALSE )) {
02329
return;
02330 }
02331
02332 Bitmap = (PULONG)
CcAllocateVacbLevel(
FALSE );
02333
CcReleaseVacbLock( OldIrql );
02334 }
02335
02336
02337
02338
02339
02340 ExAcquireSpinLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
02341
02342
02343
02344
02345
02346 Mbcb = SharedCacheMap->Mbcb;
02347
if (Mbcb ==
NULL) {
02348
02349
02350
02351
02352
02353
ASSERT(
QuadAlign(
sizeof(
MBCB)) <=
QuadAlign(
sizeof(
BCB)));
02354
02355
02356
02357
02358
02359 Mbcb = (
PMBCB)
CcAllocateInitializeBcb(
NULL,
NULL,
NULL,
NULL );
02360
02361
02362
02363
02364
02365
if (Mbcb ==
NULL) {
02366
break;
02367 }
02368
02369
02370
02371
02372
02373 Mbcb->
NodeTypeCode =
CACHE_NTC_MBCB;
02374 InitializeListHead( &Mbcb->
BitmapRanges );
02375
02376
02377
02378
02379
02380 InsertTailList( &Mbcb->
BitmapRanges, &Mbcb->
BitmapRange1.
Links );
02381 Mbcb->
BitmapRange1.
FirstDirtyPage = MAXULONG;
02382
02383
02384
02385
02386
02387 Mbcb->
BitmapRange1.
Bitmap = (PULONG)&Mbcb->
BitmapRange2;
02388
02389
02390
02391
02392
02393 SharedCacheMap->Mbcb = Mbcb;
02394 }
02395
02396
02397
02398
02399
02400
if ((LastPage >= (
MBCB_BITMAP_INITIAL_SIZE * 8)) &&
02401 (Mbcb->
NodeTypeCode !=
CACHE_NTC_MBCB_GRANDE)) {
02402
02403
02404
02405
02406
02407
02408
if (Mbcb->
BitmapRange1.
DirtyPages != 0) {
02409 RtlCopyMemory( Bitmap, Mbcb->
BitmapRange1.
Bitmap,
MBCB_BITMAP_INITIAL_SIZE );
02410 RtlZeroMemory( Mbcb->
BitmapRange1.
Bitmap,
MBCB_BITMAP_INITIAL_SIZE );
02411 }
02412
02413
02414
02415
02416
02417 Mbcb->
BitmapRange1.
Bitmap = Bitmap;
02418 Bitmap =
NULL;
02419
02420
02421
02422
02423
02424 InsertTailList( &Mbcb->
BitmapRanges, &Mbcb->
BitmapRange2.
Links );
02425 Mbcb->
BitmapRange2.
BasePage = MAXLONGLONG;
02426 Mbcb->
BitmapRange2.
FirstDirtyPage = MAXULONG;
02427 InsertTailList( &Mbcb->
BitmapRanges, &Mbcb->
BitmapRange3.
Links );
02428 Mbcb->
BitmapRange3.
BasePage = MAXLONGLONG;
02429 Mbcb->
BitmapRange3.
FirstDirtyPage = MAXULONG;
02430 Mbcb->
NodeTypeCode =
CACHE_NTC_MBCB_GRANDE;
02431
02432
02433
02434
02435
02436
02437 ExReleaseSpinLock( &SharedCacheMap->BcbSpinLock, OldIrql );
02438
continue;
02439 }
02440
02441
02442
02443
02444
02445 BitmapRange =
CcFindBitmapRangeToDirty( Mbcb, FirstPage, &Bitmap );
02446
02447
02448
02449
02450
02451
if (BitmapRange ==
NULL) {
02452
break;
02453 }
02454
02455
02456
02457
02458
02459
if (FirstPage < (BitmapRange->
BasePage + BitmapRange->
FirstDirtyPage)) {
02460 BitmapRange->
FirstDirtyPage = (ULONG)(FirstPage - BitmapRange->
BasePage);
02461 }
02462
02463
if (LastPage > (BitmapRange->
BasePage + BitmapRange->
LastDirtyPage)) {
02464 BitmapRange->
LastDirtyPage = (ULONG)(LastPage - BitmapRange->
BasePage);
02465 }
02466
02467
02468
02469
02470
02471
02472
CcAcquireMasterLockAtDpcLevel();
02473
02474
02475
02476
02477
02478
02479
if (SharedCacheMap->DirtyPages == 0) {
02480
02481
02482
02483
02484
02485
if (!
LazyWriter.
ScanActive) {
02486
CcScheduleLazyWriteScan();
02487 }
02488
02489
02490
02491
02492
02493 RemoveEntryList( &SharedCacheMap->SharedCacheMapLinks );
02494 InsertTailList( &
CcDirtySharedCacheMapList.
SharedCacheMapLinks,
02495 &SharedCacheMap->SharedCacheMapLinks );
02496
02497 Mbcb->
ResumeWritePage = FirstPage;
02498 }
02499
02500 MaskPtr = &BitmapRange->
Bitmap[(ULONG)(FirstPage - BitmapRange->
BasePage) / 32];
02501 Mask = 1 << ((ULONG)FirstPage % 32);
02502
02503
02504
02505
02506
02507
for ( ; FirstPage <= LastPage; FirstPage++) {
02508
02509
if ((*MaskPtr & Mask) == 0) {
02510
02511
CcTotalDirtyPages += 1;
02512 SharedCacheMap->DirtyPages += 1;
02513 Mbcb->
DirtyPages += 1;
02514 BitmapRange->
DirtyPages += 1;
02515 *MaskPtr |= Mask;
02516 }
02517
02518 Mask <<= 1;
02519
02520
if (Mask == 0) {
02521
02522 MaskPtr += 1;
02523 Mask = 1;
02524 }
02525 }
02526
02527
02528
02529
02530
02531 LastPage = FileOffset->QuadPart + Length;
02532
02533
if (LastPage > SharedCacheMap->ValidDataGoal.QuadPart) {
02534 SharedCacheMap->ValidDataGoal.QuadPart = (LONGLONG)LastPage;
02535 }
02536
02537
CcReleaseMasterLockFromDpcLevel();
02538
02539
02540
02541
02542
02543
02544 }
while (Mask == 0);
02545
02546
02547
02548
02549
02550
if (Bitmap !=
NULL) {
02551
CcAcquireVacbLockAtDpcLevel();
02552
CcDeallocateVacbLevel( (
PVACB *)Bitmap,
FALSE );
02553
CcReleaseVacbLockFromDpcLevel();
02554 }
02555 ExReleaseSpinLock( &SharedCacheMap->BcbSpinLock, OldIrql );
02556 }
02557
02558
02559
VOID
02560 CcSetDirtyPinnedData (
02561 IN PVOID BcbVoid,
02562 IN PLARGE_INTEGER Lsn OPTIONAL
02563 )
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587 {
02588
PBCB Bcbs[2];
02589
PBCB *BcbPtrPtr;
02590 KIRQL OldIrql;
02591
PSHARED_CACHE_MAP SharedCacheMap;
02592
02593
DebugTrace(+1,
me,
"CcSetDirtyPinnedData: Bcb = %08lx\n", BcbVoid );
02594
02595
02596
02597
02598
02599 Bcbs[0] = (
PBCB)BcbVoid;
02600 Bcbs[1] =
NULL;
02601 BcbPtrPtr = &Bcbs[0];
02602
02603
02604
02605
02606
02607
02608
if (Bcbs[0]->NodeTypeCode ==
CACHE_NTC_OBCB) {
02609 BcbPtrPtr = &((
POBCB)Bcbs[0])->Bcbs[0];
02610 }
02611
02612
02613
02614
02615
02616
while (*BcbPtrPtr !=
NULL) {
02617
02618 Bcbs[0] = *(BcbPtrPtr++);
02619
02620
02621
02622
02623
02624
ASSERT(((ULONG_PTR)Bcbs[0] & 1) != 1);
02625
02626 SharedCacheMap = Bcbs[0]->SharedCacheMap;
02627
02628
02629
02630
02631
02632
02633 ExAcquireSpinLock( &SharedCacheMap->
BcbSpinLock, &OldIrql );
02634
02635
if (!Bcbs[0]->Dirty) {
02636
02637 ULONG Pages = Bcbs[0]->ByteLength >>
PAGE_SHIFT;
02638
02639
02640
02641
02642
02643
02644 Bcbs[0]->Dirty =
TRUE;
02645
02646
02647
02648
02649
02650
if (ARGUMENT_PRESENT(Lsn)) {
02651 Bcbs[0]->OldestLsn = *Lsn;
02652 Bcbs[0]->NewestLsn = *Lsn;
02653 }
02654
02655
02656
02657
02658
02659
02660
02661
02662
CcAcquireMasterLockAtDpcLevel();
02663
if ((SharedCacheMap->
DirtyPages == 0) &&
02664 !
FlagOn(SharedCacheMap->
Flags,
DISABLE_WRITE_BEHIND)) {
02665
02666
02667
02668
02669
02670
if (!
LazyWriter.
ScanActive) {
02671
CcScheduleLazyWriteScan();
02672 }
02673
02674 RemoveEntryList( &SharedCacheMap->
SharedCacheMapLinks );
02675 InsertTailList( &
CcDirtySharedCacheMapList.
SharedCacheMapLinks,
02676 &SharedCacheMap->
SharedCacheMapLinks );
02677 }
02678
02679 SharedCacheMap->
DirtyPages += Pages;
02680
CcTotalDirtyPages += Pages;
02681
CcReleaseMasterLockFromDpcLevel();
02682 }
02683
02684
02685
02686
02687
02688
02689
if (ARGUMENT_PRESENT(Lsn)) {
02690
02691
if ((Bcbs[0]->OldestLsn.QuadPart == 0) || (Lsn->QuadPart < Bcbs[0]->OldestLsn.QuadPart)) {
02692 Bcbs[0]->OldestLsn = *Lsn;
02693 }
02694
02695
if (Lsn->QuadPart > Bcbs[0]->NewestLsn.QuadPart) {
02696 Bcbs[0]->NewestLsn = *Lsn;
02697 }
02698 }
02699
02700
02701
02702
02703
02704
if ( Bcbs[0]->BeyondLastByte.QuadPart > SharedCacheMap->
ValidDataGoal.QuadPart ) {
02705
02706 SharedCacheMap->
ValidDataGoal = Bcbs[0]->BeyondLastByte;
02707 }
02708
02709 ExReleaseSpinLock( &SharedCacheMap->
BcbSpinLock, OldIrql );
02710 }
02711
02712
DebugTrace(-1,
me,
"CcSetDirtyPinnedData -> VOID\n", 0 );
02713 }
02714
02715
02716
NTSTATUS
02717 CcSetValidData (
02718 IN
PFILE_OBJECT FileObject,
02719 IN PLARGE_INTEGER ValidDataLength
02720 )
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742 {
02743
PIO_STACK_LOCATION IrpSp;
02744
PDEVICE_OBJECT DeviceObject;
02745
NTSTATUS Status;
02746 FILE_END_OF_FILE_INFORMATION
Buffer;
02747 IO_STATUS_BLOCK IoStatus;
02748
KEVENT Event;
02749
PIRP Irp;
02750
02751
DebugTrace(+1,
me,
"CcSetValidData:\n", 0 );
02752
DebugTrace( 0,
me,
" FileObject = %08lx\n", FileObject );
02753
DebugTrace2(0,
me,
" ValidDataLength = %08lx, %08lx\n",
02754 ValidDataLength->LowPart, ValidDataLength->HighPart );
02755
02756
02757
02758
02759
02760
Buffer.EndOfFile = *ValidDataLength;
02761
02762
02763
02764
02765
02766
KeInitializeEvent( &
Event, NotificationEvent,
FALSE );
02767
02768
02769
02770
02771
02772
02773 DeviceObject =
IoGetRelatedDeviceObject( FileObject );
02774
02775
02776
02777
02778
02779
Irp =
IoAllocateIrp( DeviceObject->
StackSize,
FALSE );
02780
if (
Irp ==
NULL) {
02781
02782
DebugTrace(-1,
me,
"CcSetValidData-> STATUS_INSUFFICIENT_RESOURCES\n", 0 );
02783
02784
return STATUS_INSUFFICIENT_RESOURCES;
02785 }
02786
02787
02788
02789
02790
02791
02792
02793 IrpSp =
IoGetNextIrpStackLocation(
Irp );
02794
02795
02796
02797
02798
02799
02800
Irp->
Flags =
IRP_PAGING_IO |
IRP_SYNCHRONOUS_PAGING_IO;
02801
Irp->
RequestorMode =
KernelMode;
02802
Irp->
UserIosb = &IoStatus;
02803
Irp->
UserEvent = &
Event;
02804
Irp->
Tail.Overlay.OriginalFileObject = FileObject;
02805
Irp->
Tail.Overlay.Thread =
PsGetCurrentThread();
02806
Irp->
AssociatedIrp.SystemBuffer = &
Buffer;
02807
02808
02809
02810
02811
02812 IrpSp->
MajorFunction =
IRP_MJ_SET_INFORMATION;
02813 IrpSp->
FileObject = FileObject;
02814 IrpSp->
DeviceObject = DeviceObject;
02815 IrpSp->
Parameters.SetFile.Length =
sizeof(FILE_END_OF_FILE_INFORMATION);
02816 IrpSp->
Parameters.SetFile.FileInformationClass = FileEndOfFileInformation;
02817 IrpSp->
Parameters.SetFile.FileObject =
NULL;
02818 IrpSp->
Parameters.SetFile.AdvanceOnly =
TRUE;
02819
02820
02821
02822
02823
02824
02825
Status =
IoCallDriver( DeviceObject,
Irp );
02826
02827
02828
02829
02830
02831
02832
if (
Status == STATUS_PENDING) {
02833
KeWaitForSingleObject( &
Event,
02834
Executive,
02835
KernelMode,
02836
FALSE,
02837 (PLARGE_INTEGER)
NULL);
02838 }
02839
02840
02841
02842
02843
02844
02845
02846
if (!
NT_SUCCESS(
Status)) {
02847 IoStatus.Status =
Status;
02848 }
02849
02850
DebugTrace(-1,
me,
"CcSetValidData-> %08lx\n", IoStatus.Status );
02851
02852
return IoStatus.Status;
02853 }
02854
02855
02856
02857
02858
02859
02860 BOOLEAN
02861 CcAcquireByteRangeForWrite (
02862 IN
PSHARED_CACHE_MAP SharedCacheMap,
02863 IN PLARGE_INTEGER TargetOffset OPTIONAL,
02864 IN ULONG TargetLength,
02865 OUT PLARGE_INTEGER FileOffset,
02866 OUT PULONG Length,
02867 OUT
PBCB *FirstBcb
02868 )
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910 {
02911 KIRQL OldIrql;
02912
PMBCB Mbcb;
02913
PBCB Bcb;
02914 LARGE_INTEGER LsnToFlushTo = {0, 0};
02915
02916 BOOLEAN BcbLookasideCheck =
FALSE;
02917
02918
PBITMAP_RANGE BitmapRange;
02919 PULONG EndPtr;
02920 PULONG MaskPtr;
02921 ULONG Mask;
02922 LONGLONG FirstDirtyPage;
02923 ULONG OriginalFirstDirtyPage;
02924 LONGLONG LastDirtyPage = MAXLONGLONG;
02925
02926
DebugTrace(+1,
me,
"CcAcquireByteRangeForWrite:\n", 0);
02927
DebugTrace( 0,
me,
" SharedCacheMap = %08lx\n", SharedCacheMap);
02928
02929
02930
02931
02932
02933 FileOffset->QuadPart = 0;
02934 *Length = 0;
02935
02936
02937
02938
02939
02940 ExAcquireSpinLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
02941
02942
02943
02944
02945
02946
02947 Mbcb = SharedCacheMap->Mbcb;
02948
02949
if ((Mbcb !=
NULL) &&
02950 (Mbcb->
DirtyPages != 0) &&
02951 ((Mbcb->
PagesToWrite != 0) || (TargetLength != 0))) {
02952
02953
02954
02955
02956
02957
02958
if (ARGUMENT_PRESENT(TargetOffset)) {
02959
02960 FirstDirtyPage = TargetOffset->QuadPart >>
PAGE_SHIFT;
02961 LastDirtyPage = (TargetOffset->QuadPart + TargetLength - 1) >>
PAGE_SHIFT;
02962
02963
02964
02965
02966
02967 BitmapRange =
CcFindBitmapRangeToClean( Mbcb, FirstDirtyPage );
02968
02969
02970
02971
02972
02973
02974
if ((LastDirtyPage < (BitmapRange->
BasePage + BitmapRange->
FirstDirtyPage)) ||
02975 (FirstDirtyPage > (BitmapRange->
BasePage + BitmapRange->
LastDirtyPage))) {
02976
02977
goto Scan_Bcbs;
02978 }
02979
02980
if (LastDirtyPage < (BitmapRange->
BasePage + BitmapRange->
LastDirtyPage)) {
02981 EndPtr = &BitmapRange->
Bitmap[(ULONG)(LastDirtyPage - BitmapRange->
BasePage) / 32];
02982 }
else {
02983 EndPtr = &BitmapRange->
Bitmap[BitmapRange->
LastDirtyPage / 32];
02984 }
02985
02986
02987
02988
02989
02990
02991 }
else {
02992
02993
02994
02995
02996
02997
02998
02999 FirstDirtyPage = 0;
03000
if (TargetLength == 0) {
03001 FirstDirtyPage = Mbcb->
ResumeWritePage;
03002 }
03003
03004
03005
03006
03007
03008 BitmapRange =
CcFindBitmapRangeToClean( Mbcb, FirstDirtyPage );
03009
03010
03011
03012
03013
03014
03015
03016
03017
if (FirstDirtyPage > (BitmapRange->
BasePage + BitmapRange->
LastDirtyPage)) {
03018 FirstDirtyPage = BitmapRange->
BasePage + BitmapRange->
FirstDirtyPage;
03019 }
03020
03021 EndPtr = &BitmapRange->
Bitmap[BitmapRange->
LastDirtyPage / 32];
03022 }
03023
03024
03025
03026
03027
03028
if (FirstDirtyPage < (BitmapRange->
BasePage + BitmapRange->
FirstDirtyPage)) {
03029 FirstDirtyPage = BitmapRange->
BasePage + BitmapRange->
FirstDirtyPage;
03030 }
03031
03032
03033
03034
03035
03036 MaskPtr = &BitmapRange->
Bitmap[(ULONG)(FirstDirtyPage - BitmapRange->
BasePage) / 32];
03037 Mask = (ULONG)(-1 << (FirstDirtyPage % 32));
03038 OriginalFirstDirtyPage = (ULONG)(FirstDirtyPage - BitmapRange->
BasePage);
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
if ((*MaskPtr & Mask) == 0) {
03049
03050
03051
03052
03053
03054
03055 Mask = MAXULONG;
03056 FirstDirtyPage &= ~31;
03057
03058
03059
03060
03061
03062
03063
do {
03064
03065 MaskPtr += 1;
03066 FirstDirtyPage += 32;
03067
03068
03069
03070
03071
03072
03073
03074
if (MaskPtr > EndPtr) {
03075
03076
03077
03078
03079
03080
03081
if (TargetLength == 0) {
03082
ASSERT(OriginalFirstDirtyPage >= BitmapRange->
FirstDirtyPage);
03083 BitmapRange->
LastDirtyPage = OriginalFirstDirtyPage - 1;
03084 }
03085
03086
03087
03088
03089
03090
03091
do {
03092
03093
03094
03095
03096
03097 BitmapRange = (
PBITMAP_RANGE)BitmapRange->
Links.Flink;
03098
03099
03100
03101
03102
03103
if (BitmapRange == (
PBITMAP_RANGE)&Mbcb->
BitmapRanges) {
03104
03105
03106
03107
03108
03109
03110
if (TargetLength != 0) {
03111
goto Scan_Bcbs;
03112 }
03113
03114
03115
03116
03117
03118
03119 BitmapRange = (
PBITMAP_RANGE)BitmapRange->
Links.Flink;
03120 }
03121
03122 }
while (BitmapRange->
DirtyPages == 0);
03123
03124
03125
03126
03127
03128
03129
if ((LastDirtyPage < (BitmapRange->
BasePage + BitmapRange->
FirstDirtyPage)) ||
03130 (FirstDirtyPage > (BitmapRange->
BasePage + BitmapRange->
LastDirtyPage))) {
03131
03132
goto Scan_Bcbs;
03133 }
03134
03135
03136
03137
03138
03139
03140 MaskPtr = &BitmapRange->
Bitmap[BitmapRange->
FirstDirtyPage / 32];
03141 EndPtr = &BitmapRange->
Bitmap[BitmapRange->
LastDirtyPage / 32];
03142 FirstDirtyPage = BitmapRange->
BasePage + (BitmapRange->
FirstDirtyPage & ~31);
03143 OriginalFirstDirtyPage = BitmapRange->
FirstDirtyPage;
03144 }
03145 }
while (*MaskPtr == 0);
03146 }
03147
03148
03149
03150
03151
03152 Mask = ~Mask + 1;
03153
03154
03155
03156
03157
03158
while ((*MaskPtr & Mask) == 0) {
03159
03160 Mask <<= 1;
03161 FirstDirtyPage += 1;
03162 }
03163
03164
03165
03166
03167
03168
03169
if (ARGUMENT_PRESENT(TargetOffset)) {
03170
03171
if (FirstDirtyPage >= ((TargetOffset->QuadPart + TargetLength +
PAGE_SIZE - 1) >>
PAGE_SHIFT)) {
03172
03173
goto Scan_Bcbs;
03174 }
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
if (!IsListEmpty(&SharedCacheMap->BcbList)) {
03187
03188 BcbLookasideCheck =
TRUE;
03189
goto Scan_Bcbs;
03190 }
03191 }
03192
03193 Accept_Page:
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
while (((*MaskPtr & Mask) != 0) && (*Length < (
MAX_WRITE_BEHIND /
PAGE_SIZE)) &&
03206 (!ARGUMENT_PRESENT(TargetOffset) || ((FirstDirtyPage + *Length) <
03207 (ULONG)((TargetOffset->QuadPart + TargetLength +
PAGE_SIZE - 1) >>
PAGE_SHIFT)))) {
03208
03209
ASSERT(MaskPtr <= (&BitmapRange->Bitmap[BitmapRange->
LastDirtyPage / 32]));
03210
03211 *MaskPtr -= Mask;
03212 *Length += 1;
03213 Mask <<= 1;
03214
03215
if (Mask == 0) {
03216
03217 MaskPtr += 1;
03218 Mask = 1;
03219
03220
if (MaskPtr > EndPtr) {
03221
break;
03222 }
03223 }
03224 }
03225
03226
03227
03228
03229
03230
03231
if (*Length < Mbcb->
PagesToWrite) {
03232
03233 Mbcb->
PagesToWrite -= *Length;
03234
03235 }
else {
03236
03237 Mbcb->
PagesToWrite = 0;
03238 }
03239
03240
03241
03242
03243
03244
ASSERT(Mbcb->
DirtyPages >= *Length);
03245 Mbcb->
DirtyPages -= *Length;
03246 BitmapRange->
DirtyPages -= *Length;
03247
03248
CcAcquireMasterLockAtDpcLevel();
03249
CcTotalDirtyPages -= *Length;
03250 SharedCacheMap->DirtyPages -= *Length;
03251
03252
03253
03254
03255
03256
if (
CcPagesYetToWrite > *Length) {
03257
CcPagesYetToWrite -= *Length;
03258 }
else {
03259
CcPagesYetToWrite = 0;
03260 }
03261
03262
03263
03264
03265
03266
03267
if (SharedCacheMap->DirtyPages == 0) {
03268
03269 RemoveEntryList( &SharedCacheMap->SharedCacheMapLinks );
03270 InsertTailList( &
CcCleanSharedCacheMapList,
03271 &SharedCacheMap->SharedCacheMapLinks );
03272 }
03273
CcReleaseMasterLockFromDpcLevel();
03274
03275
03276
03277
03278
03279
03280
if (BitmapRange->
DirtyPages == 0) {
03281
03282 BitmapRange->
FirstDirtyPage = MAXULONG;
03283 BitmapRange->
LastDirtyPage = 0;
03284
03285
03286
03287
03288
03289
03290
03291 Mbcb->
ResumeWritePage = BitmapRange->
BasePage + (
MBCB_BITMAP_BLOCK_SIZE * 8);
03292
03293
03294
03295
03296
03297 }
else {
03298
03299
03300
03301
03302
03303
if (BitmapRange->
FirstDirtyPage == OriginalFirstDirtyPage) {
03304
03305 BitmapRange->
FirstDirtyPage = (ULONG)(FirstDirtyPage - BitmapRange->
BasePage) + *Length;
03306 }
03307
03308
03309
03310
03311
03312
03313
if (TargetLength == 0) {
03314
03315 Mbcb->
ResumeWritePage = FirstDirtyPage + *Length;
03316 }
03317 }
03318
03319
03320
03321
03322
03323
03324
if (IsListEmpty(&SharedCacheMap->BcbList)) {
03325 SharedCacheMap->PagesToWrite = Mbcb->
PagesToWrite;
03326 }
03327
03328 ExReleaseSpinLock( &SharedCacheMap->BcbSpinLock, OldIrql );
03329
03330
03331
03332
03333
03334
03335 *Length <<=
PAGE_SHIFT;
03336 FileOffset->QuadPart = (LONGLONG)FirstDirtyPage <<
PAGE_SHIFT;
03337 *FirstBcb =
NULL;
03338
03339
DebugTrace2(0,
me,
" <FileOffset = %08lx, %08lx\n", FileOffset->LowPart,
03340 FileOffset->HighPart );
03341
DebugTrace( 0,
me,
" <Length = %08lx\n", *Length );
03342
DebugTrace(-1,
me,
"CcAcquireByteRangeForWrite -> TRUE\n", 0 );
03343
03344
return TRUE;
03345 }
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357 Scan_Bcbs:
03358
03359
03360
03361
03362
03363
03364
while (
TRUE) {
03365
03366 Bcb = CONTAINING_RECORD( SharedCacheMap->BcbList.Blink,
BCB, BcbLinks );
03367
03368
03369
03370
03371
03372
03373
03374
if (
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED)) {
03375
03376 PLARGE_INTEGER StartingOffset;
03377
03378
if (ARGUMENT_PRESENT(TargetOffset)) {
03379 StartingOffset = TargetOffset;
03380 }
else {
03381 StartingOffset = (PLARGE_INTEGER)&SharedCacheMap->BeyondLastFlush;
03382 }
03383
03384
if (StartingOffset->QuadPart != 0) {
03385
03386 LARGE_INTEGER StartingOffsetBias;
03387
03388 StartingOffsetBias.QuadPart = StartingOffset->QuadPart +
PAGE_SIZE;
03389
03390
03391
03392
03393
03394
03395
if (!
CcFindBcb( SharedCacheMap,
03396 StartingOffset,
03397 &StartingOffsetBias,
03398 &Bcb )) {
03399 Bcb = CONTAINING_RECORD( Bcb->
BcbLinks.Blink,
BCB, BcbLinks );
03400 }
03401 }
03402 }
03403
03404
while (&Bcb->
BcbLinks != &SharedCacheMap->BcbList) {
03405
03406
03407
03408
03409
03410
if (Bcb->
NodeTypeCode !=
CACHE_NTC_BCB) {
03411
03412 Bcb = CONTAINING_RECORD( Bcb->
BcbLinks.Blink,
BCB, BcbLinks );
03413
continue;
03414 }
03415
03416
03417
03418
03419
03420
03421
if (ARGUMENT_PRESENT(TargetOffset) &&
03422 ((TargetOffset->QuadPart + TargetLength) <= Bcb->
FileOffset.QuadPart)) {
03423
03424
break;
03425 }
03426
03427
03428
03429
03430
03431
03432
if (*Length == 0) {
03433
03434
03435
03436
03437
03438
03439
if (!Bcb->
Dirty ||
03440 (ARGUMENT_PRESENT(TargetOffset) && (TargetOffset->QuadPart >= Bcb->
BeyondLastByte.QuadPart)) ||
03441 (!ARGUMENT_PRESENT(TargetOffset) && (Bcb->
FileOffset.QuadPart < SharedCacheMap->BeyondLastFlush))) {
03442
03443 Bcb = CONTAINING_RECORD( Bcb->
BcbLinks.Blink,
BCB, BcbLinks );
03444
continue;
03445
03446 }
03447
03448
03449
03450
03451
03452
03453
03454
if (BcbLookasideCheck && FirstDirtyPage <= (ULONG)(Bcb->
FileOffset.QuadPart >>
PAGE_SHIFT)) {
03455
goto Accept_Page;
03456 }
03457 }
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
else {
03473
if (!Bcb->
Dirty || ( Bcb->
FileOffset.QuadPart != ( FileOffset->QuadPart + (LONGLONG)*Length)) ||
03474 (*Length + Bcb->
ByteLength >
MAX_WRITE_BEHIND) ||
03475 (Bcb->
PinCount != 0) ||
03476 ((Bcb->
FileOffset.QuadPart & (
VACB_SIZE_OF_FIRST_LEVEL - 1)) == 0)) {
03477
03478
break;
03479 }
03480 }
03481
03482
03483
03484
03485
03486
03487
03488 Bcb->
PinCount += 1;
03489
03490
03491
03492
03493
03494 ExReleaseSpinLock( &SharedCacheMap->BcbSpinLock, OldIrql );
03495
03496
if (
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED) &&
03497 !
FlagOn(SharedCacheMap->Flags,
DISABLE_WRITE_BEHIND)) {
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
if (!
ExAcquireResourceExclusive( &Bcb->
Resource,
03514 (BOOLEAN)(*Length == 0) )) {
03515
03516
DebugTrace( 0,
me,
"Could not acquire 2nd Bcb\n", 0 );
03517
03518
03519
03520
03521
03522
03523
03524
03525
CcUnpinFileData( Bcb,
TRUE,
UNPIN );
03526
03527
03528
03529
03530
03531 ExAcquireSpinLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
03532
break;
03533 }
03534
03535 ExAcquireSpinLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
03536
03537
03538
03539
03540
03541
03542
03543
if (!Bcb->
Dirty) {
03544
03545
03546
03547
03548
03549 ExReleaseSpinLock( &SharedCacheMap->BcbSpinLock, OldIrql );
03550
03551
CcUnpinFileData( Bcb,
FALSE,
UNPIN );
03552
03553 ExAcquireSpinLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
03554
03555
03556
03557
03558
03559
03560
03561
if (*Length != 0) {
03562
break;
03563 }
03564
else {
03565
03566 Bcb = CONTAINING_RECORD( SharedCacheMap->BcbList.Blink,
BCB, BcbLinks );
03567
continue;
03568 }
03569 }
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580 }
else {
03581
03582
CcUnpinFileData( Bcb,
TRUE,
SET_CLEAN );
03583
03584 ExAcquireSpinLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
03585 }
03586
03587
DebugTrace( 0,
me,
"Adding Bcb = %08lx to run\n", Bcb );
03588
03589
03590
03591
03592
03593
03594 BcbLookasideCheck =
FALSE;
03595
03596
03597
03598
03599
03600
03601
03602
03603
if (*Length == 0) {
03604 *FileOffset = Bcb->
FileOffset;
03605 }
03606 *FirstBcb = Bcb;
03607 *Length += Bcb->
ByteLength;
03608
03609
03610
03611
03612
03613
03614
if ((SharedCacheMap->FlushToLsnRoutine !=
NULL) &&
03615 (Bcb->NewestLsn.QuadPart > LsnToFlushTo.QuadPart)) {
03616
03617 LsnToFlushTo = Bcb->NewestLsn;
03618 }
03619
03620 Bcb = CONTAINING_RECORD( Bcb->BcbLinks.Blink,
BCB, BcbLinks );
03621 }
03622
03623
03624
03625
03626
03627
03628
if (BcbLookasideCheck) {
03629
03630
ASSERT( *Length == 0 );
03631
goto Accept_Page;
03632 }
03633
03634
03635
03636
03637
03638
03639
if (*Length != 0) {
03640
03641
03642
03643
03644
03645
03646
if (!ARGUMENT_PRESENT(TargetOffset)) {
03647
03648 SharedCacheMap->BeyondLastFlush = FileOffset->QuadPart + *Length;
03649
03650
if (SharedCacheMap->PagesToWrite > (*Length >>
PAGE_SHIFT)) {
03651 SharedCacheMap->PagesToWrite -= (*Length >>
PAGE_SHIFT);
03652 }
else {
03653 SharedCacheMap->PagesToWrite = 0;
03654 }
03655 }
03656
03657
break;
03658
03659
03660
03661
03662
03663 }
else if ((SharedCacheMap->BeyondLastFlush == 0) || ARGUMENT_PRESENT(TargetOffset)) {
03664
break;
03665 }
03666
03667
03668
03669
03670
03671
03672
03673 SharedCacheMap->BeyondLastFlush = 0;
03674 }
03675
03676
03677
03678
03679
03680
03681
03682 ExReleaseSpinLock( &SharedCacheMap->BcbSpinLock, OldIrql );
03683
03684
03685
03686
03687
03688
03689
if (LsnToFlushTo.QuadPart != 0) {
03690
03691
try {
03692
03693 (*SharedCacheMap->FlushToLsnRoutine) ( SharedCacheMap->LogHandle,
03694 LsnToFlushTo );
03695 } except(
CcExceptionFilter( GetExceptionCode() )) {
03696
03697
03698
03699
03700
03701
03702
03703
03704 LARGE_INTEGER LastOffset;
03705
PBCB NextBcb;
03706
03707
03708
03709
03710
03711
03712
03713
do {
03714 NextBcb = CONTAINING_RECORD( (*FirstBcb)->BcbLinks.Flink,
BCB, BcbLinks );
03715
03716
03717
03718
03719
03720
if ((*FirstBcb)->NodeTypeCode ==
CACHE_NTC_BCB) {
03721
03722 LastOffset = (*FirstBcb)->FileOffset;
03723
03724
CcUnpinFileData( *FirstBcb,
03725
BooleanFlagOn(SharedCacheMap->Flags,
DISABLE_WRITE_BEHIND),
03726
UNPIN );
03727 }
03728
03729 *FirstBcb = NextBcb;
03730 }
while (FileOffset->QuadPart != LastOffset.QuadPart);
03731
03732
03733
03734
03735
03736 *Length = 0;
03737 }
03738 }
03739
03740
03741
03742
03743
03744
DebugTrace2(0,
me,
" <FileOffset = %08lx, %08lx\n", FileOffset->LowPart,
03745 FileOffset->HighPart );
03746
DebugTrace( 0,
me,
" <Length = %08lx\n", *Length );
03747
DebugTrace(-1,
me,
"CcAcquireByteRangeForWrite -> %02lx\n", *Length != 0 );
03748
03749
return ((BOOLEAN)(*Length != 0));
03750 }
03751
03752
03753
03754
03755
03756
03757
VOID
03758 CcReleaseByteRangeFromWrite (
03759 IN
PSHARED_CACHE_MAP SharedCacheMap,
03760 IN PLARGE_INTEGER FileOffset,
03761 IN ULONG Length,
03762 IN
PBCB FirstBcb,
03763 IN BOOLEAN VerifyRequired
03764 )
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793 {
03794 LARGE_INTEGER LastOffset;
03795
PBCB NextBcb;
03796
03797
DebugTrace(+1,
me,
"CcReleaseByteRangeFromWrite:\n", 0);
03798
DebugTrace2(0,
me,
" FileOffset = %08lx, %08lx\n", FileOffset->LowPart,
03799 FileOffset->HighPart );
03800
03801
03802
03803
03804
03805
03806
if (FirstBcb ==
NULL) {
03807
03808
ASSERT(Length != 0);
03809
03810
if (VerifyRequired) {
03811
CcSetDirtyInMask( SharedCacheMap, FileOffset, Length );
03812 }
03813
03814
DebugTrace(-1,
me,
"CcReleaseByteRangeFromWrite -> VOID\n", 0);
03815
03816
return;
03817 }
03818
03819
03820
03821
03822
03823
03824
03825
03826
do {
03827 NextBcb = CONTAINING_RECORD( FirstBcb->BcbLinks.Flink,
BCB, BcbLinks );
03828
03829
03830
03831
03832
03833
if (FirstBcb->NodeTypeCode ==
CACHE_NTC_BCB) {
03834
03835 LastOffset = FirstBcb->FileOffset;
03836
03837
03838
03839
03840
03841
03842
03843
if (
FlagOn(SharedCacheMap->Flags,
MODIFIED_WRITE_DISABLED)) {
03844
03845
CcUnpinFileData( FirstBcb,
03846
BooleanFlagOn(SharedCacheMap->Flags,
DISABLE_WRITE_BEHIND),
03847
SET_CLEAN );
03848 }
03849
03850
03851
03852
03853
03854
03855
03856
if (VerifyRequired) {
03857
CcSetDirtyPinnedData( FirstBcb,
NULL );
03858 }
03859
03860
03861
03862
03863
03864
CcUnpinFileData( FirstBcb,
TRUE,
UNPIN );
03865 }
03866
03867 FirstBcb = NextBcb;
03868 }
while (FileOffset->QuadPart != LastOffset.QuadPart);
03869
03870
DebugTrace(-1,
me,
"CcReleaseByteRangeFromWrite -> VOID\n", 0);
03871 }
03872
03873
03874
03875
03876
03877
03878
VOID
03879
FASTCALL
03880 CcWriteBehind (
03881 IN
PSHARED_CACHE_MAP SharedCacheMap,
03882 IN PIO_STATUS_BLOCK IoStatus
03883 )
03884
03885
03886
03887
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914 {
03915 KIRQL OldIrql;
03916 ULONG ActivePage;
03917 ULONG PageIsDirty;
03918
PMBCB Mbcb;
03919
NTSTATUS Status;
03920 ULONG FileExclusive =
FALSE;
03921
PVACB ActiveVacb =
NULL;
03922
03923
DebugTrace(+1,
me,
"CcWriteBehind\n", 0 );
03924
DebugTrace( 0,
me,
" SharedCacheMap = %08lx\n", SharedCacheMap );
03925
03926
03927
03928
03929
03930
03931
03932
if (!(*SharedCacheMap->Callbacks->AcquireForLazyWrite)
03933 ( SharedCacheMap->LazyWriteContext,
TRUE )) {
03934
03935
03936
03937
03938
03939
03940
03941
03942
03943
CcAcquireMasterLock( &OldIrql );
03944
ClearFlag(SharedCacheMap->Flags,
WRITE_QUEUED);
03945
CcReleaseMasterLock( OldIrql );
03946
03947 IoStatus->Status = STATUS_FILE_LOCK_CONFLICT;
03948
return;
03949 }
03950
03951
03952
03953
03954
03955
03956
03957 ExAcquireFastLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
03958
CcAcquireMasterLockAtDpcLevel();
03959
03960
if ((SharedCacheMap->DirtyPages <= 1) || (SharedCacheMap->OpenCount == 0)) {
03961
GetActiveVacbAtDpcLevel( SharedCacheMap, ActiveVacb, ActivePage, PageIsDirty );
03962 }
03963
03964
03965
03966
03967
03968
03969
03970
CcIncrementOpenCount( SharedCacheMap, 'brWS' );
03971
03972
03973
03974
03975
03976
03977
if ((Mbcb = SharedCacheMap->Mbcb) != 0) {
03978
03979
03980
03981
03982
03983
03984 Mbcb->
PagesToWrite = Mbcb->
DirtyPages + ((ActiveVacb !=
NULL) ? 1 : 0);
03985
03986
if (Mbcb->
PagesToWrite >
CcPagesYetToWrite) {
03987
03988 Mbcb->
PagesToWrite =
CcPagesYetToWrite;
03989 }
03990 }
03991
03992
CcReleaseMasterLockFromDpcLevel();
03993 ExReleaseFastLock( &SharedCacheMap->BcbSpinLock, OldIrql );
03994
03995
03996
03997
03998
03999
if (ActiveVacb !=
NULL) {
04000
04001
CcFreeActiveVacb( SharedCacheMap, ActiveVacb, ActivePage, PageIsDirty );
04002 }
04003
04004
04005
04006
04007
04008
04009
04010
04011
CcFlushCache( SharedCacheMap->FileObject->SectionObjectPointer,
04012 &
CcNoDelay,
04013 1,
04014 IoStatus );
04015
04016
04017
04018
04019
04020 (*SharedCacheMap->Callbacks->ReleaseFromLazyWrite)
04021 ( SharedCacheMap->LazyWriteContext );
04022
04023
04024
04025
04026
04027
if (!
NT_SUCCESS(IoStatus->Status) && !
RetryError(IoStatus->Status)) {
04028
04029
04030
04031
04032
04033
04034 POBJECT_NAME_INFORMATION FileNameInfo;
04035
NTSTATUS QueryStatus;
04036 ULONG whocares;
04037
04038 FileNameInfo =
ExAllocatePoolWithTag(
PagedPool, 1024, 'nFcC' );
04039
04040
if ( FileNameInfo ) {
04041 QueryStatus =
ObQueryNameString( SharedCacheMap->FileObject,
04042 FileNameInfo,
04043 1024,
04044 &whocares );
04045
04046
if ( !
NT_SUCCESS(QueryStatus) ) {
04047
ExFreePool(FileNameInfo);
04048 FileNameInfo =
NULL;
04049 }
04050 }
04051
04052
04053
04054
04055
04056
04057 KdPrint((
"CACHE MANAGER: Lost delayed write FileOb %08x status %08x\n", SharedCacheMap->FileObject, IoStatus->Status));
04058
04059
if ( FileNameInfo ) {
04060
IoRaiseInformationalHardError( STATUS_LOST_WRITEBEHIND_DATA,&FileNameInfo->Name,
NULL );
04061
ExFreePool(FileNameInfo);
04062 }
else {
04063
if ( SharedCacheMap->FileObject->FileName.Length &&
04064 SharedCacheMap->FileObject->FileName.MaximumLength &&
04065 SharedCacheMap->FileObject->FileName.Buffer ) {
04066
04067
IoRaiseInformationalHardError( STATUS_LOST_WRITEBEHIND_DATA,&SharedCacheMap->FileObject->FileName,
NULL );
04068 }
04069 }
04070
04071
CcLogError( SharedCacheMap->FileObject->DeviceObject,
04072 IO_LOST_DELAYED_WRITE,
04073 IoStatus->Status,
04074 &(SharedCacheMap->FileObject->FileName) );
04075
04076
04077
04078
04079 }
else if (!IsListEmpty(&
CcDeferredWrites)) {
04080
CcPostDeferredWrites();
04081 }
04082
04083
04084
04085
04086
04087 ExAcquireSpinLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
04088
04089
04090
04091
04092
04093
04094
04095
04096
04097
04098
04099
Status = STATUS_SUCCESS;
04100
if (
FlagOn(SharedCacheMap->Flags,
LAZY_WRITE_OCCURRED) &&
04101 (SharedCacheMap->ValidDataGoal.QuadPart >= SharedCacheMap->ValidDataLength.QuadPart) &&
04102 (SharedCacheMap->ValidDataLength.QuadPart != MAXLONGLONG) &&
04103 (SharedCacheMap->FileSize.QuadPart != 0)) {
04104
04105 LARGE_INTEGER NewValidDataLength;
04106
04107 NewValidDataLength =
CcGetFlushedValidData( SharedCacheMap->FileObject->SectionObjectPointer,
04108
TRUE );
04109
04110
04111
04112
04113
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123
if ( NewValidDataLength.QuadPart >= SharedCacheMap->ValidDataLength.QuadPart ) {
04124
04125 ExReleaseSpinLock( &SharedCacheMap->BcbSpinLock, OldIrql );
04126
04127
04128
04129
04130
04131
04132
Status =
CcSetValidData( SharedCacheMap->FileObject,
04133 &NewValidDataLength );
04134
04135 ExAcquireSpinLock( &SharedCacheMap->BcbSpinLock, &OldIrql );
04136
if (
NT_SUCCESS(
Status)) {
04137 SharedCacheMap->ValidDataLength = NewValidDataLength;
04138
#ifdef TOMM
04139
}
else if ((
Status != STATUS_INSUFFICIENT_RESOURCES) && !
RetryError(
Status)) {
04140
DbgPrint(
"Unexpected status from CcSetValidData: %08lx, FileObject: %08lx\n",
04141
Status,
04142 SharedCacheMap->FileObject);
04143 DbgBreakPoint();
04144
#endif TOMM
04145
}
04146 }
04147 }
04148
04149 ExReleaseSpinLock( &SharedCacheMap->BcbSpinLock, OldIrql );
04150
04151
04152
04153
04154
04155
CcAcquireMasterLock( &OldIrql );
04156
CcDecrementOpenCount( SharedCacheMap, 'brWF' );
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
if ((SharedCacheMap->OpenCount == 0)
04169
04170 &&
04171
04172 (
NT_SUCCESS(
Status) || ((
Status != STATUS_INSUFFICIENT_RESOURCES) && !
RetryError(
Status)))) {
04173
04174
CcReleaseMasterLock( OldIrql );
04175
FsRtlAcquireFileExclusive( SharedCacheMap->FileObject );
04176
CcAcquireMasterLock( &OldIrql );
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
if ((SharedCacheMap->OpenCount == 0)
04189
04190 &&
04191
04192 ((SharedCacheMap->DirtyPages == 0) || ((SharedCacheMap->FileSize.QuadPart == 0) &&
04193 !
FlagOn(SharedCacheMap->Flags,
PIN_ACCESS)))) {
04194
04195
04196
04197
04198
04199
04200
CcDeleteSharedCacheMap( SharedCacheMap, OldIrql,
TRUE );
04201 IoStatus->Information = 0;
04202 SharedCacheMap =
NULL;
04203
04204 }
else {
04205
04206
CcReleaseMasterLock( OldIrql );
04207
FsRtlReleaseFile( SharedCacheMap->FileObject );
04208
CcAcquireMasterLock( &OldIrql );
04209 }
04210 }
04211
04212
04213
04214
04215
04216
04217
if (SharedCacheMap !=
NULL) {
04218
04219
if (IoStatus->Information !=
CC_REQUEUE) {
04220
ClearFlag(SharedCacheMap->Flags,
WRITE_QUEUED);
04221 }
04222
CcReleaseMasterLock( OldIrql );
04223 }
04224
04225
DebugTrace(-1,
me,
"CcWriteBehind->VOID\n", 0 );
04226
04227
return;
04228 }
04229
04230
04231 LARGE_INTEGER
04232 CcGetFlushedValidData (
04233 IN
PSECTION_OBJECT_POINTERS SectionObjectPointer,
04234 IN BOOLEAN CcInternalCaller
04235 )
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265 {
04266
PSHARED_CACHE_MAP SharedCacheMap;
04267 KIRQL OldIrql;
04268 LARGE_INTEGER NewValidDataLength;
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
if (!CcInternalCaller) {
04279
04280
CcAcquireMasterLock( &OldIrql );
04281
04282 SharedCacheMap = SectionObjectPointer->SharedCacheMap;
04283
04284
if (SharedCacheMap ==
NULL) {
04285
CcReleaseMasterLock( OldIrql );
04286 NewValidDataLength.QuadPart = MAXLONGLONG;
04287
return NewValidDataLength;
04288 }
04289
04290
CcIncrementOpenCount( SharedCacheMap, 'dfGS' );
04291
CcReleaseMasterLock( OldIrql );
04292 ExAcquireSpinLock( &SharedCacheMap->
BcbSpinLock, &OldIrql );
04293
04294 }
else {
04295
04296 SharedCacheMap = SectionObjectPointer->SharedCacheMap;
04297 }
04298
04299
ASSERT( SharedCacheMap !=
NULL );
04300
04301
04302
04303
04304
04305
04306 NewValidDataLength = SharedCacheMap->
ValidDataGoal;
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
if (SharedCacheMap->
DirtyPages) {
04329
04330
PBITMAP_RANGE BitmapRange;
04331
PBCB LastBcb;
04332
PMBCB Mbcb = SharedCacheMap->
Mbcb;
04333
04334
if ((Mbcb !=
NULL) && (Mbcb->
DirtyPages != 0)) {
04335
04336 BitmapRange =
CcFindBitmapRangeToClean( Mbcb, 0 );
04337
04338
ASSERT(BitmapRange->
FirstDirtyPage != MAXULONG);
04339
04340 NewValidDataLength.QuadPart = (BitmapRange->
BasePage + BitmapRange->
FirstDirtyPage)
04341 <<
PAGE_SHIFT;
04342 }
04343
04344 LastBcb = CONTAINING_RECORD( SharedCacheMap->
BcbList.Flink,
04345
BCB,
04346 BcbLinks );
04347
04348
while (&LastBcb->
BcbLinks != &SharedCacheMap->
BcbList) {
04349
04350
if ((LastBcb->
NodeTypeCode ==
CACHE_NTC_BCB) && LastBcb->
Dirty) {
04351
break;
04352 }
04353
04354 LastBcb = CONTAINING_RECORD( LastBcb->
BcbLinks.Flink,
04355
BCB,
04356 BcbLinks );
04357 }
04358
04359
04360
04361
04362
04363
if ((&LastBcb->
BcbLinks != &SharedCacheMap->
BcbList) &&
04364 (LastBcb->
FileOffset.QuadPart < NewValidDataLength.QuadPart )) {
04365
04366 NewValidDataLength = LastBcb->
FileOffset;
04367 }
04368 }
04369
04370
if (!CcInternalCaller) {
04371
04372
04373
04374
04375
04376
CcAcquireMasterLockAtDpcLevel();
04377
CcDecrementOpenCount( SharedCacheMap, 'dfGF' );
04378
04379
if ((SharedCacheMap->
OpenCount == 0) &&
04380 !
FlagOn(SharedCacheMap->
Flags,
WRITE_QUEUED) &&
04381 (SharedCacheMap->
DirtyPages == 0)) {
04382
04383
04384
04385
04386
04387 RemoveEntryList( &SharedCacheMap->
SharedCacheMapLinks );
04388 InsertTailList( &
CcDirtySharedCacheMapList.
SharedCacheMapLinks,
04389 &SharedCacheMap->
SharedCacheMapLinks );
04390
04391
04392
04393
04394
04395
04396
LazyWriter.
OtherWork =
TRUE;
04397
if (!
LazyWriter.
ScanActive) {
04398
CcScheduleLazyWriteScan();
04399 }
04400 }
04401
04402 ExReleaseSpinLockFromDpcLevel( &SharedCacheMap->
BcbSpinLock );
04403
CcReleaseMasterLock( OldIrql );
04404 }
04405
04406
return NewValidDataLength;
04407 }
04408
04409
04410
VOID
04411 CcFlushCache (
04412 IN
PSECTION_OBJECT_POINTERS SectionObjectPointer,
04413 IN PLARGE_INTEGER FileOffset OPTIONAL,
04414 IN ULONG Length,
04415 OUT PIO_STATUS_BLOCK IoStatus OPTIONAL
04416 )
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445
04446
04447
04448
04449
04450
04451
04452 {
04453 LARGE_INTEGER NextFileOffset, TargetOffset;
04454 ULONG NextLength;
04455
PBCB FirstBcb;
04456 KIRQL OldIrql;
04457
PSHARED_CACHE_MAP SharedCacheMap;
04458 IO_STATUS_BLOCK TrashStatus;
04459 PVOID TempVa;
04460 ULONG RemainingLength, TempLength;
04461
NTSTATUS PopupStatus;
04462 BOOLEAN HotSpot;
04463 ULONG BytesWritten = 0;
04464 BOOLEAN PopupRequired =
FALSE;
04465 BOOLEAN VerifyRequired =
FALSE;
04466 BOOLEAN IsLazyWriter =
FALSE;
04467 BOOLEAN FreeActiveVacb =
FALSE;
04468
PVACB ActiveVacb =
NULL;
04469
NTSTATUS Status = STATUS_SUCCESS;
04470 LARGE_INTEGER EndTick, CurrentTick;
04471
04472
DebugTrace(+1,
me,
"CcFlushCache:\n", 0 );
04473
DebugTrace( 0,
mm,
" SectionObjectPointer = %08lx\n", SectionObjectPointer );
04474
DebugTrace2(0,
me,
" FileOffset = %08lx, %08lx\n",
04475 ARGUMENT_PRESENT(FileOffset) ? FileOffset->LowPart
04476 : 0,
04477 ARGUMENT_PRESENT(FileOffset) ? FileOffset->HighPart
04478 : 0 );
04479
DebugTrace( 0,
me,
" Length = %08lx\n", Length );
04480
04481
04482
04483
04484
04485
if (!ARGUMENT_PRESENT(IoStatus)) {
04486 IoStatus = &TrashStatus;
04487 }
04488 IoStatus->Status = STATUS_SUCCESS;
04489 IoStatus->Information = 0;
04490
04491
04492
04493
04494
04495
04496
04497
04498
04499
04500
04501
04502
if (FileOffset == &
CcNoDelay) {
04503 IoStatus->Status = STATUS_VERIFY_REQUIRED;
04504 IsLazyWriter =
TRUE;
04505 FileOffset =
NULL;
04506 }
04507
04508
04509
04510
04511
04512
if (ARGUMENT_PRESENT(FileOffset) && (Length == 0)) {
04513
04514
DebugTrace(-1,
me,
"CcFlushCache -> VOID\n", 0 );
04515
return;
04516 }
04517
04518
04519
04520
04521
04522
CcAcquireMasterLock( &OldIrql );
04523
04524 SharedCacheMap = SectionObjectPointer->SharedCacheMap;
04525
04526
if (SharedCacheMap !=
NULL) {
04527
04528
04529
04530
04531
04532
CcIncrementOpenCount( SharedCacheMap, 'fcCS' );
04533
04534
if ((SharedCacheMap->
NeedToZero !=
NULL) || (SharedCacheMap->
ActiveVacb !=
NULL)) {
04535
04536 ULONG FirstPage = 0;
04537 ULONG LastPage = MAXULONG;
04538
04539
if (ARGUMENT_PRESENT(FileOffset)) {
04540
04541 FirstPage = (ULONG)(FileOffset->QuadPart >>
PAGE_SHIFT);
04542 LastPage = (ULONG)((FileOffset->QuadPart + Length - 1) >>
PAGE_SHIFT);
04543 }
04544
04545
04546
04547
04548
04549
04550
04551
04552
if (((((LONGLONG)LastPage + 1) <<
PAGE_SHIFT) > SharedCacheMap->
ValidDataGoal.QuadPart) ||
04553
04554 ((SharedCacheMap->
NeedToZero !=
NULL) &&
04555 (FirstPage <= SharedCacheMap->
NeedToZeroPage) &&
04556 (LastPage >= SharedCacheMap->
NeedToZeroPage)) ||
04557
04558 ((SharedCacheMap->
ActiveVacb !=
NULL) &&
04559 (FirstPage <= SharedCacheMap->
ActivePage) &&
04560 (LastPage >= SharedCacheMap->
ActivePage))) {
04561
04562
GetActiveVacbAtDpcLevel( SharedCacheMap, ActiveVacb, RemainingLength, TempLength );
04563 FreeActiveVacb =
TRUE;
04564 }
04565 }
04566 }
04567
04568
CcReleaseMasterLock( OldIrql );
04569
04570
if (FreeActiveVacb) {
04571
CcFreeActiveVacb( SharedCacheMap, ActiveVacb, RemainingLength, TempLength );
04572 }
04573
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586
04587
if ((SharedCacheMap ==
NULL)
04588
04589 ||
04590
04591
FlagOn(((
PFSRTL_COMMON_FCB_HEADER)(SharedCacheMap->
FileObject->
FsContext))->Flags,
04592
FSRTL_FLAG_USER_MAPPED_FILE) && !IsLazyWriter) {
04593
04594
04595
04596
04597
04598
DebugTrace( 0,
mm,
"MmFlushSection:\n", 0 );
04599
DebugTrace( 0,
mm,
" SectionObjectPointer = %08lx\n", SectionObjectPointer );
04600
DebugTrace2(0,
me,
" FileOffset = %08lx, %08lx\n",
04601 ARGUMENT_PRESENT(FileOffset) ? FileOffset->LowPart
04602 : 0,
04603 ARGUMENT_PRESENT(FileOffset) ? FileOffset->HighPart
04604 : 0 );
04605
DebugTrace( 0,
mm,
" RegionSize = %08lx\n", Length );
04606
04607
try {
04608
04609
Status =
MmFlushSection( SectionObjectPointer,
04610 FileOffset,
04611 Length,
04612 IoStatus,
04613
TRUE );
04614
04615 } except(
CcExceptionFilter( IoStatus->Status = GetExceptionCode() )) {
04616
04617 KdPrint((
"CACHE MANAGER: MmFlushSection raised %08lx\n", IoStatus->Status));
04618 }
04619
04620
if ((!
NT_SUCCESS(IoStatus->Status)) && !
RetryError(IoStatus->Status)) {
04621
04622 PopupRequired =
TRUE;
04623 PopupStatus = IoStatus->Status;
04624 }
04625
04626
DebugTrace2(0,
mm,
" <IoStatus = %08lx, %08lx\n",
04627 IoStatus->Status, IoStatus->Information );
04628 }
04629
04630
04631
04632
04633
04634
if (SharedCacheMap !=
NULL) {
04635
04636
04637
04638
04639
04640
04641
04642
if (!IsLazyWriter && !ARGUMENT_PRESENT(FileOffset)) {
04643
04644 SharedCacheMap->
ValidDataLength = SharedCacheMap->
ValidDataGoal;
04645 }
04646
04647
04648
04649
04650
04651
if (ARGUMENT_PRESENT(FileOffset)) {
04652 TargetOffset = *FileOffset;
04653 }
04654
04655
04656
04657
04658
04659
04660
04661 NextLength = 1;
04662
if (Length != 0) {
04663 NextLength = Length;
04664 }
04665
04666
04667
04668
04669
04670
04671
if (IsLazyWriter) {
04672
04673
KeQueryTickCount( &EndTick );
04674 EndTick.QuadPart +=
CcIdleDelayTick;
04675 }
04676
04677
04678
04679
04680
04681
04682
while (((SharedCacheMap->
PagesToWrite != 0) || !IsLazyWriter)
04683
04684 &&
04685 ((SharedCacheMap->
FileSize.QuadPart != 0) ||
04686
FlagOn(SharedCacheMap->
Flags,
PIN_ACCESS))
04687
04688 &&
04689
04690 !VerifyRequired
04691
04692 &&
04693
04694
CcAcquireByteRangeForWrite ( SharedCacheMap,
04695 IsLazyWriter ?
NULL : (ARGUMENT_PRESENT(FileOffset) ?
04696 &TargetOffset :
NULL),
04697 IsLazyWriter ? 0: NextLength,
04698 &NextFileOffset,
04699 &NextLength,
04700 &FirstBcb )) {
04701
04702
04703
04704
04705
04706 HotSpot =
FALSE;
04707
04708
04709
04710
04711
04712
04713
04714 RemainingLength = NextLength;
04715
04716
do {
04717
04718
04719
04720
04721
04722
04723
if ((TempVa =
CcGetVirtualAddressIfMapped( SharedCacheMap,
04724 NextFileOffset.QuadPart + NextLength - RemainingLength,
04725 &ActiveVacb,
04726 &TempLength)) !=
NULL) {
04727
04728
04729
04730
04731
04732
04733
if (TempLength > RemainingLength) {
04734 TempLength = RemainingLength;
04735 }
04736
04737
04738
04739
04740
04741
04742
04743
04744
04745 HotSpot = (BOOLEAN)((
MmSetAddressRangeModified(TempVa, TempLength) || HotSpot) &&
04746 ((NextFileOffset.QuadPart + NextLength) <
04747 (SharedCacheMap->
ValidDataLength.QuadPart)) &&
04748 ((SharedCacheMap->
LazyWritePassCount & 0xF) != 0) && IsLazyWriter) &&
04749 !
FlagOn(SharedCacheMap->
Flags,
MODIFIED_WRITE_DISABLED);
04750
04751
CcFreeVirtualAddress( ActiveVacb );
04752
04753 }
else {
04754
04755
04756
04757
04758
04759
if (TempLength > RemainingLength) {
04760 TempLength = RemainingLength;
04761 }
04762 }
04763
04764
04765
04766
04767
04768 RemainingLength -= TempLength;
04769
04770
04771
04772
04773
04774 }
while (RemainingLength != 0);
04775
04776
CcLazyWriteHotSpots += HotSpot;
04777
04778
04779
04780
04781
04782
if (!HotSpot) {
04783
04784
MmFlushSection( SharedCacheMap->
FileObject->
SectionObjectPointer,
04785 &NextFileOffset,
04786 NextLength,
04787 IoStatus,
04788 !IsLazyWriter );
04789
04790
if (
NT_SUCCESS(IoStatus->Status)) {
04791
04792
if (!
FlagOn(SharedCacheMap->
Flags,
LAZY_WRITE_OCCURRED)) {
04793
04794
CcAcquireMasterLock( &OldIrql );
04795
SetFlag(SharedCacheMap->
Flags,
LAZY_WRITE_OCCURRED);
04796
CcReleaseMasterLock( OldIrql );
04797 }
04798
04799
04800
04801
04802
04803
if (IsLazyWriter) {
04804
04805
CcLazyWriteIos += 1;
04806
CcLazyWritePages += (NextLength +
PAGE_SIZE - 1) >>
PAGE_SHIFT;
04807 }
04808
04809 }
else {
04810
04811 LARGE_INTEGER
Offset = NextFileOffset;
04812 ULONG RetryLength = NextLength;
04813
04814
DebugTrace2( 0, 0,
"I/O Error on Cache Flush: %08lx, %08lx\n",
04815 IoStatus->Status, IoStatus->Information );
04816
04817
if (
RetryError(IoStatus->Status)) {
04818
04819 VerifyRequired =
TRUE;
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831
04832
04833 }
else {
04834
04835
do {
04836
04837
DebugTrace2( 0, 0,
"Trying page at offset %08lx, %08lx\n",
04838
Offset.LowPart,
Offset.HighPart );
04839
04840
MmFlushSection ( SharedCacheMap->
FileObject->
SectionObjectPointer,
04841 &
Offset,
04842
PAGE_SIZE,
04843 IoStatus,
04844 !IsLazyWriter );
04845
04846
DebugTrace2( 0, 0,
"I/O status = %08lx, %08lx\n",
04847 IoStatus->Status, IoStatus->Information );
04848
04849
if (
NT_SUCCESS(IoStatus->Status)) {
04850
CcAcquireMasterLock( &OldIrql );
04851
SetFlag(SharedCacheMap->
Flags,
LAZY_WRITE_OCCURRED);
04852
CcReleaseMasterLock( OldIrql );
04853 }
04854
04855
if ((!
NT_SUCCESS(IoStatus->Status)) && !
RetryError(IoStatus->Status)) {
04856
04857 PopupRequired =
TRUE;
04858 PopupStatus = IoStatus->Status;
04859 }
04860
04861 VerifyRequired = VerifyRequired ||
RetryError(IoStatus->Status);
04862
04863
Offset.QuadPart =
Offset.QuadPart + (LONGLONG)
PAGE_SIZE;
04864 RetryLength -=
PAGE_SIZE;
04865
04866 }
while(RetryLength > 0);
04867 }
04868 }
04869 }
04870
04871
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
CcReleaseByteRangeFromWrite ( SharedCacheMap,
04892 &NextFileOffset,
04893 NextLength,
04894 FirstBcb,
04895 (BOOLEAN)(HotSpot || VerifyRequired) );
04896
04897
04898
04899
04900
04901 BytesWritten += NextLength;
04902
if ((BytesWritten >= 0x40000) && !IsListEmpty(&
CcDeferredWrites)) {
04903
CcPostDeferredWrites();
04904 BytesWritten = 0;
04905 }
04906
04907
04908
04909
04910
04911
04912
04913
if (IsLazyWriter) {
04914
04915
KeQueryTickCount( &CurrentTick );
04916
04917
04918
04919
04920
04921
if (CurrentTick.QuadPart > EndTick.QuadPart) {
04922
04923 IoStatus->Information =
CC_REQUEUE;
04924
break;
04925 }
04926 }
04927
04928
04929
04930
04931
04932
if (ARGUMENT_PRESENT(FileOffset)) {
04933
04934 NextFileOffset.QuadPart += NextLength;
04935
04936
04937
04938
04939
04940
if ((FileOffset->QuadPart + Length) <= NextFileOffset.QuadPart) {
04941
break;
04942 }
04943
04944
04945
04946
04947
04948 NextLength = (ULONG)((FileOffset->QuadPart + Length) - NextFileOffset.QuadPart);
04949 TargetOffset = NextFileOffset;
04950 }
04951 }
04952 }
04953
04954
04955
04956
04957
04958
04959
04960
if (BytesWritten != 0 && !IsListEmpty(&
CcDeferredWrites)) {
04961
04962
CcPostDeferredWrites();
04963 }
04964
04965
04966
04967
04968
04969
if (SharedCacheMap !=
NULL) {
04970
04971
04972
04973
04974
04975
CcAcquireMasterLock( &OldIrql );
04976
04977
CcDecrementOpenCount( SharedCacheMap, 'fcCF' );
04978
04979
if ((SharedCacheMap->
OpenCount == 0) &&
04980 !
FlagOn(SharedCacheMap->
Flags,
WRITE_QUEUED) &&
04981 (SharedCacheMap->
DirtyPages == 0)) {
04982
04983
04984
04985
04986
04987 RemoveEntryList( &SharedCacheMap->
SharedCacheMapLinks );
04988 InsertTailList( &
CcDirtySharedCacheMapList.
SharedCacheMapLinks,
04989 &SharedCacheMap->
SharedCacheMapLinks );
04990
04991
04992
04993
04994
04995
04996
LazyWriter.
OtherWork =
TRUE;
04997
if (!
LazyWriter.
ScanActive) {
04998
CcScheduleLazyWriteScan();
04999 }
05000 }
05001
05002
CcReleaseMasterLock( OldIrql );
05003 }
05004
05005
05006
05007
05008
05009
05010
if (PopupRequired) {
05011 IoStatus->Status = PopupStatus;
05012 }
05013
05014
05015
05016
05017
DebugTrace(-1,
me,
"CcFlushCache -> VOID\n", 0 );
05018
05019
return;
05020 }
05021
05022
05023 PVOID
05024 CcRemapBcb (
05025 IN PVOID Bcb
05026 )
05027
05028
05029
05030
05031
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044
05045
05046
05047 {
05048 KIRQL OldIrql;
05049
PVACB Vacb;
05050
05051
05052
05053
05054
05055 Bcb = (PVOID) ((ULONG_PTR)Bcb & ~1);
05056
05057
if (((
PBCB)Bcb)->NodeTypeCode ==
CACHE_NTC_OBCB) {
05058
05059
05060
05061
05062
05063
05064 Vacb = ((
POBCB)Bcb)->Bcbs[0]->Vacb;
05065
05066 }
else if (((
PBCB)Bcb)->NodeTypeCode ==
CACHE_NTC_BCB) {
05067
05068
05069
05070
05071
05072 Vacb = ((
PBCB)Bcb)->Vacb;
05073
05074 }
else {
05075
05076
05077
05078
05079
05080
05081 Vacb = (
PVACB) Bcb;
05082 }
05083
05084
ASSERT((Vacb >=
CcVacbs) && (Vacb <
CcBeyondVacbs));
05085
05086
05087
05088
05089
05090
CcAcquireVacbLock( &OldIrql );
05091
05092 Vacb->
Overlay.ActiveCount += 1;
05093
05094
CcReleaseVacbLock( OldIrql );
05095
05096
return (PVOID) ((ULONG_PTR)Vacb | 1);
05097 }
05098
05099
05100
VOID
05101 CcRepinBcb (
05102 IN PVOID Bcb
05103 )
05104
05105
05106
05107
05108
05109
05110
05111
05112
05113
05114
05115
05116
05117
05118
05119
05120
05121
05122
05123
05124
05125
05126
05127
05128
05129
05130
05131 {
05132 KIRQL OldIrql;
05133
05134 ExAcquireFastLock( &((
PBCB)Bcb)->SharedCacheMap->BcbSpinLock, &OldIrql );
05135
05136 ((
PBCB)Bcb)->PinCount += 1;
05137
05138 ExReleaseFastLock( &((
PBCB)Bcb)->SharedCacheMap->BcbSpinLock, OldIrql );
05139 }
05140
05141
05142
VOID
05143 CcUnpinRepinnedBcb (
05144 IN PVOID Bcb,
05145 IN BOOLEAN WriteThrough,
05146 OUT PIO_STATUS_BLOCK IoStatus
05147 )
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169
05170
05171
05172
05173
05174
05175
05176
05177
05178 {
05179
PSHARED_CACHE_MAP SharedCacheMap = ((
PBCB)Bcb)->SharedCacheMap;
05180
05181
DebugTrace(+1,
me,
"CcUnpinRepinnedBcb\n", 0 );
05182
DebugTrace( 0,
me,
" Bcb = %08lx\n", Bcb );
05183
DebugTrace( 0,
me,
" WriteThrough = %02lx\n", WriteThrough );
05184
05185
05186
05187
05188
05189 IoStatus->Status = STATUS_SUCCESS;
05190
05191
if (WriteThrough) {
05192
05193
05194
05195
05196
05197
05198
if (
FlagOn(SharedCacheMap->
Flags,
MODIFIED_WRITE_DISABLED)) {
05199
ExAcquireResourceExclusive( &((
PBCB)Bcb)->
Resource,
TRUE );
05200 }
05201
05202
05203
05204
05205
05206
05207
05208
if (((
PBCB)Bcb)->Dirty) {
05209
05210
05211
05212
05213
05214
ASSERT( ((
PBCB)Bcb)->BaseAddress !=
NULL );
05215
MmSetAddressRangeModified( ((
PBCB)Bcb)->BaseAddress,
05216 ((
PBCB)Bcb)->ByteLength );
05217
05218
05219
05220
05221
05222
05223
05224
05225
05226
05227
05228
05229
05230
05231
05232
05233
05234
05235
05236
05237
05238
05239
05240
05241
CcUnpinFileData( (
PBCB)Bcb,
TRUE,
SET_CLEAN );
05242
05243
05244
05245
05246
05247
MmFlushSection( ((
PBCB)Bcb)->SharedCacheMap->
FileObject->
SectionObjectPointer,
05248 &((
PBCB)Bcb)->FileOffset,
05249 ((
PBCB)Bcb)->ByteLength,
05250 IoStatus,
05251
TRUE );
05252
05253
05254
05255
05256
05257
05258
if (
RetryError(IoStatus->Status)) {
05259
CcSetDirtyPinnedData( (
PBCB)Bcb,
NULL );
05260 }
05261
05262
05263
05264
05265
05266
CcUnpinFileData( (
PBCB)Bcb,
FALSE,
UNPIN );
05267
05268
05269
05270
05271
05272
if (!IsListEmpty(&
CcDeferredWrites)) {
05273
CcPostDeferredWrites();
05274 }
05275 }
05276
else {
05277
05278
05279
05280
05281
05282
CcUnpinFileData( (
PBCB)Bcb,
FALSE,
UNPIN );
05283
05284 }
05285
05286
DebugTrace2(0,
me,
" <IoStatus = %08lx, %08lx\n", IoStatus->Status,
05287 IoStatus->Information );
05288 }
05289
05290
05291
05292
05293
05294
else {
05295
05296
CcUnpinFileData( (
PBCB)Bcb,
TRUE,
UNPIN );
05297
05298
05299
05300
05301
05302 IoStatus->Status = STATUS_SUCCESS;
05303 }
05304
05305
DebugTrace(-1,
me,
"CcUnpinRepinnedBcb -> VOID\n", 0 );
05306 }
05307
05308
05309
05310
05311
05312
05313 BOOLEAN
05314 CcFindBcb (
05315 IN
PSHARED_CACHE_MAP SharedCacheMap,
05316 IN PLARGE_INTEGER FileOffset,
05317 IN OUT PLARGE_INTEGER BeyondLastByte,
05318 OUT
PBCB *Bcb
05319 )
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336
05337
05338
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354
05355
05356
05357
05358
05359
05360
05361
05362
05363 {
05364 PLIST_ENTRY BcbList;
05365
PBCB Bcbt;
05366 BOOLEAN Found =
FALSE;
05367
05368
DebugTrace(+1,
me,
"CcFindBcb:\n", 0 );
05369
DebugTrace( 0,
me,
" SharedCacheMap = %08lx\n", SharedCacheMap );
05370
DebugTrace2(0,
me,
" FileOffset = %08lx, %08lx\n", FileOffset->LowPart,
05371 FileOffset->HighPart );
05372
DebugTrace2(0,
me,
" TrialLength = %08lx, %08lx\n", TrialLength->LowPart,
05373 TrialLength->HighPart );
05374
05375
05376
05377
05378
05379
05380
05381
ASSERT(FIELD_OFFSET(
SHARED_CACHE_MAP, BcbList) == FIELD_OFFSET(
BCB, BcbLinks));
05382
05383
05384
05385
05386
05387
05388
05389
ASSERT((
CACHE_NTC_BCB & 3) != 0);
05390
05391
05392
05393
05394
05395
05396
05397 BcbList =
GetBcbListHead( SharedCacheMap, FileOffset->QuadPart +
SIZE_PER_BCB_LIST,
TRUE );
05398
05399
05400
05401
05402
05403
05404 Bcbt = CONTAINING_RECORD(BcbList->Flink,
BCB, BcbLinks);
05405
05406
05407
05408
05409
05410
05411
05412
if (FileOffset->HighPart == 0 &&
05413 Bcbt->
NodeTypeCode ==
CACHE_NTC_BCB &&
05414 Bcbt->
BeyondLastByte.HighPart == 0) {
05415
05416
05417
05418
05419
05420
while (Bcbt->
NodeTypeCode ==
CACHE_NTC_BCB) {
05421
05422
05423
05424
05425
05426
05427
05428
if (FileOffset->LowPart >= Bcbt->
BeyondLastByte.LowPart) {
05429
break;
05430 }
05431
05432
05433
05434
05435
05436
05437
05438
05439
05440
if (FileOffset->LowPart >= Bcbt->
FileOffset.LowPart) {
05441 Found =
TRUE;
05442
break;
05443 }
05444
05445
05446
05447
05448
05449
05450
05451
05452
05453
05454
if (BeyondLastByte->LowPart >= Bcbt->
FileOffset.LowPart) {
05455 BeyondLastByte->LowPart = Bcbt->
FileOffset.LowPart;
05456 }
05457
05458
05459
05460
05461
05462
05463 Bcbt = CONTAINING_RECORD( Bcbt->
BcbLinks.Flink,
05464
BCB,
05465 BcbLinks );
05466
05467 }
05468
05469 }
else {
05470
05471
05472
05473
05474
05475
while (Bcbt->
NodeTypeCode ==
CACHE_NTC_BCB) {
05476
05477
05478
05479
05480
05481
05482
05483
if (FileOffset->QuadPart >= Bcbt->
BeyondLastByte.QuadPart) {
05484
break;
05485 }
05486
05487
05488
05489
05490
05491
05492
05493
05494
05495
if (FileOffset->QuadPart >= Bcbt->
FileOffset.QuadPart) {
05496 Found =
TRUE;
05497
break;
05498 }
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508
05509
if (BeyondLastByte->QuadPart >= Bcbt->
FileOffset.QuadPart) {
05510 BeyondLastByte->QuadPart = Bcbt->
FileOffset.QuadPart;
05511 }
05512
05513
05514
05515
05516
05517
05518 Bcbt = CONTAINING_RECORD( Bcbt->
BcbLinks.Flink,
05519
BCB,
05520 BcbLinks );
05521
05522 }
05523 }
05524
05525 *Bcb = Bcbt;
05526
05527
DebugTrace2(0,
me,
" <TrialLength = %08lx, %08lx\n", TrialLength->LowPart,
05528 TrialLength->HighPart );
05529
DebugTrace( 0,
me,
" <Bcb = %08lx\n", *Bcb );
05530
DebugTrace(-1,
me,
"CcFindBcb -> %02lx\n", Found );
05531
05532
return Found;
05533 }
05534
05535
05536
05537
05538
05539
05540
PBCB
05541 CcAllocateInitializeBcb (
05542 IN OUT
PSHARED_CACHE_MAP SharedCacheMap OPTIONAL,
05543 IN OUT
PBCB AfterBcb,
05544 IN PLARGE_INTEGER FileOffset,
05545 IN PLARGE_INTEGER TrialLength
05546 )
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567
05568
05569
05570
05571
05572
05573
05574
05575
05576 {
05577
PBCB Bcb;
05578 CSHORT NodeIsInZone;
05579 ULONG RoundedBcbSize = (
sizeof(
BCB) + 7) & ~7;
05580
05581
05582
05583
05584
05585
while (
TRUE) {
05586
05587 PVOID Segment;
05588 ULONG SegmentSize;
05589
05590 ExAcquireSpinLockAtDpcLevel( &
CcBcbSpinLock );
05591 Bcb =
ExAllocateFromZone( &
LazyWriter.
BcbZone );
05592 ExReleaseSpinLockFromDpcLevel( &
CcBcbSpinLock );
05593
05594
if (Bcb !=
NULL) {
05595 NodeIsInZone = 1;
05596
break;
05597 }
05598
05599
05600
05601
05602
05603
if (
MmQuerySystemSize() ==
MmLargeSystem ) {
05604
05605 SegmentSize =
PAGE_SIZE;
05606
05607
if ((Segment =
ExAllocatePoolWithTag(
NonPagedPool, SegmentSize, 'zBcC')) ==
NULL) {
05608
return NULL;
05609 }
05610
05611 ExAcquireSpinLockAtDpcLevel( &
CcBcbSpinLock );
05612
if (!
NT_SUCCESS(
ExExtendZone( &
LazyWriter.
BcbZone, Segment, SegmentSize ))) {
05613
CcBugCheck( 0, 0, 0 );
05614 }
05615 ExReleaseSpinLockFromDpcLevel( &
CcBcbSpinLock );
05616 }
else {
05617
if ((Bcb =
ExAllocatePoolWithTag(
NonPagedPool,
sizeof(
BCB), 'cBcC')) ==
NULL) {
05618
return NULL;
05619 }
05620 NodeIsInZone = 0;
05621
break;
05622 }
05623 }
05624
05625
05626
05627
05628
05629
05630 RtlZeroMemory( Bcb, RoundedBcbSize );
05631
05632 Bcb->
NodeIsInZone = NodeIsInZone;
05633
05634
05635
05636
05637
05638
05639
if (SharedCacheMap !=
NULL) {
05640
05641 Bcb->
NodeTypeCode =
CACHE_NTC_BCB;
05642 Bcb->
FileOffset = *FileOffset;
05643 Bcb->
ByteLength = TrialLength->LowPart;
05644 Bcb->
BeyondLastByte.QuadPart = FileOffset->QuadPart + TrialLength->QuadPart;
05645 Bcb->
PinCount += 1;
05646
ExInitializeResource( &Bcb->
Resource );
05647 Bcb->
SharedCacheMap = SharedCacheMap;
05648
05649
05650
05651
05652
05653
05654
05655
CcAcquireVacbLockAtDpcLevel();
05656 InsertTailList( &AfterBcb->BcbLinks, &Bcb->
BcbLinks );
05657
05658
ASSERT( (SharedCacheMap->SectionSize.QuadPart <
VACB_SIZE_OF_FIRST_LEVEL) ||
05659 (
CcFindBcb(SharedCacheMap, FileOffset, &Bcb->
BeyondLastByte, &AfterBcb) &&
05660 (Bcb == AfterBcb)) );
05661
05662
05663
05664
05665
05666
CcLockVacbLevel( SharedCacheMap, FileOffset->QuadPart );
05667
CcReleaseVacbLockFromDpcLevel();
05668
05669
05670
05671
05672
05673
05674
05675
if (SharedCacheMap &&
05676
FlagOn(SharedCacheMap->Flags,
DISABLE_WRITE_BEHIND)) {
05677
#if DBG
05678
SetFlag(Bcb->
Resource.
Flag,
ResourceNeverExclusive);
05679
#endif
05680
ExDisableResourceBoost( &Bcb->
Resource );
05681 }
05682 }
05683
05684
return Bcb;
05685 }
05686
05687
05688
05689
05690
05691
05692
VOID
05693
FASTCALL
05694 CcDeallocateBcb (
05695 IN
PBCB Bcb
05696 )
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706
05707
05708
05709
05710
05711
05712
05713
05714
05715 {
05716 KIRQL OldIrql;
05717
05718
05719
05720
05721
05722
if (Bcb->NodeTypeCode ==
CACHE_NTC_BCB) {
05723
05724
ExDeleteResource( &Bcb->Resource );
05725 }
05726
05727
if ( Bcb->NodeIsInZone ) {
05728
05729
05730
05731
05732
05733 ExAcquireSpinLock( &
CcBcbSpinLock, &OldIrql );
05734
ExFreeToZone( &
LazyWriter.
BcbZone, Bcb );
05735 ExReleaseSpinLock( &
CcBcbSpinLock, OldIrql );
05736
05737 }
else {
05738
ExFreePool(Bcb);
05739 }
05740
return;
05741 }
05742
05743
05744
05745
05746
05747
05748 BOOLEAN
05749 CcMapAndRead(
05750 IN
PSHARED_CACHE_MAP SharedCacheMap,
05751 IN PLARGE_INTEGER FileOffset,
05752 IN ULONG Length,
05753 IN ULONG ZeroFlags,
05754 IN BOOLEAN Wait,
05755 IN PVOID BaseAddress
05756 )
05757
05758
05759
05760
05761
05762
05763
05764
05765
05766
05767
05768
05769
05770
05771
05772
05773
05774
05775
05776
05777
05778
05779
05780
05781
05782
05783
05784
05785
05786
05787
05788
05789
05790
05791
05792
05793
05794
05795
05796
05797 {
05798 ULONG ZeroCase;
05799 ULONG SavedState;
05800 BOOLEAN Result =
FALSE;
05801
PETHREAD Thread =
PsGetCurrentThread();
05802
05803
MmSavePageFaultReadAhead( Thread, &SavedState );
05804
05805
05806
05807
05808
05809
try {
05810
05811 ULONG PagesToGo;
05812
05813
05814
05815
05816
05817
05818
05819 PagesToGo =
COMPUTE_PAGES_SPANNED( BaseAddress, Length );
05820
05821
05822
05823
05824
05825 ZeroCase =
ZERO_FIRST_PAGE;
05826
05827
while (PagesToGo) {
05828
05829
05830
05831
05832
05833
05834
MmSetPageFaultReadAhead( Thread, (PagesToGo - 1) );
05835
05836
if (!
FlagOn(ZeroFlags, ZeroCase) ||
05837 !
MmCheckCachedPageState(BaseAddress,
TRUE)) {
05838
05839
05840
05841
05842
05843
05844
05845
05846
05847
if (!
MmCheckCachedPageState(BaseAddress,
FALSE) && !Wait) {
05848
try_return( Result =
FALSE );
05849 }
05850 }
05851
05852 BaseAddress = (PCHAR)BaseAddress +
PAGE_SIZE;
05853 PagesToGo -= 1;
05854
05855
if (PagesToGo == 1) {
05856 ZeroCase =
ZERO_LAST_PAGE;
05857 }
else {
05858 ZeroCase =
ZERO_MIDDLE_PAGES;
05859 }
05860 }
05861
05862
try_return( Result =
TRUE );
05863
05864 try_exit: NOTHING;
05865 }
05866
05867
05868
05869
05870
05871 finally {
05872
05873
MmResetPageFaultReadAhead(Thread, SavedState);
05874 }
05875
05876
return Result;
05877 }
05878
05879
05880
05881
05882
05883
05884
VOID
05885 CcFreeActiveVacb (
05886 IN
PSHARED_CACHE_MAP SharedCacheMap,
05887 IN
PVACB ActiveVacb OPTIONAL,
05888 IN ULONG ActivePage,
05889 IN ULONG PageIsDirty
05890 )
05891
05892
05893
05894
05895
05896
05897
05898
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910
05911
05912
05913
05914
05915
05916
05917
05918
05919 {
05920 LARGE_INTEGER ActiveOffset;
05921 PVOID ActiveAddress;
05922 ULONG BytesLeftInPage;
05923 KIRQL OldIrql;
05924
05925
05926
05927
05928
05929
if (SharedCacheMap->NeedToZero !=
NULL) {
05930
05931
PVACB NeedToZeroVacb;
05932
05933
05934
05935
05936
05937
05938
05939
05940
05941 ExAcquireFastLock( &SharedCacheMap->ActiveVacbSpinLock, &OldIrql );
05942
05943
05944
05945
05946
05947 ActiveAddress = SharedCacheMap->NeedToZero;
05948
if (ActiveAddress !=
NULL) {
05949
05950 BytesLeftInPage =
PAGE_SIZE - ((((ULONG)((ULONG_PTR)ActiveAddress) - 1) & (
PAGE_SIZE - 1)) + 1);
05951
05952 RtlZeroBytes( ActiveAddress, BytesLeftInPage );
05953 SharedCacheMap->NeedToZero =
NULL;
05954 NeedToZeroVacb = SharedCacheMap->NeedToZeroVacb;
05955 }
05956 ExReleaseFastLock( &SharedCacheMap->ActiveVacbSpinLock, OldIrql );
05957
05958
05959
05960
05961
05962
05963
05964
if (ActiveAddress !=
NULL) {
05965
MmUnlockCachedPage( (PVOID)((PCHAR)ActiveAddress - 1) );
05966
CcFreeVirtualAddress( NeedToZeroVacb );
05967 }
05968 }
05969
05970
05971
05972
05973
05974
if (ActiveVacb !=
NULL) {
05975
05976
05977
05978
05979
05980
if (PageIsDirty) {
05981
05982 ActiveOffset.QuadPart = (LONGLONG)ActivePage <<
PAGE_SHIFT;
05983 ActiveAddress = (PVOID)((PCHAR)ActiveVacb->BaseAddress +
05984 (ActiveOffset.LowPart & (
VACB_MAPPING_GRANULARITY - 1)));
05985
05986
05987
05988
05989
05990
CcSetDirtyInMask( SharedCacheMap, &ActiveOffset,
PAGE_SIZE );
05991
05992
05993
05994
05995
05996
05997
CcAcquireMasterLock( &OldIrql );
05998 ExAcquireSpinLockAtDpcLevel( &SharedCacheMap->ActiveVacbSpinLock );
05999
if ((SharedCacheMap->ActiveVacb ==
NULL) &&
06000
FlagOn(SharedCacheMap->Flags,
ACTIVE_PAGE_IS_DIRTY)) {
06001
06002
ClearFlag(SharedCacheMap->Flags,
ACTIVE_PAGE_IS_DIRTY);
06003 SharedCacheMap->DirtyPages -= 1;
06004
CcTotalDirtyPages -= 1;
06005 }
06006 ExReleaseSpinLockFromDpcLevel( &SharedCacheMap->ActiveVacbSpinLock );
06007
CcReleaseMasterLock( OldIrql );
06008 }
06009
06010
06011
06012
06013
06014
CcFreeVirtualAddress( ActiveVacb );
06015 }
06016 }
06017
06018
06019
06020
06021
06022
06023
VOID
06024 CcMapAndCopy(
06025 IN
PSHARED_CACHE_MAP SharedCacheMap,
06026 IN PVOID UserBuffer,
06027 IN PLARGE_INTEGER FileOffset,
06028 IN ULONG Length,
06029 IN ULONG ZeroFlags,
06030 IN BOOLEAN WriteThrough
06031 )
06032
06033
06034
06035
06036
06037
06038
06039
06040
06041
06042
06043
06044
06045
06046
06047
06048
06049
06050
06051
06052
06053
06054
06055
06056
06057
06058
06059
06060
06061
06062 {
06063 ULONG ReceivedLength;
06064 ULONG ZeroCase;
06065 PVOID CacheBuffer;
06066 PVOID SavedMappedBuffer;
06067 ULONG SavedMappedLength;
06068 ULONG ActivePage;
06069 KIRQL OldIrql;
06070 LARGE_INTEGER PFileOffset;
06071 IO_STATUS_BLOCK IoStatus;
06072
NTSTATUS Status;
06073 ULONG SavedState;
06074 BOOLEAN MorePages;
06075 ULONG SavedTotalLength = Length;
06076 LARGE_INTEGER LocalOffset = *FileOffset;
06077 ULONG PageOffset = FileOffset->LowPart & (
PAGE_SIZE - 1);
06078
PVACB Vacb =
NULL;
06079
PETHREAD Thread =
PsGetCurrentThread();
06080
06081
06082
06083
06084
06085
06086 BOOLEAN SavePage =
TRUE;
06087
06088
DebugTrace(+1,
me,
"CcMapAndCopy:\n", 0 );
06089
DebugTrace( 0,
me,
" SharedCacheMap = %08lx\n", SharedCacheMap );
06090
DebugTrace2(0,
me,
" FileOffset = %08lx, %08lx\n", FileOffset->LowPart,
06091 FileOffset->HighPart );
06092
DebugTrace( 0,
me,
" Length = %08lx\n", Length );
06093
06094
MmSavePageFaultReadAhead( Thread, &SavedState );
06095
06096
06097
06098
06099
06100
try {
06101
06102
while (Length != 0) {
06103
06104 CacheBuffer =
CcGetVirtualAddress( SharedCacheMap,
06105 LocalOffset,
06106 &Vacb,
06107 &ReceivedLength );
06108
06109
06110
06111
06112
06113
06114
if (ReceivedLength > Length) {
06115 ReceivedLength = Length;
06116 }
06117 SavedMappedBuffer = CacheBuffer;
06118 SavedMappedLength = ReceivedLength;
06119 Length -= ReceivedLength;
06120
06121
06122
06123
06124
06125
06126
06127 CacheBuffer = (PVOID)((PCHAR)CacheBuffer - PageOffset);
06128 ReceivedLength += PageOffset;
06129
06130
06131
06132
06133
06134 ZeroCase =
ZERO_FIRST_PAGE;
06135
06136
06137
06138
06139
06140 PFileOffset = LocalOffset;
06141 PFileOffset.LowPart -= PageOffset;
06142
06143
while (
TRUE) {
06144
06145
06146
06147
06148
06149
06150 SavePage = ((Length == 0) &&
06151 (ReceivedLength <
PAGE_SIZE) &&
06152 (SavedTotalLength <= (
PAGE_SIZE / 2)) &&
06153 !WriteThrough);
06154
06155 MorePages = (ReceivedLength >
PAGE_SIZE);
06156
06157
06158
06159
06160
06161
try {
06162
06163
06164
06165
06166
06167
06168
if (SharedCacheMap->NeedToZero !=
NULL) {
06169
CcFreeActiveVacb( SharedCacheMap,
NULL, 0, 0 );
06170 }
06171
06172
Status = STATUS_SUCCESS;
06173
if (
FlagOn(ZeroFlags, ZeroCase)) {
06174
06175
Status =
MmCopyToCachedPage( CacheBuffer,
06176 UserBuffer,
06177 PageOffset,
06178 MorePages ?
06179 (
PAGE_SIZE - PageOffset) :
06180 (ReceivedLength - PageOffset),
06181 SavePage );
06182
06183
if (!
NT_SUCCESS(
Status)) {
06184
06185
ExRaiseStatus(
FsRtlNormalizeNtstatus(
Status,
06186 STATUS_INVALID_USER_BUFFER ));
06187 }
06188
06189
06190
06191
06192
06193 }
else {
06194
06195
MmSetPageFaultReadAhead( Thread,
06196 (MorePages &&
FlagOn(ZeroFlags,
ZERO_LAST_PAGE)) ? 1 : 0);
06197
06198 RtlCopyBytes( (PVOID)((PCHAR)CacheBuffer + PageOffset),
06199 UserBuffer,
06200 MorePages ?
06201 (
PAGE_SIZE - PageOffset) :
06202 (ReceivedLength - PageOffset) );
06203
06204
MmResetPageFaultReadAhead( Thread, SavedState );
06205
06206 }
06207
06208 } except(
CcCopyReadExceptionFilter( GetExceptionInformation(),
06209 &
Status ) ) {
06210
06211
06212
06213
06214
06215
06216
06217
if (
Status == STATUS_ACCESS_VIOLATION) {
06218
ExRaiseStatus( STATUS_INVALID_USER_BUFFER );
06219 }
06220
else {
06221
ExRaiseStatus(
FsRtlNormalizeNtstatus(
Status,
06222 STATUS_UNEXPECTED_IO_ERROR ));
06223 }
06224 }
06225
06226
06227
06228
06229
06230
06231
if (SavePage) {
06232
06233 ActivePage = (ULONG)( Vacb->
Overlay.FileOffset.QuadPart >>
PAGE_SHIFT ) +
06234 (ULONG)(((PCHAR)CacheBuffer - (PCHAR)Vacb->
BaseAddress) >>
06235
PAGE_SHIFT);
06236
06237 PFileOffset.LowPart += ReceivedLength;
06238
06239
06240
06241
06242
06243
06244
if (
Status == STATUS_CACHE_PAGE_LOCKED) {
06245
06246
06247
06248
06249
06250
06251
06252
CcAcquireVacbLock( &OldIrql );
06253 Vacb->
Overlay.ActiveCount += 1;
06254
06255 ExAcquireSpinLockAtDpcLevel( &SharedCacheMap->ActiveVacbSpinLock );
06256
06257
ASSERT(SharedCacheMap->NeedToZero ==
NULL);
06258
06259 SharedCacheMap->NeedToZero = (PVOID)((PCHAR)CacheBuffer +
06260 (PFileOffset.LowPart & (
PAGE_SIZE - 1)));
06261 SharedCacheMap->NeedToZeroPage = ActivePage;
06262 SharedCacheMap->NeedToZeroVacb = Vacb;
06263
06264 ExReleaseSpinLockFromDpcLevel( &SharedCacheMap->ActiveVacbSpinLock );
06265
CcReleaseVacbLock( OldIrql );
06266
06267 }
06268
06269
SetActiveVacb( SharedCacheMap,
06270 OldIrql,
06271 Vacb,
06272 ActivePage,
06273
ACTIVE_PAGE_IS_DIRTY );
06274
06275
try_return( NOTHING );
06276 }
06277
06278
06279
06280
06281
06282
06283
06284
06285
06286
if ((SavedTotalLength <= (
PAGE_SIZE / 2)) && !WriteThrough) {
06287
06288
CcSetDirtyInMask( SharedCacheMap, &PFileOffset, ReceivedLength );
06289 }
06290
06291 UserBuffer = (PVOID)((PCHAR)UserBuffer + (
PAGE_SIZE - PageOffset));
06292 PageOffset = 0;
06293
06294
06295
06296
06297
06298
06299
06300
if (MorePages) {
06301
06302 CacheBuffer = (PCHAR)CacheBuffer +
PAGE_SIZE;
06303 ReceivedLength -=
PAGE_SIZE;
06304
06305
06306
06307
06308
06309
06310
06311
06312 PFileOffset.LowPart +=
PAGE_SIZE;
06313
06314
if (ReceivedLength >
PAGE_SIZE) {
06315 ZeroCase =
ZERO_MIDDLE_PAGES;
06316 }
else {
06317 ZeroCase =
ZERO_LAST_PAGE;
06318 }
06319
06320 }
else {
06321
06322
break;
06323 }
06324 }
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334
06335
if (Length >
CcMaxDirtyWrite) {
06336
06337
MmSetAddressRangeModified( SavedMappedBuffer, SavedMappedLength );
06338
MmFlushSection( SharedCacheMap->FileObject->SectionObjectPointer,
06339 &LocalOffset,
06340 SavedMappedLength,
06341 &IoStatus,
06342
TRUE );
06343
06344
if (!
NT_SUCCESS(IoStatus.Status)) {
06345
ExRaiseStatus(
FsRtlNormalizeNtstatus( IoStatus.Status,
06346 STATUS_UNEXPECTED_IO_ERROR ));
06347 }
06348
06349
06350
06351
06352
06353
06354
06355 }
else if (WriteThrough) {
06356
06357
MmSetAddressRangeModified( SavedMappedBuffer, SavedMappedLength );
06358
06359
06360
06361
06362
06363
06364 }
else {
06365
06366
CcSetDirtyInMask( SharedCacheMap, &LocalOffset, SavedMappedLength );
06367 }
06368
06369
CcFreeVirtualAddress( Vacb );
06370 Vacb =
NULL;
06371
06372
06373
06374
06375
06376
06377
06378
06379
if (Length >=
PAGE_SIZE) {
06380 ZeroFlags |=
ZERO_FIRST_PAGE;
06381 }
else if ((ZeroFlags &
ZERO_LAST_PAGE) == 0) {
06382 ZeroFlags = 0;
06383 }
06384
06385
06386
06387
06388
06389
06390
06391
06392 LocalOffset.QuadPart = LocalOffset.QuadPart + (LONGLONG)SavedMappedLength;
06393 }
06394 try_exit: NOTHING;
06395 }
06396
06397
06398
06399
06400
06401 finally {
06402
06403
MmResetPageFaultReadAhead( Thread, SavedState );
06404
06405
06406
06407
06408
06409
if (!SavePage || AbnormalTermination()) {
06410
06411
06412
06413
06414
06415
06416
if (Vacb !=
NULL) {
06417
06418
CcFreeVirtualAddress( Vacb );
06419 }
06420
06421
06422
06423
06424
06425
06426
if (WriteThrough) {
06427
06428
MmFlushSection ( SharedCacheMap->FileObject->SectionObjectPointer,
06429 FileOffset,
06430 SavedTotalLength,
06431 &IoStatus,
06432
TRUE );
06433
06434
if (!
NT_SUCCESS(IoStatus.Status)) {
06435
ExRaiseStatus(
FsRtlNormalizeNtstatus( IoStatus.Status,
06436 STATUS_UNEXPECTED_IO_ERROR ));
06437 }
06438
06439
06440
06441
06442
06443 LocalOffset.QuadPart = FileOffset->QuadPart + (LONGLONG)SavedTotalLength;
06444
if (LocalOffset.QuadPart > SharedCacheMap->ValidDataGoal.QuadPart) {
06445 SharedCacheMap->ValidDataGoal = LocalOffset;
06446 }
06447 }
06448 }
06449 }
06450
06451
DebugTrace(-1,
me,
"CcMapAndCopy -> %02lx\n", Result );
06452
06453
return;
06454 }
06455
06456
06457 BOOLEAN
06458 CcLogError(
06459 IN
PDEVICE_OBJECT Device,
06460 IN NTSTATUS Error,
06461 IN NTSTATUS DeviceError,
06462 IN PUNICODE_STRING FileName
06463 )
06464
06465
06466
06467
06468
06469
06470
06471
06472
06473
06474
06475
06476
06477
06478
06479
06480
06481
06482
06483
06484
06485
06486
06487
06488
06489
06490 {
06491 UCHAR ErrorPacketLength;
06492 PIO_ERROR_LOG_PACKET ErrorLogEntry =
NULL;
06493 BOOLEAN RetVal =
FALSE;
06494 PWCHAR
String;
06495 ULONG StringSpace;
06496
06497
ASSERT( KeGetCurrentIrql() <=
DISPATCH_LEVEL );
06498
06499 ErrorPacketLength =
sizeof(IO_ERROR_LOG_PACKET) +
sizeof(
NTSTATUS);
06500
if (
FileName) {
06501
if ((
FileName->Length +
sizeof(WCHAR) + ErrorPacketLength) >= ERROR_LOG_MAXIMUM_SIZE) {
06502 ErrorPacketLength = ERROR_LOG_MAXIMUM_SIZE - 1;
06503 }
else {
06504 ErrorPacketLength += (UCHAR)(
FileName->Length +
sizeof(WCHAR));
06505 }
06506 }
06507
06508
ASSERT( ErrorPacketLength < UCHAR_MAX );
06509
06510 ErrorLogEntry = (PIO_ERROR_LOG_PACKET)
06511
IoAllocateErrorLogEntry( Device,
06512 ErrorPacketLength );
06513
if (ErrorLogEntry) {
06514 ErrorLogEntry->ErrorCode =
Error;
06515 ErrorLogEntry->DumpDataSize =
sizeof(
NTSTATUS);
06516 ErrorLogEntry->DumpData[0] = DeviceError;
06517
06518
if (
FileName &&
FileName->Length) {
06519
06520
06521
06522
06523
06524
06525 StringSpace = ErrorPacketLength -
sizeof( IO_ERROR_LOG_PACKET ) -
sizeof( WCHAR );
06526
String = (PWCHAR) (ErrorLogEntry + 1);
06527 ErrorLogEntry->NumberOfStrings = 1;
06528 ErrorLogEntry->StringOffset =
sizeof( IO_ERROR_LOG_PACKET );
06529 RtlCopyMemory(
String,
06530
FileName->Buffer,
06531
min(
FileName->Length, StringSpace ) );
06532
06533
06534
06535
06536
06537
String +=
min( (
FileName->Length /
sizeof( WCHAR )), (StringSpace /
sizeof( WCHAR )) );
06538 *
String =
L'\0';
06539 }
06540
06541
IoWriteErrorLogEntry( ErrorLogEntry );
06542 RetVal =
TRUE;
06543 }
06544
06545
return RetVal;
06546 }
06547
06548
06549
06550
#ifdef CCDBG
06551
VOID
06552 CcDump (
06553 IN PVOID Ptr
06554 )
06555
06556 {
06557 PVOID Junk =
Ptr;
06558 }
06559
#endif
06560
06561