00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "lfsprocs.h"
00022
00023
00024
00025
00026
00027 #define Dbg (DEBUG_TRACE_CACHE_SUP)
00028
00029
00030
00031
00032
00033
00034
00035 USHORT LfsUsaSeqNumber;
00036
00037 BOOLEAN
00038
LfsIsRestartPageHeaderValid (
00039 IN LONGLONG FileOffset,
00040 IN
PLFS_RESTART_PAGE_HEADER PageHeader,
00041 OUT PBOOLEAN LogPacked
00042 );
00043
00044 BOOLEAN
00045
LfsIsRestartAreaValid (
00046 IN
PLFS_RESTART_PAGE_HEADER PageHeader,
00047 IN BOOLEAN LogPacked
00048 );
00049
00050 BOOLEAN
00051
LfsIsClientAreaValid (
00052 IN
PLFS_RESTART_PAGE_HEADER PageHeader,
00053 IN BOOLEAN LogPacked,
00054 IN BOOLEAN UsaError
00055 );
00056
00057
VOID
00058
LfsFindFirstIo (
00059 IN
PLFCB Lfcb,
00060 IN
PLBCB TargetLbcb,
00061 IN
PLBCB FirstLbcb,
00062 OUT
PLBCB *NextLbcb,
00063 OUT PLONGLONG FileOffset,
00064 OUT PBOOLEAN ContainsLastEntry,
00065 OUT PBOOLEAN LfsRestart,
00066 OUT PBOOLEAN UseTailCopy,
00067 OUT PULONG IoBlocks
00068 );
00069
00070
#ifdef ALLOC_PRAGMA
00071
#pragma alloc_text(PAGE, LfsCopyReadLogRecord)
00072
#pragma alloc_text(PAGE, LfsFindFirstIo)
00073
#pragma alloc_text(PAGE, LfsFlushLfcb)
00074
#pragma alloc_text(PAGE, LfsIsClientAreaValid)
00075
#pragma alloc_text(PAGE, LfsIsRestartAreaValid)
00076
#pragma alloc_text(PAGE, LfsIsRestartPageHeaderValid)
00077
#pragma alloc_text(PAGE, LfsPinOrMapData)
00078
#pragma alloc_text(PAGE, LfsPinOrMapLogRecordHeader)
00079
#pragma alloc_text(PAGE, LfsReadRestart)
00080
#endif
00081
00082
00083
NTSTATUS
00084 LfsPinOrMapData (
00085 IN
PLFCB Lfcb,
00086 IN LONGLONG FileOffset,
00087 IN ULONG Length,
00088 IN BOOLEAN PinData,
00089 IN BOOLEAN AllowErrors,
00090 IN BOOLEAN IgnoreUsaErrors,
00091 OUT PBOOLEAN UsaError,
00092 OUT PVOID *Buffer,
00093 OUT
PBCB *Bcb
00094 )
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 {
00131
volatile NTSTATUS Status;
00132 ULONG Signature;
00133 BOOLEAN Result =
FALSE;
00134
00135
Status = STATUS_SUCCESS;
00136
00137
PAGED_CODE();
00138
00139
DebugTrace( +1,
Dbg,
"LfsPinReadLogPage: Entered\n", 0 );
00140
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
00141
DebugTrace( 0,
Dbg,
"FileOffset (Low) -> %08lx\n", FileOffset.HighPart );
00142
DebugTrace( 0,
Dbg,
"FileOffset (High) -> %08lx\n", FileOffset.LowPart );
00143
DebugTrace( 0,
Dbg,
"Length -> %08lx\n", Length );
00144
DebugTrace( 0,
Dbg,
"PinData -> %04x\n", PinData );
00145
DebugTrace( 0,
Dbg,
"AllowErrors -> %08x\n", AllowErrors );
00146
DebugTrace( 0,
Dbg,
"IgnoreUsaErrors -> %04x\n", IgnoreUsaErrors );
00147
00148
00149
00150
00151
00152
try {
00153
00154
00155
00156
00157
00158
try {
00159
00160
00161
00162
00163
00164
if (PinData) {
00165
00166 Result =
CcPinRead( Lfcb->FileObject,
00167 (PLARGE_INTEGER)&FileOffset,
00168 Length,
00169
TRUE,
00170 Bcb,
00171
Buffer );
00172
00173 }
else {
00174
00175 Result =
CcMapData( Lfcb->FileObject,
00176 (PLARGE_INTEGER)&FileOffset,
00177 Length,
00178
TRUE,
00179 Bcb,
00180
Buffer );
00181 }
00182
00183
00184
00185
00186
00187
00188 Signature = *((PULONG) *
Buffer);
00189
00190 } except(
LfsExceptionFilter( GetExceptionInformation() )) {
00191
00192
Status = GetExceptionCode();
00193
if (Result) {
00194
CcUnpinData( *Bcb );
00195 *Bcb =
NULL;
00196 }
00197 }
00198
00199 *UsaError =
FALSE;
00200
00201
00202
00203
00204
00205
if (!
NT_SUCCESS(
Status )) {
00206
00207
if (!AllowErrors) {
00208
00209
DebugTrace( 0,
Dbg,
"Read on log page failed -> %08lx\n",
Status );
00210
ExRaiseStatus(
Status );
00211 }
00212
00213
00214
00215
00216
00217
00218 }
else if (Signature ==
LFS_SIGNATURE_BAD_USA_ULONG) {
00219
00220
00221
00222
00223
00224
if (!IgnoreUsaErrors) {
00225
00226
DebugTrace( 0,
Dbg,
"Usa error on log page\n", 0 );
00227
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
00228 }
00229
00230 *UsaError =
TRUE;
00231 }
00232
00233 } finally {
00234
00235
DebugUnwind(
LfsPinOrMapData );
00236
00237
DebugTrace( 0,
Dbg,
"Buffer -> %08lx\n", *
Buffer );
00238
DebugTrace( 0,
Dbg,
"Bcb -> %08lx\n", *Bcb );
00239
00240
DebugTrace( -1,
Dbg,
"LfsPinOrMapData: Exit -> %08lx\n",
Status );
00241 }
00242
00243
return Status;
00244 }
00245
00246
00247
VOID
00248 LfsPinOrMapLogRecordHeader (
00249 IN
PLFCB Lfcb,
00250 IN LSN Lsn,
00251 IN BOOLEAN PinData,
00252 IN BOOLEAN IgnoreUsaErrors,
00253 OUT PBOOLEAN UsaError,
00254 OUT
PLFS_RECORD_HEADER *RecordHeader,
00255 OUT
PBCB *Bcb
00256 )
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 {
00288
PLFS_RECORD_PAGE_HEADER LogPageHeader;
00289 LONGLONG LogPage;
00290 ULONG PageOffset;
00291
00292
PAGED_CODE();
00293
00294
DebugTrace( +1,
Dbg,
"LfsPinOrMapLogRecordHeader: Entered\n", 0 );
00295
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
00296
DebugTrace( 0,
Dbg,
"Lsn (Low) -> %08lx\n", Lsn.HighPart );
00297
DebugTrace( 0,
Dbg,
"Lsn (High) -> %08lx\n", Lsn.LowPart );
00298
DebugTrace( 0,
Dbg,
"PinData -> %04x\n", PinData );
00299
DebugTrace( 0,
Dbg,
"IgnoreUsaErrors -> %04x\n", IgnoreUsaErrors );
00300
00301
00302
00303
00304
00305
00306
LfsTruncateLsnToLogPage( Lfcb, Lsn, &LogPage );
00307 PageOffset =
LfsLsnToPageOffset( Lfcb, Lsn );
00308
00309
00310
00311
00312
00313
LfsPinOrMapData( Lfcb,
00314 LogPage,
00315 (ULONG)Lfcb->LogPageSize,
00316 PinData,
00317
FALSE,
00318 IgnoreUsaErrors,
00319 UsaError,
00320 (PVOID *) &LogPageHeader,
00321 Bcb );
00322
00323
00324
00325
00326
00327 *RecordHeader =
Add2Ptr( LogPageHeader, PageOffset,
PLFS_RECORD_HEADER );
00328
00329
DebugTrace( 0,
Dbg,
"Record Header -> %08lx\n", *RecordHeader );
00330
DebugTrace( 0,
Dbg,
"Bcb -> %08lx\n", *Bcb );
00331
00332
DebugTrace( -1,
Dbg,
"LfsPinOrMapLogRecordHeader: Exit\n", 0 );
00333
00334
return;
00335 }
00336
00337
00338
VOID
00339 LfsCopyReadLogRecord (
00340 IN
PLFCB Lfcb,
00341 IN
PLFS_RECORD_HEADER RecordHeader,
00342 OUT PVOID Buffer
00343 )
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 {
00367
PBCB Bcb =
NULL;
00368 BOOLEAN UsaError;
00369
00370
PLFS_RECORD_PAGE_HEADER PageHeader;
00371
00372 LONGLONG LogPageFileOffset;
00373 ULONG LogPageOffset;
00374
00375 ULONG RemainingTransferBytes;
00376
00377
PAGED_CODE();
00378
00379
DebugTrace( +1,
Dbg,
"LfsCopyReadLogRecord: Entered\n", 0 );
00380
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
00381
DebugTrace( 0,
Dbg,
"RecordHeader -> %08lx\n", RecordHeader );
00382
DebugTrace( 0,
Dbg,
"Buffer -> %08lx\n",
Buffer );
00383
00384
00385
00386
00387
00388
00389
00390
00391
LfsTruncateLsnToLogPage( Lfcb, RecordHeader->ThisLsn, &LogPageFileOffset );
00392 LogPageOffset =
LfsLsnToPageOffset( Lfcb, RecordHeader->ThisLsn ) + Lfcb->RecordHeaderLength;
00393
00394 RemainingTransferBytes = RecordHeader->ClientDataLength;
00395
00396
00397
00398
00399
00400
try {
00401
00402
00403
00404
00405
00406
00407
while (
TRUE) {
00408
00409 ULONG RemainingPageBytes;
00410
00411 BOOLEAN Wrapped;
00412
00413 RemainingPageBytes = (ULONG)Lfcb->LogPageSize - LogPageOffset;
00414
00415
00416
00417
00418
00419
00420
if (RemainingTransferBytes <= RemainingPageBytes) {
00421
00422 RemainingPageBytes = RemainingTransferBytes;
00423 }
00424
00425 RemainingTransferBytes -= RemainingPageBytes;
00426
00427
00428
00429
00430
00431
if (Bcb !=
NULL) {
00432
00433
CcUnpinData( Bcb );
00434 Bcb =
NULL;
00435 }
00436
00437
LfsPinOrMapData( Lfcb,
00438 LogPageFileOffset,
00439 (ULONG)Lfcb->LogPageSize,
00440
FALSE,
00441
FALSE,
00442
TRUE,
00443 &UsaError,
00444 (PVOID *) &PageHeader,
00445 &Bcb );
00446
00447
00448
00449
00450
00451
00452
if ( PageHeader->Copy.LastLsn.QuadPart < RecordHeader->ThisLsn.QuadPart ) {
00453
00454
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
00455 }
00456
00457 RtlCopyMemory(
Buffer,
00458
Add2Ptr( PageHeader, LogPageOffset, PVOID ),
00459 RemainingPageBytes );
00460
00461
00462
00463
00464
00465
if (RemainingTransferBytes == 0) {
00466
00467
00468
00469
00470
00471
if (!
FlagOn( PageHeader->Flags,
LOG_PAGE_LOG_RECORD_END )
00472
00473 || (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG )
00474 && ( RecordHeader->ThisLsn.QuadPart > PageHeader->Header.Packed.LastEndLsn.QuadPart ))) {
00475
00476
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
00477 }
00478
00479
break;
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
if (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG )) {
00489
00490
00491
00492
00493
00494
if (( PageHeader->Copy.LastLsn.QuadPart == PageHeader->Header.Packed.LastEndLsn.QuadPart )
00495
00496 || ( RecordHeader->ThisLsn.QuadPart > PageHeader->Copy.LastLsn.QuadPart )) {
00497
00498
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
00499 }
00500
00501
00502
00503
00504
00505
00506 }
else if (
FlagOn( PageHeader->Flags,
LOG_PAGE_LOG_RECORD_END )) {
00507
00508
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
00509 }
00510
00511
00512
00513
00514
00515
00516
LfsNextLogPageOffset( Lfcb,
00517 LogPageFileOffset,
00518 &LogPageFileOffset,
00519 &Wrapped );
00520
00521 LogPageOffset = (ULONG)Lfcb->LogPageDataOffset;
00522
00523
00524
00525
00526
00527
00528
Buffer =
Add2Ptr(
Buffer, RemainingPageBytes, PVOID );
00529 }
00530
00531 } finally {
00532
00533
00534
00535
00536
00537
if (Bcb !=
NULL) {
00538
00539
CcUnpinData( Bcb );
00540 Bcb =
NULL;
00541 }
00542
00543
DebugTrace( -1,
Dbg,
"LfsCopyReadLogRecord: Exit\n", 0 );
00544 }
00545
00546
return;
00547 }
00548
00549
00550
VOID
00551 LfsFlushLfcb (
00552 IN
PLFCB Lfcb,
00553 IN
PLBCB Lbcb
00554 )
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 {
00577
PLBCB FirstLbcb;
00578
PLBCB ThisLbcb;
00579
PLBCB NextLbcb;
00580
00581
PLBCB TargetLbcb;
00582 PULONG Signature;
00583
00584 LONGLONG FileOffset;
00585 ULONG Length;
00586
00587 BOOLEAN RaiseCorrupt =
FALSE;
00588 BOOLEAN ValidLastLsn =
FALSE;
00589
00590 BOOLEAN ContainsLastEntry =
FALSE;
00591 BOOLEAN LfsRestart;
00592 BOOLEAN UseTailCopy;
00593
00594 ULONG IoBlocks;
00595 ULONG NewLfcbFlags = 0;
00596
00597
PBCB MapPageBcb =
NULL;
00598 PVOID MapPage;
00599
00600
LSN LastLsn;
00601
00602 IO_STATUS_BLOCK Iosb;
00603
00604
PBCB PageBcb =
NULL;
00605
00606
PAGED_CODE();
00607
00608
DebugTrace( +1,
Dbg,
"LfsFlushLfcb: Entered\n", 0 );
00609
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
00610
00611
00612
00613
00614
00615
try {
00616
00617
00618
00619
00620
00621
if (IsListEmpty( &Lfcb->LbcbWorkque )) {
00622
00623
try_return( NOTHING );
00624 }
00625
00626
00627
00628
00629
00630 Lfcb->LfsIoState =
LfsClientThreadIo;
00631
#ifdef BRIANDBG
00632
Lfcb->LfsIoThread =
ExGetCurrentResourceThread();
00633
#endif
00634
00635
00636
00637
00638
00639 FirstLbcb = CONTAINING_RECORD( Lfcb->LbcbWorkque.Flink,
00640
LBCB,
00641 WorkqueLinks );
00642
00643
00644
00645
00646
00647
while (!ContainsLastEntry) {
00648
00649
ASSERT( Lfcb->PageToDirty ==
NULL );
00650
00651
00652
00653
00654
00655
KeClearEvent( &Lfcb->Sync->Event );
00656
00657
00658
00659
00660
00661
00662
00663
LfsFindFirstIo( Lfcb,
00664 Lbcb,
00665 FirstLbcb,
00666 &NextLbcb,
00667 &FileOffset,
00668 &ContainsLastEntry,
00669 &LfsRestart,
00670 &UseTailCopy,
00671 &IoBlocks );
00672
00673 Length = IoBlocks * (ULONG) Lfcb->LogPageSize;
00674
if (UseTailCopy) {
00675
00676 TargetLbcb = Lfcb->ActiveTail;
00677 Lfcb->ActiveTail = Lfcb->PrevTail;
00678 Lfcb->PrevTail = TargetLbcb;
00679
00680 FileOffset = TargetLbcb->
FileOffset;
00681
00682 }
else {
00683
00684 TargetLbcb = FirstLbcb;
00685 }
00686
00687
00688
00689
00690
00691
if (!UseTailCopy) {
00692
00693
LfsReleaseLfcb( Lfcb );
00694 }
00695
00696
00697
00698
00699
00700
00701
if (LfsRestart) {
00702
00703
PLFS_RESTART_PAGE_HEADER RestartPage;
00704 BOOLEAN UsaError;
00705
NTSTATUS Status;
00706
00707
00708
00709
00710
00711
00712
if (
FlagOn( Lfcb->Flags,
LFCB_READ_FIRST_RESTART |
LFCB_READ_SECOND_RESTART ) &&
00713 ((FileOffset == 0) ?
00714
FlagOn( Lfcb->Flags,
LFCB_READ_FIRST_RESTART ) :
00715
FlagOn( Lfcb->Flags,
LFCB_READ_SECOND_RESTART ))) {
00716
00717
LfsPreparePinWriteData( Lfcb,
00718 FileOffset,
00719 (ULONG) Lfcb->SystemPageSize,
00720 &RestartPage,
00721 &PageBcb );
00722
00723
Status = STATUS_SUCCESS;
00724
00725
if (FileOffset == 0) {
00726
00727
SetFlag( NewLfcbFlags,
LFCB_READ_FIRST_RESTART );
00728
00729 }
else {
00730
00731
SetFlag( NewLfcbFlags,
LFCB_READ_SECOND_RESTART );
00732 }
00733
00734 }
else {
00735
00736
Status =
LfsPinOrMapData( Lfcb,
00737 FileOffset,
00738 (ULONG)Lfcb->SystemPageSize,
00739
TRUE,
00740
TRUE,
00741
TRUE,
00742 &UsaError,
00743 &RestartPage,
00744 &PageBcb );
00745 }
00746
00747
if (
NT_SUCCESS(
Status )) {
00748
00749
00750
00751
00752
00753 Signature = (PULONG) &RestartPage->
MultiSectorHeader.
Signature;
00754
00755 *Signature =
LFS_SIGNATURE_RESTART_PAGE_ULONG;
00756 RestartPage->
ChkDskLsn =
LfsLi0;
00757
00758 RestartPage->
MultiSectorHeader.
UpdateSequenceArrayOffset
00759 = Lfcb->RestartUsaOffset;
00760
00761 RestartPage->
MultiSectorHeader.
UpdateSequenceArraySize
00762 = Lfcb->RestartUsaArraySize;
00763
00764 RestartPage->
SystemPageSize = (ULONG)Lfcb->SystemPageSize;
00765 RestartPage->
LogPageSize = (ULONG)Lfcb->LogPageSize;
00766
00767 RestartPage->
RestartOffset = (
USHORT) Lfcb->RestartDataOffset;
00768 RestartPage->
MajorVersion = Lfcb->MajorVersion;
00769 RestartPage->
MinorVersion = Lfcb->MinorVersion;
00770
00771
00772
00773
00774
00775
00776
if (
FlagOn( Lfcb->Flags,
LFCB_LOG_WRAPPED )) {
00777
00778
ClearFlag( ((
PLFS_RESTART_AREA) FirstLbcb->
PageHeader)->Flags,
RESTART_SINGLE_PAGE_IO );
00779
SetFlag( Lfcb->Flags,
LFCB_MULTIPLE_PAGE_IO );
00780 }
00781
00782
00783
00784
00785
00786 RtlCopyMemory(
Add2Ptr( RestartPage, Lfcb->RestartDataOffset, PVOID ),
00787 FirstLbcb->
PageHeader,
00788 (ULONG)FirstLbcb->
Length );
00789
00790
00791
00792
00793
00794
00795
00796
CcSetDirtyPinnedData( PageBcb,
NULL );
00797
00798
00799
00800
00801
00802
CcUnpinData( PageBcb );
00803 PageBcb =
NULL;
00804
00805 LastLsn = FirstLbcb->
LastLsn;
00806 ValidLastLsn =
TRUE;
00807
00808
00809
00810
00811
00812 Length = (ULONG)Lfcb->SystemPageSize;
00813
00814 }
else {
00815
00816 RaiseCorrupt =
TRUE;
00817 }
00818
00819
00820
00821
00822
00823 }
else {
00824
00825
PLFS_RECORD_PAGE_HEADER RecordPageHeader;
00826
00827 ULONG
Count;
00828
00829
00830
00831
00832
00833
00834
00835
Count = 1;
00836
00837 ThisLbcb = FirstLbcb;
00838
00839
while (
TRUE) {
00840
00841
00842
00843
00844
00845
if (UseTailCopy) {
00846
00847 BOOLEAN UsaError;
00848
00849
if (!
NT_SUCCESS(
LfsPinOrMapData( Lfcb,
00850 TargetLbcb->
FileOffset,
00851 (ULONG)Lfcb->LogPageSize,
00852
TRUE,
00853
TRUE,
00854
TRUE,
00855 &UsaError,
00856 &RecordPageHeader,
00857 &PageBcb ))) {
00858
00859 RaiseCorrupt =
TRUE;
00860
break;
00861 }
00862
00863 }
else {
00864
00865
PUSHORT SeqNumber;
00866
00867 RecordPageHeader = (
PLFS_RECORD_PAGE_HEADER) ThisLbcb->
PageHeader;
00868
00869
00870
00871
00872
00873
00874
00875
00876 SeqNumber =
Add2Ptr( RecordPageHeader,
00877 Lfcb->LogRecordUsaOffset,
00878
PUSHORT );
00879
00880
if (*SeqNumber == 0) {
00881
00882 *SeqNumber =
LfsUsaSeqNumber;
00883
LfsUsaSeqNumber += 1;
00884 }
00885 }
00886
00887
00888
00889
00890
00891
00892
00893
if (UseTailCopy) {
00894
00895
00896
00897
00898
00899
00900 RtlCopyMemory( RecordPageHeader,
00901 ThisLbcb->
PageHeader,
00902 (ULONG)Lfcb->LogPageSize );
00903
00904 RecordPageHeader->
Copy.FileOffset = ThisLbcb->
FileOffset;
00905 }
00906
00907
00908
00909
00910
00911 RecordPageHeader->
PagePosition = (
USHORT)
Count;
00912 RecordPageHeader->
PageCount = (
USHORT) IoBlocks;
00913
00914
00915
00916
00917
00918 Signature = (PULONG) &RecordPageHeader->
MultiSectorHeader.
Signature;
00919 *Signature =
LFS_SIGNATURE_RECORD_PAGE_ULONG;
00920
00921 RecordPageHeader->
MultiSectorHeader.
UpdateSequenceArrayOffset
00922 = Lfcb->LogRecordUsaOffset;
00923
00924 RecordPageHeader->
MultiSectorHeader.
UpdateSequenceArraySize
00925 = Lfcb->LogRecordUsaArraySize;
00926
00927
00928
00929
00930
00931
00932
00933
if (UseTailCopy) {
00934
00935
CcSetDirtyPinnedData( PageBcb,
NULL );
00936
00937
CcUnpinData( PageBcb );
00938 PageBcb =
NULL;
00939
00940 }
else {
00941
00942
CcSetDirtyPinnedData( ThisLbcb->
LogPageBcb,
NULL );
00943
00944
00945
00946
00947
00948
CcUnpinDataForThread( ThisLbcb->
LogPageBcb, ThisLbcb->
ResourceThread );
00949 }
00950
00951
00952
00953
00954
00955
00956
if (
FlagOn( ThisLbcb->
Flags,
LOG_PAGE_LOG_RECORD_END )) {
00957
00958 LastLsn = ThisLbcb->
LastEndLsn;
00959 ValidLastLsn =
TRUE;
00960 }
00961
00962
00963
00964
00965
00966
if (
Count == IoBlocks) {
00967
00968
break;
00969 }
00970
00971
00972
00973
00974
00975 ThisLbcb = CONTAINING_RECORD( ThisLbcb->
WorkqueLinks.Flink,
00976
LBCB,
00977 WorkqueLinks );
00978
00979
Count += 1;
00980 }
00981 }
00982
00983
00984
00985
00986
00987
00988 Lfcb->UserWriteData->FileOffset = FileOffset;
00989 Lfcb->UserWriteData->Length = Length;
00990
00991
if (!UseTailCopy && !LfsRestart) {
00992
00993
PLBCB TailLbcb;
00994 PLIST_ENTRY Links;
00995 LONGLONG NextOffset;
00996
00997
00998
00999
01000
01001
01002
01003
if (
FlagOn( (ULONG)(FileOffset + Length), (
PAGE_SIZE - 1) )) {
01004
01005 NextOffset = FileOffset + Length;
01006
01007
LfsAcquireLfcb( Lfcb );
01008
01009
01010
01011
01012
01013 Links = Lfcb->LbcbActive.Flink;
01014
01015
while (Links != &Lfcb->LbcbActive) {
01016
01017 TailLbcb = CONTAINING_RECORD( Links,
01018
LBCB,
01019 ActiveLinks );
01020
01021
if (TailLbcb->
FileOffset == NextOffset) {
01022
01023 Lfcb->PageToDirty = TailLbcb;
01024
break;
01025 }
01026
01027 Links = Links->Flink;
01028 }
01029
01030
01031
01032
01033
01034
if (Lfcb->PageToDirty ==
NULL) {
01035
01036 Links = Lfcb->LbcbWorkque.Flink;
01037
01038
while (Links != &Lfcb->LbcbWorkque) {
01039
01040 TailLbcb = CONTAINING_RECORD( Links,
01041
LBCB,
01042 WorkqueLinks );
01043
01044
if (TailLbcb->
FileOffset == NextOffset) {
01045
01046 Lfcb->PageToDirty = TailLbcb;
01047
break;
01048 }
01049
01050 Links = Links->Flink;
01051 }
01052 }
01053
01054
01055
01056
01057
01058
01059
if (Lfcb->PageToDirty !=
NULL) {
01060
01061
01062
01063
01064
01065
01066
CcMapData( Lfcb->FileObject,
01067 (PLARGE_INTEGER) &Lfcb->PageToDirty->FileOffset,
01068 (ULONG) Lfcb->LogPageSize,
01069
TRUE,
01070 &MapPageBcb,
01071 &MapPage );
01072
01073
CcUnpinDataForThread( Lfcb->PageToDirty->LogPageBcb,
01074 Lfcb->PageToDirty->ResourceThread );
01075
01076 Lfcb->PageToDirty->LogPageBcb =
NULL;
01077 }
01078
01079
LfsReleaseLfcb( Lfcb );
01080 }
01081 }
01082
01083
01084
01085
01086
01087
CcFlushCache( Lfcb->FileObject->SectionObjectPointer,
01088 (PLARGE_INTEGER)&FileOffset,
01089 Length,
01090 &Iosb );
01091
01092
01093
01094
01095
01096
if (Lfcb->PageToDirty !=
NULL) {
01097
01098
LfsPreparePinWriteData( Lfcb,
01099 Lfcb->PageToDirty->FileOffset,
01100 (ULONG) Lfcb->LogPageSize,
01101 &Lfcb->PageToDirty->PageHeader,
01102 &Lfcb->PageToDirty->LogPageBcb );
01103
01104 Lfcb->PageToDirty->ResourceThread =
ExGetCurrentResourceThread();
01105 Lfcb->PageToDirty =
NULL;
01106
01107
CcUnpinData( MapPageBcb );
01108 MapPageBcb =
NULL;
01109 }
01110
01111
if (!
NT_SUCCESS( Iosb.Status )) {
01112
01113 LONG BytesRemaining = (LONG) Length;
01114
01115
01116
01117
01118
01119
while (BytesRemaining > 0) {
01120
01121
01122
01123
01124
01125
01126 Lfcb->UserWriteData->FileOffset = FileOffset;
01127 Lfcb->UserWriteData->Length = Length;
01128
01129
if (!UseTailCopy && !LfsRestart) {
01130
01131
PLBCB TailLbcb;
01132 PLIST_ENTRY Links;
01133 LONGLONG NextOffset;
01134
01135
01136
01137
01138
01139
01140
01141
if (
FlagOn( (ULONG)(FileOffset + Length), (
PAGE_SIZE - 1) )) {
01142
01143 NextOffset = FileOffset + Length;
01144
01145
LfsAcquireLfcb( Lfcb );
01146
01147
01148
01149
01150
01151 Links = Lfcb->LbcbActive.Flink;
01152
01153
while (Links != &Lfcb->LbcbActive) {
01154
01155 TailLbcb = CONTAINING_RECORD( Links,
01156
LBCB,
01157 ActiveLinks );
01158
01159
if (TailLbcb->
FileOffset == NextOffset) {
01160
01161 Lfcb->PageToDirty = TailLbcb;
01162
break;
01163 }
01164
01165 Links = Links->Flink;
01166 }
01167
01168
01169
01170
01171
01172
if (Lfcb->PageToDirty ==
NULL) {
01173
01174 Links = Lfcb->LbcbWorkque.Flink;
01175
01176
while (Links != &Lfcb->LbcbWorkque) {
01177
01178 TailLbcb = CONTAINING_RECORD( Links,
01179
LBCB,
01180 WorkqueLinks );
01181
01182
if (TailLbcb->
FileOffset == NextOffset) {
01183
01184 Lfcb->PageToDirty = TailLbcb;
01185
break;
01186 }
01187
01188 Links = Links->Flink;
01189 }
01190 }
01191
01192
01193
01194
01195
01196
01197
if (Lfcb->PageToDirty !=
NULL) {
01198
01199
CcMapData( Lfcb->FileObject,
01200 (PLARGE_INTEGER) &Lfcb->PageToDirty->FileOffset,
01201 (ULONG) Lfcb->PageToDirty->Length,
01202
TRUE,
01203 &MapPageBcb,
01204 &MapPage );
01205
01206
CcUnpinDataForThread( Lfcb->PageToDirty->LogPageBcb,
01207 Lfcb->PageToDirty->ResourceThread );
01208
01209 Lfcb->PageToDirty->LogPageBcb =
NULL;
01210 }
01211 }
01212
LfsReleaseLfcb( Lfcb );
01213 }
01214
01215
CcFlushCache( Lfcb->FileObject->SectionObjectPointer,
01216 (PLARGE_INTEGER)&FileOffset,
01217 (ULONG)Lfcb->SystemPageSize,
01218 &Iosb );
01219
01220
01221
01222
01223
01224
if (Lfcb->PageToDirty !=
NULL) {
01225
01226
LfsPreparePinWriteData( Lfcb,
01227 Lfcb->PageToDirty->FileOffset,
01228 (ULONG) Lfcb->PageToDirty->Length,
01229 &Lfcb->PageToDirty->PageHeader,
01230 &Lfcb->PageToDirty->LogPageBcb );
01231
01232 Lfcb->PageToDirty->ResourceThread =
ExGetCurrentResourceThread();
01233 Lfcb->PageToDirty =
NULL;
01234
01235
CcUnpinData( MapPageBcb );
01236 MapPageBcb =
NULL;
01237 }
01238
01239
if (!
NT_SUCCESS( Iosb.Status )) {
01240
01241
#ifdef NTFS_RESTART
01242
ASSERT(
FALSE );
01243
#endif
01244
RaiseCorrupt =
TRUE;
01245 }
01246
01247 BytesRemaining -= (LONG)Lfcb->SystemPageSize;
01248 FileOffset = FileOffset + Lfcb->SystemPageSize;
01249 }
01250 }
01251
01252
01253
01254
01255
01256
if (!UseTailCopy) {
01257
01258
LfsAcquireLfcb( Lfcb );
01259 }
01260
01261
01262
01263
01264
01265
01266
if (!LfsRestart) {
01267
01268
if (ValidLastLsn) {
01269
01270 Lfcb->LastFlushedLsn = LastLsn;
01271 }
01272
01273
01274
01275
01276
01277 }
else {
01278
01279 Lfcb->LastFlushedRestartLsn = LastLsn;
01280
01281
01282
01283
01284
01285
if (!RaiseCorrupt) {
01286
01287
ClearFlag( Lfcb->Flags, NewLfcbFlags );
01288 NewLfcbFlags = 0;
01289 }
01290
01291
01292
01293
01294
01295
01296
if (
NT_SUCCESS( Iosb.Status ) &&
01297 (Lfcb->CurrentOpenLogCount != ((
PLFS_RESTART_AREA) FirstLbcb->
PageHeader)->RestartOpenLogCount)) {
01298
01299 Lfcb->CurrentOpenLogCount = ((
PLFS_RESTART_AREA) FirstLbcb->
PageHeader)->RestartOpenLogCount;
01300 }
01301 }
01302
01303
01304
01305
01306
01307
if (!UseTailCopy) {
01308
01309
PLBCB TempLbcb;
01310
01311 ThisLbcb = FirstLbcb;
01312
01313
while (
TRUE) {
01314
01315
01316
01317
01318
01319 TempLbcb = CONTAINING_RECORD( ThisLbcb->
WorkqueLinks.Flink,
01320
LBCB,
01321 WorkqueLinks );
01322
01323
01324
01325
01326
01327 RemoveEntryList( &ThisLbcb->
WorkqueLinks );
01328
01329
01330
01331
01332
01333
LfsDeallocateLbcb( Lfcb, ThisLbcb );
01334
01335
if (IoBlocks-- == 1) {
01336
01337
break;
01338 }
01339
01340 ThisLbcb = TempLbcb;
01341 }
01342 }
01343
01344
01345
01346
01347
01348
01349
KeSetEvent( &Lfcb->Sync->Event, 0,
FALSE );
01350
01351
01352
01353
01354
01355 FirstLbcb = NextLbcb;
01356 }
01357
01358 try_exit: NOTHING;
01359 } finally {
01360
01361
DebugUnwind(
LfsFlushLfcb );
01362
01363
ASSERT( Lfcb->PageToDirty ==
NULL );
01364
01365
01366
01367
01368
01369 Lfcb->LfsIoState =
LfsNoIoInProgress;
01370
#ifdef BRIANDBG
01371
Lfcb->LfsIoThread = 0;
01372
#endif
01373
01374
01375
01376
01377
01378
if (PageBcb !=
NULL) {
01379
01380
CcUnpinData( PageBcb );
01381 }
01382
01383
DebugTrace( -1,
Dbg,
"LfsFlushLfcb: Exit\n", 0 );
01384 }
01385
01386
01387
01388
01389
01390
01391
01392
if (RaiseCorrupt && (!
FlagOn( Lfcb->Flags,
LFCB_FINAL_SHUTDOWN ))) {
01393
01394
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
01395 }
01396
01397
return;
01398 }
01399
01400
01401 BOOLEAN
01402 LfsReadRestart (
01403 IN
PLFCB Lfcb,
01404 IN LONGLONG FileSize,
01405 IN BOOLEAN FirstRestart,
01406 OUT PLONGLONG RestartPageOffset,
01407 OUT
PLFS_RESTART_PAGE_HEADER *RestartPage,
01408 OUT
PBCB *RestartPageBcb,
01409 OUT PBOOLEAN ChkdskWasRun,
01410 OUT PBOOLEAN ValidPage,
01411 OUT PBOOLEAN UninitializedFile,
01412 OUT PBOOLEAN LogPacked,
01413 OUT
PLSN LastLsn
01414 )
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461 {
01462 ULONG FileOffsetIncrement;
01463 LONGLONG FileOffset;
01464
01465
PLFS_RESTART_AREA RestartArea;
01466
01467
NTSTATUS Status;
01468
01469
PLFS_RESTART_PAGE_HEADER ThisPage;
01470
PBCB ThisPageBcb =
NULL;
01471
01472 BOOLEAN FoundRestart =
FALSE;
01473
01474
PAGED_CODE();
01475
01476
DebugTrace( +1,
Dbg,
"LfsReadRestart: Entered\n", 0 );
01477
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
01478
01479
01480
01481
01482
01483 *UninitializedFile =
TRUE;
01484 *ValidPage =
FALSE;
01485 *ChkdskWasRun =
FALSE;
01486 *LogPacked =
FALSE;
01487
01488
try {
01489
01490
01491
01492
01493
01494
if (FirstRestart) {
01495
01496 FileOffset = 0;
01497 FileOffsetIncrement =
SEQUENCE_NUMBER_STRIDE;
01498
01499 }
else {
01500
01501 FileOffset =
SEQUENCE_NUMBER_STRIDE;
01502 FileOffsetIncrement = 0;
01503 }
01504
01505
01506
01507
01508
01509
01510
while ( FileOffset < FileSize ) {
01511
01512 ULONG Signature;
01513 BOOLEAN UsaError;
01514
01515
if (ThisPageBcb !=
NULL) {
01516
01517
CcUnpinData( ThisPageBcb );
01518 ThisPageBcb =
NULL;
01519 }
01520
01521
01522
01523
01524
01525
Status =
LfsPinOrMapData( Lfcb,
01526 FileOffset,
01527
SEQUENCE_NUMBER_STRIDE,
01528
TRUE,
01529
TRUE,
01530
TRUE,
01531 &UsaError,
01532 (PVOID *)&ThisPage,
01533 &ThisPageBcb );
01534
01535
01536
01537
01538
01539
01540
if (
NT_SUCCESS(
Status )) {
01541
01542 Signature = *((PULONG) &ThisPage->MultiSectorHeader.Signature);
01543
01544
01545
01546
01547
01548
if (Signature ==
LFS_SIGNATURE_RECORD_PAGE_ULONG) {
01549
01550 *UninitializedFile =
FALSE;
01551
break;
01552 }
01553
01554
01555
01556
01557
01558
01559
if (Signature ==
LFS_SIGNATURE_MODIFIED_ULONG
01560 || Signature ==
LFS_SIGNATURE_RESTART_PAGE_ULONG) {
01561
01562 *UninitializedFile =
FALSE;
01563
01564
01565
01566
01567
01568 *RestartPageOffset = FileOffset;
01569
01570
01571
01572
01573
01574
if (
LfsIsRestartPageHeaderValid( FileOffset,
01575 ThisPage,
01576 LogPacked )
01577
01578 &&
LfsIsRestartAreaValid( ThisPage, *LogPacked )) {
01579
01580
01581
01582
01583
01584
01585
01586 RestartArea =
Add2Ptr( ThisPage,
01587 ThisPage->RestartOffset,
01588
PLFS_RESTART_AREA );
01589
01590
if (Signature ==
LFS_SIGNATURE_RESTART_PAGE_ULONG
01591 && RestartArea->
ClientInUseList !=
LFS_NO_CLIENT) {
01592
01593
01594
01595
01596
01597
CcUnpinData( ThisPageBcb );
01598 ThisPageBcb =
NULL;
01599
01600
Status =
LfsPinOrMapData( Lfcb,
01601 FileOffset,
01602 ThisPage->SystemPageSize,
01603
TRUE,
01604
TRUE,
01605
TRUE,
01606 &UsaError,
01607 (PVOID *)&ThisPage,
01608 &ThisPageBcb );
01609
01610
if (
NT_SUCCESS(
Status )
01611 &&
LfsIsClientAreaValid( ThisPage, *LogPacked, UsaError )) {
01612
01613 *ValidPage =
TRUE;
01614
01615 RestartArea =
Add2Ptr( ThisPage,
01616 ThisPage->RestartOffset,
01617
PLFS_RESTART_AREA );
01618 }
01619
01620 }
else {
01621
01622 *ValidPage =
TRUE;
01623 }
01624 }
01625
01626
01627
01628
01629
01630
if (Signature ==
LFS_SIGNATURE_MODIFIED_ULONG) {
01631
01632 *ChkdskWasRun =
TRUE;
01633
01634 *LastLsn = ThisPage->ChkDskLsn;
01635
01636 FoundRestart =
TRUE;
01637
01638 *RestartPageBcb = ThisPageBcb;
01639 *RestartPage = ThisPage;
01640
01641 ThisPageBcb =
NULL;
01642
break;
01643 }
01644
01645
01646
01647
01648
01649
if (*ValidPage) {
01650
01651 *LastLsn = RestartArea->
CurrentLsn;
01652
01653 FoundRestart =
TRUE;
01654
01655 *RestartPageBcb = ThisPageBcb;
01656 *RestartPage = ThisPage;
01657
01658 ThisPageBcb =
NULL;
01659
break;
01660 }
01661
01662
01663
01664
01665
01666 }
else if (Signature !=
LFS_SIGNATURE_UNINITIALIZED_ULONG) {
01667
01668 *UninitializedFile =
FALSE;
01669 }
01670 }
01671
01672
01673
01674
01675
01676 FileOffset = FileOffset << 1;
01677
01678 (ULONG)FileOffset += FileOffsetIncrement;
01679
01680 FileOffsetIncrement = 0;
01681 }
01682
01683 } finally {
01684
01685
DebugUnwind(
LfsReadRestart );
01686
01687
01688
01689
01690
01691
if (ThisPageBcb !=
NULL) {
01692
01693
CcUnpinData( ThisPageBcb );
01694 }
01695
01696
DebugTrace( 0,
Dbg,
"RestartPageAddress (Low) -> %08lx\n", RestartPageAddress->LowPart );
01697
DebugTrace( 0,
Dbg,
"RestartPageAddress (High) -> %08lx\n", RestartPageAddress->HighPart );
01698
DebugTrace( 0,
Dbg,
"FirstRestartPage -> %08lx\n", *FirstRestartPage );
01699
DebugTrace( -1,
Dbg,
"LfsReadRestart: Exit\n", 0 );
01700 }
01701
01702
return FoundRestart;
01703 }
01704
01705
01706
01707
01708
01709
01710 BOOLEAN
01711 LfsIsRestartPageHeaderValid (
01712 IN LONGLONG FileOffset,
01713 IN
PLFS_RESTART_PAGE_HEADER PageHeader,
01714 OUT PBOOLEAN LogPacked
01715 )
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742 {
01743 ULONG SystemPage;
01744 ULONG LogPageSize;
01745 ULONG Mask;
01746 ULONG BitCount;
01747
01748
USHORT EndOfUsa;
01749
01750
PAGED_CODE();
01751
01752 *LogPacked =
FALSE;
01753
01754
01755
01756
01757
01758 SystemPage = PageHeader->SystemPageSize;
01759 LogPageSize = PageHeader->LogPageSize;
01760
01761
01762
01763
01764
01765
01766
if (SystemPage <
SEQUENCE_NUMBER_STRIDE
01767 || LogPageSize <
SEQUENCE_NUMBER_STRIDE) {
01768
01769
return FALSE;
01770 }
01771
01772
01773
01774
01775
01776
01777
for (Mask = 1, BitCount = 0; Mask != 0; Mask = Mask << 1) {
01778
01779
if (Mask & LogPageSize) {
01780
01781 BitCount += 1;
01782 }
01783 }
01784
01785
01786
01787
01788
01789
if (BitCount != 1) {
01790
01791
return FALSE;
01792 }
01793
01794
01795
01796
01797
01798
for (Mask = 1, BitCount = 0; Mask != 0; Mask = Mask << 1) {
01799
01800
if (Mask & SystemPage) {
01801
01802 BitCount += 1;
01803 }
01804 }
01805
01806
01807
01808
01809
01810
if (BitCount != 1) {
01811
01812
return FALSE;
01813 }
01814
01815
01816
01817
01818
01819
if (( FileOffset != 0 )
01820 && ((ULONG)FileOffset != SystemPage)) {
01821
01822
return FALSE;
01823 }
01824
01825
01826
01827
01828
01829
01830
01831
if (PageHeader->MajorVersion != 0
01832 && PageHeader->MajorVersion != 1) {
01833
01834
return FALSE;
01835 }
01836
01837
01838
01839
01840
01841
01842
if (
QuadAlign( PageHeader->RestartOffset ) != PageHeader->RestartOffset
01843 || PageHeader->RestartOffset > (
USHORT) PageHeader->SystemPageSize) {
01844
01845
return FALSE;
01846 }
01847
01848
01849
01850
01851
01852 EndOfUsa = (
USHORT) (
UpdateSequenceArraySize( PageHeader->SystemPageSize )
01853 *
sizeof(
UPDATE_SEQUENCE_NUMBER ));
01854
01855 EndOfUsa += PageHeader->MultiSectorHeader.UpdateSequenceArrayOffset;
01856
01857
if (PageHeader->RestartOffset < EndOfUsa) {
01858
01859
return FALSE;
01860 }
01861
01862
01863
01864
01865
01866
if (PageHeader->MajorVersion == 1
01867 && PageHeader->MinorVersion > 0) {
01868
01869 *LogPacked =
TRUE;
01870 }
01871
01872
01873
01874
01875
01876
return TRUE;
01877 }
01878
01879
01880
01881
01882
01883
01884 BOOLEAN
01885 LfsIsRestartAreaValid (
01886 IN
PLFS_RESTART_PAGE_HEADER PageHeader,
01887 IN BOOLEAN LogPacked
01888 )
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912 {
01913
PLFS_RESTART_AREA RestartArea;
01914 ULONG OffsetInRestart;
01915 ULONG SeqNumberBits;
01916
01917 LONGLONG FileSize;
01918
01919
PAGED_CODE();
01920
01921
01922
01923
01924
01925
01926 OffsetInRestart = FIELD_OFFSET(
LFS_RESTART_AREA, FileSize );
01927
01928
if ((PageHeader->RestartOffset + OffsetInRestart) >
FIRST_STRIDE) {
01929
01930
return FALSE;
01931 }
01932
01933 RestartArea =
Add2Ptr( PageHeader, PageHeader->RestartOffset,
PLFS_RESTART_AREA );
01934
01935
01936
01937
01938
01939
01940
01941
if (LogPacked) {
01942
01943 OffsetInRestart = RestartArea->
ClientArrayOffset;
01944
01945 }
else {
01946
01947
01948
01949
01950
01951 OffsetInRestart = FIELD_OFFSET(
LFS_OLD_RESTART_AREA, LogClientArray );
01952 }
01953
01954
if (
QuadAlign( OffsetInRestart ) != OffsetInRestart
01955 || (PageHeader->RestartOffset + OffsetInRestart) >
FIRST_STRIDE) {
01956
01957
return FALSE;
01958 }
01959
01960
01961
01962
01963
01964
01965
01966
01967 OffsetInRestart += (RestartArea->
LogClients *
sizeof(
LFS_CLIENT_RECORD ));
01968
01969
if (OffsetInRestart > PageHeader->SystemPageSize ) {
01970
01971
return FALSE;
01972 }
01973
01974
01975
01976
01977
01978
01979
if (LogPacked
01980 && ((ULONG) (PageHeader->RestartOffset + RestartArea->
RestartAreaLength) > PageHeader->SystemPageSize
01981 || OffsetInRestart > RestartArea->
RestartAreaLength)) {
01982
01983
return FALSE;
01984 }
01985
01986
01987
01988
01989
01990
01991
if ((RestartArea->
ClientFreeList !=
LFS_NO_CLIENT
01992 && RestartArea->
ClientFreeList >= RestartArea->
LogClients)
01993
01994 || (RestartArea->
ClientInUseList !=
LFS_NO_CLIENT
01995 && RestartArea->
ClientInUseList >= RestartArea->
LogClients)) {
01996
01997
return FALSE;
01998 }
01999
02000
02001
02002
02003
02004 FileSize = RestartArea->
FileSize;
02005
02006
for (SeqNumberBits = 0;
02007 ( FileSize != 0 );
02008 SeqNumberBits += 1,
02009 FileSize = ((ULONGLONG)(FileSize)) >> 1 ) {
02010 }
02011
02012 SeqNumberBits = (
sizeof(
LSN ) * 8) + 3 - SeqNumberBits;
02013
02014
if (SeqNumberBits != RestartArea->
SeqNumberBits) {
02015
02016
return FALSE;
02017 }
02018
02019
02020
02021
02022
02023
if (LogPacked) {
02024
02025
02026
02027
02028
02029
02030
if ((
QuadAlign( RestartArea->
LogPageDataOffset ) != RestartArea->
LogPageDataOffset ) ||
02031 (
QuadAlign( RestartArea->
RecordHeaderLength ) != RestartArea->
RecordHeaderLength )) {
02032
02033
return FALSE;
02034 }
02035 }
02036
02037
return TRUE;
02038 }
02039
02040
02041
02042
02043
02044
02045 BOOLEAN
02046 LfsIsClientAreaValid (
02047 IN
PLFS_RESTART_PAGE_HEADER PageHeader,
02048 IN BOOLEAN LogPacked,
02049 IN BOOLEAN UsaError
02050 )
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075 {
02076
PLFS_RESTART_AREA RestartArea;
02077
USHORT ThisClientIndex;
02078
USHORT ClientCount;
02079
02080
PLFS_CLIENT_RECORD ClientArray;
02081
PLFS_CLIENT_RECORD ThisClient;
02082
02083 ULONG LoopCount;
02084
02085
PAGED_CODE();
02086
02087 RestartArea =
Add2Ptr( PageHeader, PageHeader->RestartOffset,
PLFS_RESTART_AREA );
02088
02089
02090
02091
02092
02093
02094
if (UsaError
02095 && (RestartArea->
RestartAreaLength + PageHeader->RestartOffset) >
FIRST_STRIDE) {
02096
02097
return FALSE;
02098 }
02099
02100
02101
02102
02103
02104
if (LogPacked) {
02105
02106 ClientArray =
Add2Ptr( RestartArea,
02107 RestartArea->
ClientArrayOffset,
02108
PLFS_CLIENT_RECORD );
02109
02110 }
else {
02111
02112
02113
02114
02115
02116 ClientArray =
Add2Ptr( RestartArea,
02117 FIELD_OFFSET(
LFS_OLD_RESTART_AREA,
02118 LogClientArray ),
02119
PLFS_CLIENT_RECORD );
02120 }
02121
02122
02123
02124
02125
02126
02127 ThisClientIndex = RestartArea->
ClientFreeList;
02128
02129 LoopCount = 2;
02130
02131
do {
02132
02133 BOOLEAN FirstClient;
02134
02135 FirstClient =
TRUE;
02136
02137 ClientCount = RestartArea->
LogClients;
02138
02139
while (ThisClientIndex !=
LFS_NO_CLIENT) {
02140
02141
02142
02143
02144
02145
02146
02147
if (ClientCount == 0
02148 || ThisClientIndex >= RestartArea->
LogClients) {
02149
02150
return FALSE;
02151 }
02152
02153 ClientCount -= 1;
02154
02155 ThisClient = ClientArray + ThisClientIndex;
02156 ThisClientIndex = ThisClient->
NextClient;
02157
02158
02159
02160
02161
02162
02163
if (FirstClient) {
02164
02165 FirstClient =
FALSE;
02166
02167
if (ThisClient->
PrevClient !=
LFS_NO_CLIENT) {
02168
02169
return FALSE;
02170 }
02171 }
02172 }
02173
02174 ThisClientIndex = RestartArea->
ClientInUseList;
02175
02176 }
while (--LoopCount);
02177
02178
02179
02180
02181
02182
return TRUE;
02183 }
02184
02185
02186
02187
02188
02189
02190
VOID
02191 LfsFindFirstIo (
02192 IN
PLFCB Lfcb,
02193 IN
PLBCB TargetLbcb,
02194 IN
PLBCB FirstLbcb,
02195 OUT
PLBCB *NextLbcb,
02196 OUT PLONGLONG FileOffset,
02197 OUT PBOOLEAN ContainsLastEntry,
02198 OUT PBOOLEAN LfsRestart,
02199 OUT PBOOLEAN UseTailCopy,
02200 OUT PULONG IoBlocks
02201 )
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248 {
02249
PAGED_CODE();
02250
02251
DebugTrace( +1,
Dbg,
"LfsFindFirstIo: Entered\n", 0 );
02252
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
02253
02254
02255
02256
02257
02258
02259
02260 *FileOffset = FirstLbcb->FileOffset;
02261 *IoBlocks = 1;
02262
02263 *LfsRestart =
FALSE;
02264 *UseTailCopy =
FALSE;
02265
02266 *NextLbcb =
NULL;
02267
02268
02269
02270
02271
02272
02273
if (FirstLbcb == TargetLbcb
02274 && !
FlagOn( TargetLbcb->LbcbFlags,
LBCB_FLUSH_COPY )) {
02275
02276 *ContainsLastEntry =
TRUE;
02277
02278 }
else {
02279
02280 *ContainsLastEntry =
FALSE;
02281 }
02282
02283
02284
02285
02286
02287
02288
02289
if (
LfsLbcbIsRestart( FirstLbcb )) {
02290
02291 *LfsRestart =
TRUE;
02292
02293 }
else if (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG )
02294 && (
FlagOn( FirstLbcb->LbcbFlags,
LBCB_FLUSH_COPY |
LBCB_ON_ACTIVE_QUEUE ))) {
02295
02296 *UseTailCopy =
TRUE;
02297
02298
02299
02300
02301
02302
02303
02304
if (
FlagOn( FirstLbcb->LbcbFlags,
LBCB_FLUSH_COPY )) {
02305
02306 *NextLbcb = FirstLbcb;
02307
ClearFlag( FirstLbcb->LbcbFlags,
LBCB_FLUSH_COPY );
02308 }
02309
02310 }
else if (
FlagOn( Lfcb->Flags,
LFCB_MULTIPLE_PAGE_IO )) {
02311
02312
PLBCB EndOfPageLbcb =
NULL;
02313 ULONG EndOfPageIoBlocks;
02314
02315
02316
02317
02318
02319
02320
02321
02322
while ((FirstLbcb->WorkqueLinks.Flink != &Lfcb->LbcbWorkque) &&
02323 !
FlagOn( FirstLbcb->LbcbFlags,
LBCB_ON_ACTIVE_QUEUE )) {
02324
02325 LONGLONG ExpectedFileOffset;
02326
PLBCB TempLbcb;
02327
02328
02329
02330
02331
02332 TempLbcb = CONTAINING_RECORD( FirstLbcb->WorkqueLinks.Flink,
02333
LBCB,
02334 WorkqueLinks );
02335
02336
02337
02338
02339
02340
02341 ExpectedFileOffset = FirstLbcb->FileOffset + Lfcb->LogPageSize;
02342
02343
02344
02345
02346
02347
02348
02349
02350
if ((TempLbcb->
FileOffset != ExpectedFileOffset) ||
02351 (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG ) &&
02352
FlagOn( TempLbcb->
LbcbFlags,
LBCB_FLUSH_COPY |
LBCB_ON_ACTIVE_QUEUE))) {
02353
02354
02355
02356
02357
02358
if (EndOfPageLbcb !=
NULL) {
02359
02360 FirstLbcb = EndOfPageLbcb;
02361 *IoBlocks = EndOfPageIoBlocks;
02362 }
02363
02364
break;
02365 }
02366
02367
02368
02369
02370
02371
02372
02373 *IoBlocks += 1;
02374
02375
if (TempLbcb == TargetLbcb ) {
02376
02377 *ContainsLastEntry =
TRUE;
02378 }
02379
02380
02381
02382
02383
02384
if (*ContainsLastEntry &&
02385 (
PAGE_SIZE != (ULONG) Lfcb->SystemPageSize) &&
02386 !
FlagOn( ((ULONG) TempLbcb->
FileOffset + (ULONG) Lfcb->LogPageSize),
02387
PAGE_SIZE - 1 )) {
02388
02389 EndOfPageLbcb = TempLbcb;
02390 EndOfPageIoBlocks = *IoBlocks;
02391 }
02392
02393
02394
02395
02396
02397 FirstLbcb = TempLbcb;
02398 }
02399 }
02400
02401
02402
02403
02404
02405
02406
02407
02408
if (!(*UseTailCopy) &&
FlagOn( FirstLbcb->LbcbFlags,
LBCB_ON_ACTIVE_QUEUE )) {
02409
02410
if (Lfcb->CurrentAvailable < Lfcb->TotalUndoCommitment) {
02411
02412
02413
02414
02415
02416 *IoBlocks -= 1;
02417 *NextLbcb = FirstLbcb;
02418
02419
02420
02421
02422
02423 }
else {
02424
02425
ClearFlag( FirstLbcb->LbcbFlags,
LBCB_ON_ACTIVE_QUEUE );
02426 RemoveEntryList( &FirstLbcb->ActiveLinks );
02427 }
02428 }
02429
02430
02431
02432
02433
02434
02435
if (*NextLbcb ==
NULL) {
02436
02437 *NextLbcb = CONTAINING_RECORD( FirstLbcb->WorkqueLinks.Flink,
02438
LBCB,
02439 WorkqueLinks );
02440 }
02441
02442
DebugTrace( 0,
Dbg,
"File Offset (Low) -> %08lx\n", FileOffset->LowPart );
02443
DebugTrace( 0,
Dbg,
"File Offset (High) -> %08lx\n", FileOffset->HighPart );
02444
DebugTrace( 0,
Dbg,
"Contains Last Entry -> %08x\n", *ContainsLastEntry );
02445
DebugTrace( 0,
Dbg,
"LfsRestart -> %08x\n", *LfsRestart );
02446
DebugTrace( 0,
Dbg,
"IoBlocks -> %08lx\n", *IoBlocks );
02447
DebugTrace( -1,
Dbg,
"LfsFindFirstIo: Exit\n", 0 );
02448
02449
return;
02450 }
02451