00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "lfsprocs.h"
00023
00024
00025
00026
00027
00028 #define Dbg (DEBUG_TRACE_REGISTRY)
00029
00030
PLFCB
00031
LfsRestartLogFile (
00032 IN
PFILE_OBJECT LogFile,
00033 IN USHORT MaximumClients,
00034 IN ULONG LogPageSize OPTIONAL,
00035 IN LONGLONG FileSize,
00036 IN OUT PLFS_INFO LfsInfo,
00037 OUT
PLFS_WRITE_DATA WriteData
00038 );
00039
00040
VOID
00041
LfsNormalizeBasicLogFile (
00042 IN OUT PLONGLONG FileSize,
00043 IN OUT PULONG LogPageSize,
00044 IN OUT PUSHORT LogClients,
00045 IN BOOLEAN UseDefaultLogPage
00046 );
00047
00048
VOID
00049
LfsUpdateLfcbFromPgHeader (
00050 IN
PLFCB Lfcb,
00051 IN ULONG SystemPageSize,
00052 IN ULONG LogPageSize,
00053 IN SHORT MajorVersion,
00054 IN SHORT MinorVersion,
00055 IN BOOLEAN PackLog
00056 );
00057
00058
VOID
00059
LfsUpdateLfcbFromNoRestart (
00060 IN
PLFCB Lfcb,
00061 IN LONGLONG FileSize,
00062 IN LSN LastLsn,
00063 IN ULONG LogClients,
00064 IN ULONG OpenLogCount,
00065 IN BOOLEAN LogFileWrapped,
00066 IN BOOLEAN UseMultiplePageIo
00067 );
00068
00069
VOID
00070
LfsUpdateLfcbFromRestart (
00071 IN
PLFCB Lfcb,
00072 IN
PLFS_RESTART_AREA RestartArea,
00073 IN USHORT RestartOffset
00074 );
00075
00076
VOID
00077
LfsUpdateRestartAreaFromLfcb (
00078 IN
PLFCB Lfcb,
00079 IN
PLFS_RESTART_AREA RestartArea
00080 );
00081
00082
VOID
00083
LfsInitializeLogFilePriv (
00084 IN
PLFCB Lfcb,
00085 IN BOOLEAN ForceRestartToDisk,
00086 IN ULONG RestartAreaSize,
00087 IN LONGLONG StartOffsetForClear,
00088 IN BOOLEAN ClearLogFile
00089 );
00090
00091
VOID
00092
LfsFindLastLsn (
00093 IN OUT
PLFCB Lfcb
00094 );
00095
00096 BOOLEAN
00097
LfsCheckSubsequentLogPage (
00098 IN
PLFCB Lfcb,
00099 IN
PLFS_RECORD_PAGE_HEADER RecordPageHeader,
00100 IN LONGLONG LogFileOffset,
00101 IN LONGLONG SequenceNumber
00102 );
00103
00104
VOID
00105
LfsFlushLogPage (
00106 IN
PLFCB Lfcb,
00107 PVOID LogPage,
00108 IN LONGLONG FileOffset,
00109 OUT
PBCB *Bcb
00110 );
00111
00112
VOID
00113
LfsRemoveClientFromList (
00114 IN
PLFS_CLIENT_RECORD ClientArray,
00115 IN
PLFS_CLIENT_RECORD ClientRecord,
00116 IN PUSHORT ListHead
00117 );
00118
00119
VOID
00120
LfsAddClientToList (
00121 IN
PLFS_CLIENT_RECORD ClientArray,
00122 IN USHORT ClientIndex,
00123 IN PUSHORT ListHead
00124 );
00125
00126
#ifdef ALLOC_PRAGMA
00127
#pragma alloc_text(PAGE, LfsAddClientToList)
00128
#pragma alloc_text(PAGE, LfsCheckSubsequentLogPage)
00129
#pragma alloc_text(PAGE, LfsCloseLogFile)
00130
#pragma alloc_text(PAGE, LfsDeleteLogHandle)
00131
#pragma alloc_text(PAGE, LfsFindLastLsn)
00132
#pragma alloc_text(PAGE, LfsFlushLogPage)
00133
#pragma alloc_text(PAGE, LfsInitializeLogFile)
00134
#pragma alloc_text(PAGE, LfsInitializeLogFilePriv)
00135
#pragma alloc_text(PAGE, LfsNormalizeBasicLogFile)
00136
#pragma alloc_text(PAGE, LfsOpenLogFile)
00137
#pragma alloc_text(PAGE, LfsReadLogFileInformation)
00138
#pragma alloc_text(PAGE, LfsRemoveClientFromList)
00139
#pragma alloc_text(PAGE, LfsResetUndoTotal)
00140
#pragma alloc_text(PAGE, LfsRestartLogFile)
00141
#pragma alloc_text(PAGE, LfsUpdateLfcbFromRestart)
00142
#pragma alloc_text(PAGE, LfsUpdateLfcbFromNoRestart)
00143
#pragma alloc_text(PAGE, LfsUpdateLfcbFromPgHeader)
00144
#pragma alloc_text(PAGE, LfsUpdateRestartAreaFromLfcb)
00145
#pragma alloc_text(PAGE, LfsVerifyLogFile)
00146
#endif
00147
00148
00149
VOID
00150 LfsInitializeLogFile (
00151 IN
PFILE_OBJECT LogFile,
00152 IN USHORT MaximumClients,
00153 IN ULONG LogPageSize OPTIONAL,
00154 IN LONGLONG FileSize,
00155 OUT
PLFS_WRITE_DATA WriteData
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
PLFCB Lfcb;
00192 LARGE_INTEGER CurrentTime;
00193
00194
PLFS_RESTART_AREA RestartArea =
NULL;
00195
00196
volatile NTSTATUS Status = STATUS_SUCCESS;
00197
00198
PAGED_CODE();
00199
00200
DebugTrace( +1,
Dbg,
"LfsInitializeLogFile: Entered\n", 0 );
00201
DebugTrace( 0,
Dbg,
"Log File -> %08lx\n", LogFile );
00202
DebugTrace( 0,
Dbg,
"Maximum Clients -> %04x\n", MaximumClients );
00203
DebugTrace( 0,
Dbg,
"Log Page Size -> %08lx\n", LogPageSize );
00204
DebugTrace( 0,
Dbg,
"File Size (Low) -> %08lx\n", FileSize.LowPart );
00205
DebugTrace( 0,
Dbg,
"File Size (High) -> %08lx\n", FileSize.HighPart );
00206
00207 Lfcb =
NULL;
00208
00209
00210
00211
00212
00213
try {
00214
00215
00216
00217
00218
00219
LfsAcquireLfsData();
00220
00221
00222
00223
00224
00225
try {
00226
00227
00228
00229
00230
00231 Lfcb =
LfsAllocateLfcb();
00232
00233
LfsAcquireLfcb( Lfcb );
00234
00235 Lfcb->
FileObject = LogFile;
00236
00237
00238
00239
00240
00241
00242
CcSetAdditionalCacheAttributes( LogFile,
TRUE,
TRUE );
00243
00244
00245
00246
00247
00248
LfsNormalizeBasicLogFile( &FileSize,
00249 &LogPageSize,
00250 &MaximumClients,
00251 (BOOLEAN) ((
PAGE_SIZE >=
LFS_DEFAULT_LOG_PAGE_SIZE) &&
00252 (
PAGE_SIZE <=
LFS_DEFAULT_LOG_PAGE_SIZE * 2)));
00253
00254
00255
00256
00257
00258
00259
LfsUpdateLfcbFromPgHeader( Lfcb,
00260 LogPageSize,
00261 LogPageSize,
00262 1,
00263 1,
00264
TRUE );
00265
00266
KeQuerySystemTime( &CurrentTime );
00267
00268
LfsUpdateLfcbFromNoRestart( Lfcb,
00269 FileSize,
00270
LfsLi0,
00271 MaximumClients,
00272 CurrentTime.LowPart,
00273
FALSE,
00274
FALSE );
00275
00276
LfsAllocateRestartArea( &RestartArea, Lfcb->
RestartDataSize );
00277
00278
LfsUpdateRestartAreaFromLfcb( Lfcb, RestartArea );
00279
00280 Lfcb->
RestartArea = RestartArea;
00281 Lfcb->
ClientArray =
Add2Ptr( RestartArea, Lfcb->
ClientArrayOffset,
PLFS_CLIENT_RECORD );
00282 RestartArea =
NULL;
00283
00284 Lfcb->
InitialRestartArea =
TRUE;
00285
00286
00287
00288
00289
00290 Lfcb->
UserWriteData = WriteData;
00291 WriteData->
LfsStructureSize = LogPageSize;
00292 WriteData->Lfcb = Lfcb;
00293
00294
00295
00296
00297
00298
LfsInitializeLogFilePriv( Lfcb,
00299
TRUE,
00300 Lfcb->
RestartDataSize,
00301 Lfcb->
FirstLogPage,
00302
TRUE );
00303
00304
00305
00306
00307
00308 InsertHeadList( &
LfsData.
LfcbLinks, &Lfcb->
LfcbLinks );
00309
00310 } finally {
00311
00312
DebugUnwind(
LfsInitializeLogFile );
00313
00314
00315
00316
00317
00318
if (Lfcb !=
NULL) {
00319
00320
LfsReleaseLfcb( Lfcb );
00321
00322
00323
00324
00325
00326
00327
if (AbnormalTermination()) {
00328
00329
LfsDeallocateLfcb( Lfcb,
TRUE );
00330 }
00331 }
00332
00333
00334
00335
00336
00337
if (RestartArea !=
NULL) {
00338
00339
LfsDeallocateRestartArea( RestartArea );
00340 }
00341
00342
00343
00344
00345
00346
LfsReleaseLfsData();
00347
00348
DebugTrace( -1,
Dbg,
"LfsInitializeLogFile: Exit\n", 0 );
00349 }
00350
00351 } except (
LfsExceptionFilter( GetExceptionInformation() )) {
00352
00353
Status = GetExceptionCode();
00354 }
00355
00356
if (
Status != STATUS_SUCCESS) {
00357
00358
ExRaiseStatus(
Status );
00359 }
00360
00361
return;
00362 }
00363
00364
00365 ULONG
00366 LfsOpenLogFile (
00367 IN
PFILE_OBJECT LogFile,
00368 IN UNICODE_STRING ClientName,
00369 IN USHORT MaximumClients,
00370 IN ULONG LogPageSize OPTIONAL,
00371 IN LONGLONG FileSize,
00372 IN OUT PLFS_INFO LfsInfo,
00373 OUT PLFS_LOG_HANDLE LogHandle,
00374 OUT
PLFS_WRITE_DATA WriteData
00375 )
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 {
00424
volatile NTSTATUS Status = STATUS_SUCCESS;
00425
00426 PLIST_ENTRY Link;
00427
PLFCB ThisLfcb =
NULL;
00428
PLFCB NewLfcb =
NULL;
00429
00430
USHORT ThisClient;
00431
PLFS_CLIENT_RECORD ClientRecord;
00432
00433
PLCH Lch =
NULL;
00434
00435 ULONG ReservedHeader;
00436
00437
PAGED_CODE();
00438
00439
DebugTrace( +1,
Dbg,
"LfsOpenLogFile: Entered\n", 0 );
00440
DebugTrace( 0,
Dbg,
"Log File -> %08lx\n", LogFile );
00441
DebugTrace( 0,
Dbg,
"Client Name -> %08lx\n", &ClientName );
00442
DebugTrace( 0,
Dbg,
"Maximum Clients -> %04x\n", MaximumClients );
00443
DebugTrace( 0,
Dbg,
"Log Page Size -> %08lx\n", LogPageSize );
00444
DebugTrace( 0,
Dbg,
"File Size (Low) -> %08lx\n", FileSize.LowPart );
00445
DebugTrace( 0,
Dbg,
"File Size (High) -> %08lx\n", FileSize.HighPart );
00446
00447
00448
00449
00450
00451
if (ClientName.Length >
LFS_CLIENT_NAME_MAX) {
00452
00453
DebugTrace( 0,
Dbg,
"Illegal name length for client\n", 0 );
00454
DebugTrace( -1,
Dbg,
"LfsOpenLogFile: Exit\n", 0 );
00455
ExRaiseStatus( STATUS_INVALID_PARAMETER );
00456 }
00457
00458
00459
00460
00461
00462
try {
00463
00464
00465
00466
00467
00468
LfsAcquireLfsData();
00469
00470
00471
00472
00473
00474
try {
00475
00476
00477
00478
00479
00480 Link =
LfsData.
LfcbLinks.Flink;
00481
00482
while (Link != &
LfsData.
LfcbLinks) {
00483
00484 ThisLfcb = CONTAINING_RECORD( Link,
LFCB, LfcbLinks );
00485
00486
if (ThisLfcb->
FileObject == LogFile) {
00487
00488
DebugTrace( 0,
Dbg,
"Found matching log file\n", 0 );
00489
break;
00490 }
00491
00492 Link = Link->Flink;
00493 }
00494
00495
00496
00497
00498
00499
00500
if (Link == &
LfsData.
LfcbLinks) {
00501
00502
00503
00504
00505
00506
00507
CcSetAdditionalCacheAttributes( LogFile,
TRUE,
TRUE );
00508
00509
00510
00511
00512
00513 ThisLfcb = NewLfcb =
LfsRestartLogFile( LogFile,
00514 MaximumClients,
00515 0,
00516 FileSize,
00517 LfsInfo,
00518 WriteData );
00519
00520
00521
00522
00523
00524 InsertHeadList( &
LfsData.
LfcbLinks, &ThisLfcb->
LfcbLinks );
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
if (
FlagOn( ThisLfcb->
Flags,
LFCB_LOG_FILE_CORRUPT )) {
00534
00535
00536
00537
00538
00539
00540
DebugTrace( 0,
Dbg,
"The Lfcb is corrupt\n", 0 );
00541
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
00542 }
00543
00544
00545
00546
00547
00548 ThisClient = ThisLfcb->
RestartArea->
ClientInUseList;
00549
00550
while (ThisClient !=
LFS_NO_CLIENT) {
00551
00552 ClientRecord = ThisLfcb->
ClientArray + ThisClient;
00553
00554
if (ClientRecord->
ClientNameLength == (ULONG) ClientName.Length
00555 && RtlCompareMemory( ClientRecord->
ClientName,
00556 ClientName.Buffer,
00557 ClientName.Length ) == (ULONG) ClientName.Length) {
00558
00559
DebugTrace( 0,
Dbg,
"Matching client name found\n", 0 );
00560
break;
00561 }
00562
00563 ThisClient = ClientRecord->
NextClient;
00564 }
00565
00566
00567
00568
00569
00570
LfsAllocateLch( &Lch );
00571 InsertTailList( &ThisLfcb->
LchLinks, &Lch->
LchLinks );
00572
00573
00574
00575
00576
00577 Lch->
Lfcb = ThisLfcb;
00578 Lch->
Sync = ThisLfcb->
Sync;
00579 Lch->
Sync->
UserCount += 1;
00580
00581
00582
00583
00584
00585
00586
if (ThisClient ==
LFS_NO_CLIENT) {
00587
00588
00589
00590
00591
00592 ThisClient = ThisLfcb->
RestartArea->
ClientFreeList;
00593
00594
if (ThisClient ==
LFS_NO_CLIENT) {
00595
00596
DebugTrace( 0,
Dbg,
"No free client records available\n", 0 );
00597
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
00598 }
00599
00600
00601
00602
00603
00604 ClientRecord = ThisLfcb->
ClientArray + ThisClient;
00605
00606
LfsRemoveClientFromList( ThisLfcb->
ClientArray,
00607 ClientRecord,
00608 &ThisLfcb->
RestartArea->
ClientFreeList );
00609
00610 ClientRecord->
ClientRestartLsn =
LfsZeroLsn;
00611 ClientRecord->
OldestLsn = ThisLfcb->
OldestLsn;
00612 ClientRecord->
ClientNameLength = ClientName.Length;
00613 RtlCopyMemory( ClientRecord->
ClientName,
00614 ClientName.Buffer,
00615 ClientName.Length );
00616
00617
00618
00619
00620
00621
LfsAddClientToList( ThisLfcb->
ClientArray,
00622 ThisClient,
00623 &ThisLfcb->
RestartArea->
ClientInUseList );
00624 }
00625
00626
00627
00628
00629
00630 Lch->
ClientId.
SeqNumber = ClientRecord->
SeqNumber;
00631 Lch->
ClientId.
ClientIndex = ThisClient;
00632
00633 Lch->
ClientArrayByteOffset =
PtrOffset( ThisLfcb->
ClientArray,
00634 ClientRecord );
00635
00636 *LogHandle = (
LFS_LOG_HANDLE) Lch;
00637
00638 } finally {
00639
00640
DebugUnwind(
LfsOpenLogFile );
00641
00642
00643
00644
00645
00646
if (ThisLfcb !=
NULL) {
00647
00648
00649
00650
00651
00652
00653
00654 ReservedHeader = ThisLfcb->
RecordHeaderLength;
00655
if (
FlagOn( ThisLfcb->
Flags,
LFCB_PACK_LOG )) {
00656
00657 ReservedHeader *= 2;
00658 }
00659
00660
LfsReleaseLfcb( ThisLfcb );
00661 }
00662
00663
00664
00665
00666
00667
if (AbnormalTermination()) {
00668
00669
if (Lch !=
NULL) {
00670
00671
LfsDeallocateLch( Lch );
00672 ThisLfcb->
Sync->
UserCount -= 1;
00673 }
00674
00675
if (NewLfcb !=
NULL) {
00676
00677
LfsDeallocateLfcb( NewLfcb,
TRUE );
00678 }
00679 }
00680
00681
00682
00683
00684
00685
LfsReleaseLfsData();
00686
00687
DebugTrace( 0,
Dbg,
"Log Handle -> %08ln\n", *LogHandle );
00688
DebugTrace( -1,
Dbg,
"LfsOpenLogFile: Exit\n", 0 );
00689 }
00690
00691 } except (
LfsExceptionFilter( GetExceptionInformation() )) {
00692
00693
Status = GetExceptionCode();
00694 }
00695
00696
if (
Status != STATUS_SUCCESS) {
00697
00698
ExRaiseStatus(
Status );
00699 }
00700
00701
return ReservedHeader;
00702 }
00703
00704
00705
VOID
00706 LfsCloseLogFile (
00707 IN LFS_LOG_HANDLE LogHandle
00708 )
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 {
00730
volatile NTSTATUS Status = STATUS_SUCCESS;
00731
00732
PLCH Lch;
00733
00734
PLFCB Lfcb;
00735
00736
USHORT ClientIndex;
00737
PLFS_CLIENT_RECORD ClientRecord;
00738
00739 BOOLEAN FlushRestart;
00740 BOOLEAN ExitLoop;
00741
00742
PAGED_CODE();
00743
00744
DebugTrace( +1,
Dbg,
"LfsCloseLogFile: Entered\n", 0 );
00745
DebugTrace( 0,
Dbg,
"LogHandle -> %08lx\n", LogHandle );
00746
00747 Lch = (
PLCH) LogHandle;
00748
00749
00750
00751
00752
00753
00754
while (
TRUE) {
00755
00756
00757
00758
00759
00760 ExitLoop =
TRUE;
00761
00762
00763
00764
00765
00766
LfsValidateLch( Lch );
00767
00768
00769
00770
00771
00772
try {
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
LfsAcquireLfsData();
00783
00784
try {
00785
00786
PLBCB ThisLbcb;
00787
00788
LfsAcquireLch( Lch );
00789
00790 Lfcb = Lch->
Lfcb;
00791
00792
00793
00794
00795
00796
if (Lfcb ==
NULL) {
00797
00798
try_return( NOTHING );
00799 }
00800
00801
00802
00803
00804
00805
if ((Lfcb->
Waiters != 0) ||
00806 (Lfcb->
LfsIoState !=
LfsNoIoInProgress)) {
00807
00808 ExitLoop =
FALSE;
00809 Lfcb->
Waiters += 1;
00810
try_return( NOTHING );
00811 }
00812
00813
00814
00815
00816
00817
LfsValidateClientId( Lfcb, Lch );
00818
00819 ClientRecord =
Add2Ptr( Lfcb->
ClientArray,
00820 Lch->
ClientArrayByteOffset,
00821
PLFS_CLIENT_RECORD );
00822
00823
#if 1
00824
00825
00826
00827
00828
00829 ClientIndex = Lch->
ClientId.
ClientIndex;
00830
00831 ClientRecord->
SeqNumber++;
00832
#endif
00833
00834
00835
00836
00837
00838 FlushRestart = (BOOLEAN) (
LfsZeroLsn.QuadPart != ClientRecord->
ClientRestartLsn.QuadPart );
00839
00840
#if 1
00841
00842
00843
00844
00845
LfsRemoveClientFromList( Lfcb->
ClientArray,
00846 ClientRecord,
00847 &Lfcb->
RestartArea->
ClientInUseList );
00848
00849
00850
00851
00852
00853
LfsAddClientToList( Lfcb->
ClientArray,
00854 ClientIndex,
00855 &Lfcb->
RestartArea->
ClientFreeList );
00856
00857
00858
00859
00860
00861
00862
if (Lfcb->
RestartArea->
ClientInUseList ==
LFS_NO_CLIENT) {
00863
#endif
00864
00865
00866
00867
00868
SetFlag( Lfcb->
Flags,
LFCB_FINAL_SHUTDOWN );
00869
00870
00871
00872
00873
00874
00875
while (!IsListEmpty( &Lfcb->
LbcbActive )) {
00876
00877 ThisLbcb = CONTAINING_RECORD( Lfcb->
LbcbActive.Flink,
00878
LBCB,
00879 ActiveLinks );
00880
00881 RemoveEntryList( &ThisLbcb->
ActiveLinks );
00882
ClearFlag( ThisLbcb->
LbcbFlags,
LBCB_ON_ACTIVE_QUEUE );
00883
00884
00885
00886
00887
00888
00889
if (!
FlagOn( ThisLbcb->
LbcbFlags,
LBCB_NOT_EMPTY )) {
00890
00891 RemoveEntryList( &ThisLbcb->
WorkqueLinks );
00892
00893
if (ThisLbcb->
LogPageBcb !=
NULL) {
00894
00895
CcUnpinDataForThread( ThisLbcb->
LogPageBcb,
00896 ThisLbcb->
ResourceThread );
00897 }
00898
00899
LfsDeallocateLbcb( Lfcb, ThisLbcb );
00900 }
00901 }
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
if ((Lfcb->
LfsIoState ==
LfsNoIoInProgress) && !FlushRestart) {
00913
00914 PLIST_ENTRY Links;
00915
00916
00917
00918
00919
00920
00921 Links = Lfcb->
LbcbWorkque.Flink;
00922
00923
while (Links != &Lfcb->
LbcbWorkque) {
00924
00925 ThisLbcb = CONTAINING_RECORD( Links,
00926
LBCB,
00927 WorkqueLinks );
00928
00929
00930
00931
00932
00933
00934
if (!
LfsLbcbIsRestart( ThisLbcb )) {
00935
00936 FlushRestart =
TRUE;
00937
break;
00938 }
00939
00940 Links = Links->Flink;
00941 }
00942
00943
00944
00945
00946
00947
00948
if (!FlushRestart) {
00949
00950
while (!IsListEmpty( &Lfcb->
LbcbWorkque)) {
00951
00952 ThisLbcb = CONTAINING_RECORD( Lfcb->
LbcbWorkque.Blink,
00953
LBCB,
00954 WorkqueLinks );
00955
00956 RemoveEntryList( &ThisLbcb->
WorkqueLinks );
00957
LfsDeallocateLbcb( Lfcb, ThisLbcb );
00958 }
00959 }
00960
00961 }
else {
00962
00963 FlushRestart =
TRUE;
00964 }
00965
00966
#if 1
00967
00968
00969
00970
00971 }
else {
00972
00973 FlushRestart =
TRUE;
00974 }
00975
#endif
00976
00977
00978
00979
00980
00981
if (FlushRestart) {
00982
00983
LfsWriteLfsRestart( Lfcb, Lfcb->
RestartAreaSize,
FALSE );
00984
LfsWriteLfsRestart( Lfcb, Lfcb->
RestartAreaSize,
TRUE );
00985 }
00986
00987
00988
00989
00990
00991 Lch->
Lfcb =
NULL;
00992 RemoveEntryList( &Lch->
LchLinks );
00993
00994
00995
00996
00997
00998
00999
#if 1
01000
if (Lfcb->
RestartArea->
ClientInUseList ==
LFS_NO_CLIENT) {
01001
#endif
01002
01003 RemoveEntryList( &Lfcb->
LfcbLinks );
01004
LfsDeallocateLfcb( Lfcb,
FALSE );
01005
#if 1
01006
}
01007
#endif
01008
01009 try_exit: NOTHING;
01010 } finally {
01011
01012
DebugUnwind(
LfsCloseLogFile );
01013
01014
01015
01016
01017
01018
LfsReleaseLch( Lch );
01019
01020
01021
01022
01023
01024
LfsReleaseLfsData();
01025
01026
DebugTrace( -1,
Dbg,
"LfsCloseLogFile: Exit\n", 0 );
01027 }
01028
01029 } except (
LfsExceptionFilter( GetExceptionInformation() )) {
01030
01031
Status = GetExceptionCode();
01032 }
01033
01034
01035
01036
01037
01038
if (ExitLoop) {
break; }
01039
01040
01041
01042
01043
01044
KeWaitForSingleObject( &Lfcb->
Sync->
Event,
01045
Executive,
01046
KernelMode,
01047
FALSE,
01048
NULL );
01049
01050
LfsAcquireLfcb( Lfcb );
01051 Lfcb->
Waiters -= 1;
01052
LfsReleaseLfcb( Lfcb );
01053 }
01054
01055
01056
01057
01058
01059
return;
01060 }
01061
01062
VOID
01063 LfsDeleteLogHandle (
01064 IN LFS_LOG_HANDLE LogHandle
01065 )
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087 {
01088
PLCH Lch;
01089
01090
PAGED_CODE();
01091
01092
01093
01094
01095
01096 Lch = (
PLCH) LogHandle;
01097
01098
if ((Lch ==
NULL) ||
01099 (Lch->
NodeTypeCode !=
LFS_NTC_LCH)) {
01100
01101
return;
01102 }
01103
01104
01105
01106
01107
01108
try {
01109
01110
LfsAcquireLch( Lch );
01111
01112 Lch->
Sync->
UserCount -= 1;
01113
01114
01115
01116
01117
01118
if (Lch->
Sync->
UserCount == 0) {
01119
01120
ExDeleteResource( &Lch->
Sync->
Resource );
01121
01122
ExFreePool( Lch->
Sync );
01123
01124 }
else {
01125
01126
LfsReleaseLch( Lch );
01127 }
01128
01129
LfsDeallocateLch( Lch );
01130
01131 } except (
LfsExceptionFilter( GetExceptionInformation() )) {
01132
01133 NOTHING;
01134 }
01135
01136
return;
01137 }
01138
01139
01140
VOID
01141 LfsReadLogFileInformation (
01142 IN LFS_LOG_HANDLE LogHandle,
01143 IN
PLOG_FILE_INFORMATION Buffer,
01144 IN OUT PULONG Length
01145 )
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170 {
01171
PLCH Lch;
01172
PLFCB Lfcb;
01173
01174
PAGED_CODE();
01175
01176
DebugTrace( +1,
Dbg,
"LfsReadLogFileInformation: Entered\n", 0 );
01177
DebugTrace( 0,
Dbg,
"Log Handle -> %08lx\n", LogHandle );
01178
DebugTrace( 0,
Dbg,
"Buffer -> %08lx\n",
Buffer );
01179
DebugTrace( 0,
Dbg,
"Length -> %08lx\n", *Length );
01180
01181 Lch = (
PLCH) LogHandle;
01182
01183
01184
01185
01186
01187
LfsValidateLch( Lch );
01188
01189
01190
01191
01192
01193
try {
01194
01195
01196
01197
01198
01199
LfsAcquireLch( Lch );
01200 Lfcb = Lch->
Lfcb;
01201
01202
01203
01204
01205
01206
if (Lfcb ==
NULL) {
01207
01208
try_return( *Length = 0 );
01209 }
01210
01211
01212
01213
01214
01215
LfsValidateClientId( Lfcb, Lch );
01216
01217
01218
01219
01220
01221
if (*Length >=
sizeof(
LOG_FILE_INFORMATION )) {
01222
01223
PLOG_FILE_INFORMATION Information;
01224 LONGLONG CurrentAvail;
01225 ULONG UnusedBytes;
01226
01227
LfsCurrentAvailSpace( Lfcb,
01228 &CurrentAvail,
01229 &UnusedBytes );
01230
01231
01232
01233
01234
01235
01236 Information = (
PLOG_FILE_INFORMATION)
Buffer;
01237
01238 Information->
TotalAvailable = Lfcb->
TotalAvailable;
01239 Information->
CurrentAvailable = CurrentAvail;
01240 Information->
TotalUndoCommitment = Lfcb->
TotalUndoCommitment;
01241 Information->
ClientUndoCommitment = Lch->
ClientUndoCommitment;
01242
01243 Information->
OldestLsn = Lfcb->
OldestLsn;
01244 Information->
LastFlushedLsn = Lfcb->
LastFlushedLsn;
01245 Information->
LastLsn = Lfcb->
RestartArea->
CurrentLsn;
01246
01247 *Length =
sizeof(
LOG_FILE_INFORMATION );
01248
01249 }
else {
01250
01251 *Length = 0;
01252 }
01253
01254 try_exit: NOTHING;
01255 } finally {
01256
01257
DebugUnwind(
LfsReadLogFileInformation );
01258
01259
01260
01261
01262
01263
LfsReleaseLch( Lch );
01264
01265
DebugTrace( -1,
Dbg,
"LfsReadLogFileInformation: Exit\n", 0 );
01266 }
01267
01268
return;
01269 }
01270
01271
01272 BOOLEAN
01273 LfsVerifyLogFile (
01274 IN LFS_LOG_HANDLE LogHandle,
01275 IN PVOID LogFileHeader,
01276 IN ULONG Length
01277 )
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303 {
01304 BOOLEAN ValidLogFile =
FALSE;
01305
PLCH Lch;
01306
PLFCB Lfcb;
01307
01308
PLFS_RESTART_PAGE_HEADER RestartPage = LogFileHeader;
01309
01310
PAGED_CODE();
01311
01312 Lch = (
PLCH) LogHandle;
01313
01314
01315
01316
01317
01318
if ((Lch ==
NULL) ||
01319 (Lch->
NodeTypeCode !=
LFS_NTC_LCH) ||
01320 ((Lch->
Lfcb !=
NULL) &&
01321 (Lch->
Lfcb->
NodeTypeCode !=
LFS_NTC_LFCB))) {
01322
01323
return FALSE;
01324 }
01325
01326
01327
01328
01329
01330
LfsAcquireLch( Lch );
01331 Lfcb = Lch->
Lfcb;
01332
01333
01334
01335
01336
01337
if (Lfcb ==
NULL) {
01338
01339
LfsReleaseLch( Lch );
01340
return FALSE;
01341 }
01342
01343
01344
01345
01346
01347
if ((Length >= (ULONG) Lfcb->
SystemPageSize) &&
01348 (*((PULONG) RestartPage) ==
LFS_SIGNATURE_RESTART_PAGE_ULONG) &&
01349 ((RestartPage->
RestartOffset +
sizeof(
LFS_RESTART_AREA )) < (ULONG) Lfcb->
SystemPageSize) &&
01350 ((
Add2Ptr( RestartPage, RestartPage->
RestartOffset,
PLFS_RESTART_AREA ))->RestartOpenLogCount == Lfcb->
CurrentOpenLogCount)) {
01351
01352 ValidLogFile =
TRUE;
01353 }
01354
01355
LfsReleaseLfcb( Lfcb );
01356
return ValidLogFile;
01357 }
01358
01359
01360
VOID
01361 LfsResetUndoTotal (
01362 IN LFS_LOG_HANDLE LogHandle,
01363 IN ULONG NumberRecords,
01364 IN LONG ResetTotal
01365 )
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404 {
01405
PLCH Lch;
01406
01407
PLFCB Lfcb;
01408
01409 LONGLONG AdjustedUndoTotal;
01410 LONG LfsHeaderBytes;
01411
01412
PAGED_CODE();
01413
01414
DebugTrace( +1,
Dbg,
"LfsResetUndoTotal: Entered\n", 0 );
01415
DebugTrace( 0,
Dbg,
"Log Handle -> %08lx\n", LogHandle );
01416
DebugTrace( 0,
Dbg,
"Number Records -> %08lx\n", NumberRecords );
01417
DebugTrace( 0,
Dbg,
"ResetTotal -> %08lx\n", ResetTotal );
01418
01419 Lch = (
PLCH) LogHandle;
01420
01421
01422
01423
01424
01425
LfsValidateLch( Lch );
01426
01427
01428
01429
01430
01431
try {
01432
01433
01434
01435
01436
01437
LfsAcquireLch( Lch );
01438 Lfcb = Lch->
Lfcb;
01439
01440
01441
01442
01443
01444
if (Lfcb ==
NULL) {
01445
01446
ExRaiseStatus( STATUS_ACCESS_DENIED );
01447 }
01448
01449
01450
01451
01452
01453
LfsValidateClientId( Lfcb, Lch );
01454
01455
01456
01457
01458
01459
01460
01461
01462 LfsHeaderBytes = NumberRecords * Lfcb->
RecordHeaderLength;
01463 LfsHeaderBytes *= 2;
01464
01465
if (!
FlagOn( Lfcb->
Flags,
LFCB_PACK_LOG )) {
01466
01467 ResetTotal *= 2;
01468 }
01469
01470
01471
01472
01473
01474
if (ResetTotal > 0) {
01475
01476
01477
01478
01479
01480
01481 Lfcb->
TotalUndoCommitment = Lfcb->
TotalUndoCommitment - Lch->
ClientUndoCommitment;
01482
01483
01484
01485
01486
01487
01488 Lch->
ClientUndoCommitment = 0;
01489
01490
01491 ResetTotal += LfsHeaderBytes;
01492
01493
01494
01495
01496
01497 }
else {
01498
01499 ResetTotal -= LfsHeaderBytes;
01500 }
01501
01502
01503
01504
01505
01506 AdjustedUndoTotal = ResetTotal;
01507
01508 Lfcb->
TotalUndoCommitment = Lfcb->
TotalUndoCommitment + AdjustedUndoTotal;
01509
01510 Lch->
ClientUndoCommitment = Lch->
ClientUndoCommitment + AdjustedUndoTotal;
01511
01512 } finally {
01513
01514
DebugUnwind(
LfsResetUndoTotal );
01515
01516
01517
01518
01519
01520
LfsReleaseLch( Lch );
01521
01522
DebugTrace( -1,
Dbg,
"LfsResetUndoTotal: Exit\n", 0 );
01523 }
01524
01525
return;
01526 }
01527
01528
01529
01530
01531
01532
01533
PLFCB
01534 LfsRestartLogFile (
01535 IN
PFILE_OBJECT LogFile,
01536 IN USHORT MaximumClients,
01537 IN ULONG LogPageSize OPTIONAL,
01538 IN LONGLONG FileSize,
01539 IN OUT PLFS_INFO LfsInfo,
01540 OUT
PLFS_WRITE_DATA WriteData
01541 )
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585 {
01586
PLFCB ThisLfcb =
NULL;
01587
PLFS_RESTART_AREA RestartArea =
NULL;
01588
PLFS_RESTART_AREA DiskRestartArea;
01589
01590 BOOLEAN UninitializedFile;
01591
01592 LONGLONG OriginalFileSize = FileSize;
01593 LONGLONG FirstRestartOffset;
01594
PLFS_RESTART_PAGE_HEADER FirstRestartPage;
01595 BOOLEAN FirstChkdskWasRun;
01596 BOOLEAN FirstValidPage;
01597 BOOLEAN FirstLogPacked;
01598
LSN FirstRestartLastLsn;
01599
01600
PBCB FirstRestartPageBcb =
NULL;
01601
PBCB SecondRestartPageBcb =
NULL;
01602
01603 BOOLEAN PackLogFile =
TRUE;
01604 BOOLEAN UseDefaultLogPage =
FALSE;
01605 LARGE_INTEGER CurrentTime;
01606
01607
PAGED_CODE();
01608
01609
DebugTrace( +1,
Dbg,
"LfsRestartLogFile: Entered\n", 0 );
01610
DebugTrace( 0,
Dbg,
"LogFile -> %08lx\n", LogFile );
01611
DebugTrace( 0,
Dbg,
"Maximum Clients -> %04x\n", MaximumClients );
01612
DebugTrace( 0,
Dbg,
"Log Page Size -> %08lx\n", LogPageSize );
01613
DebugTrace( 0,
Dbg,
"File Size (Low) -> %08lx\n", FileSize.LowPart );
01614
DebugTrace( 0,
Dbg,
"File Size (High) -> %08lx\n", FileSize.HighPart );
01615
DebugTrace( 0,
Dbg,
"Pack Log -> %04x\n", *LfsInfo );
01616
01617
01618
01619
01620
01621
01622
ASSERT( *LfsInfo >=
LfsPackLog );
01623
01624
if ((
PAGE_SIZE >=
LFS_DEFAULT_LOG_PAGE_SIZE) &&
01625 (
PAGE_SIZE <=
LFS_DEFAULT_LOG_PAGE_SIZE * 2) &&
01626 (*LfsInfo >=
LfsFixedPageSize)) {
01627
01628 UseDefaultLogPage =
TRUE;
01629 }
01630
01631
01632
01633
01634
01635
try {
01636
01637
01638
01639
01640
01641
LfsNormalizeBasicLogFile( &FileSize,
01642 &LogPageSize,
01643 &MaximumClients,
01644 UseDefaultLogPage );
01645
01646
01647
01648
01649
01650 ThisLfcb =
LfsAllocateLfcb();
01651
01652
01653
01654
01655
01656
LfsAcquireLfcb( ThisLfcb );
01657
01658
01659
01660
01661
01662 ThisLfcb->
FileObject = LogFile;
01663
01664
SetFlag( ThisLfcb->
Flags,
01665 (
LFCB_READ_FIRST_RESTART |
01666
LFCB_READ_SECOND_RESTART) );
01667
01668
01669
01670
01671
01672
if (
LfsReadRestart( ThisLfcb,
01673 FileSize,
01674
TRUE,
01675 &FirstRestartOffset,
01676 &FirstRestartPage,
01677 &FirstRestartPageBcb,
01678 &FirstChkdskWasRun,
01679 &FirstValidPage,
01680 &UninitializedFile,
01681 &FirstLogPacked,
01682 &FirstRestartLastLsn )) {
01683
01684 BOOLEAN DoubleRestart;
01685
01686 LONGLONG SecondRestartOffset;
01687
PLFS_RESTART_PAGE_HEADER SecondRestartPage;
01688 BOOLEAN SecondChkdskWasRun;
01689 BOOLEAN SecondValidPage;
01690 BOOLEAN SecondLogPacked;
01691
LSN SecondRestartLastLsn;
01692
01693
01694
01695
01696
01697
01698
if (FirstRestartOffset == 0) {
01699
01700
ClearFlag( ThisLfcb->
Flags,
LFCB_READ_FIRST_RESTART );
01701
01702 DoubleRestart =
LfsReadRestart( ThisLfcb,
01703 FileSize,
01704
FALSE,
01705 &SecondRestartOffset,
01706 &SecondRestartPage,
01707 &SecondRestartPageBcb,
01708 &SecondChkdskWasRun,
01709 &SecondValidPage,
01710 &UninitializedFile,
01711 &SecondLogPacked,
01712 &SecondRestartLastLsn );
01713
01714
if (DoubleRestart) {
01715
01716
ClearFlag( ThisLfcb->
Flags,
LFCB_READ_SECOND_RESTART );
01717 }
01718
01719 }
else {
01720
01721
ClearFlag( ThisLfcb->
Flags,
LFCB_READ_SECOND_RESTART );
01722 DoubleRestart =
FALSE;
01723 }
01724
01725
01726
01727
01728
01729
if (DoubleRestart
01730 && (SecondRestartLastLsn.QuadPart > FirstRestartLastLsn.QuadPart)) {
01731
01732 BOOLEAN UseSecondPage =
TRUE;
01733 PULONG SecondPage;
01734
PBCB SecondPageBcb =
NULL;
01735 BOOLEAN UsaError;
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
if (FirstChkdskWasRun &&
01746 (SecondRestartOffset !=
PAGE_SIZE)) {
01747
01748
if (
NT_SUCCESS(
LfsPinOrMapData( ThisLfcb,
01749
PAGE_SIZE,
01750
PAGE_SIZE,
01751
FALSE,
01752
TRUE,
01753
TRUE,
01754 &UsaError,
01755 &SecondPage,
01756 &SecondPageBcb )) &&
01757 (*SecondPage ==
LFS_SIGNATURE_MODIFIED_ULONG)) {
01758
01759 UseSecondPage =
FALSE;
01760 }
01761
01762
if (SecondPageBcb !=
NULL) {
01763
01764
CcUnpinData( SecondPageBcb );
01765 }
01766 }
01767
01768
if (UseSecondPage) {
01769
01770 FirstRestartOffset = SecondRestartOffset;
01771 FirstRestartPage = SecondRestartPage;
01772 FirstChkdskWasRun = SecondChkdskWasRun;
01773 FirstValidPage = SecondValidPage;
01774 FirstLogPacked = SecondLogPacked;
01775 FirstRestartLastLsn = SecondRestartLastLsn;
01776 }
01777 }
01778
01779
01780
01781
01782
01783
01784
if (FirstRestartOffset != 0) {
01785
01786 ThisLfcb->
InitialRestartArea =
TRUE;
01787 }
01788
01789
01790
01791
01792
01793
if (FirstValidPage) {
01794
01795 DiskRestartArea =
Add2Ptr( FirstRestartPage, FirstRestartPage->
RestartOffset,
PLFS_RESTART_AREA );
01796 }
01797
01798
01799
01800
01801
01802
01803
if (FirstChkdskWasRun
01804 || DiskRestartArea->
ClientInUseList ==
LFS_NO_CLIENT) {
01805
01806
01807
01808
01809
01810
SHORT MajorVersion = 1;
01811
SHORT MinorVersion = 1;
01812
01813 BOOLEAN LogFileWrapped =
FALSE;
01814 BOOLEAN UseMultiplePageIo =
FALSE;
01815
01816 BOOLEAN ForceRestartToDisk =
TRUE;
01817
01818 BOOLEAN ClearLogFile =
TRUE;
01819
01820 LONGLONG StartOffsetForClear;
01821 StartOffsetForClear = LogPageSize * 2;
01822
01823
01824
01825
01826
01827
if (FirstValidPage) {
01828
01829 CurrentTime.LowPart = DiskRestartArea->
RestartOpenLogCount;
01830
01831
01832
01833
01834
01835
01836
if (LogPageSize == FirstRestartPage->
SystemPageSize) {
01837
01838
01839
01840
01841
01842
01843
if (FileSize > DiskRestartArea->
FileSize) {
01844
01845 StartOffsetForClear = DiskRestartArea->
FileSize;
01846
01847 }
else {
01848
01849
if (!
FlagOn( DiskRestartArea->
Flags,
RESTART_SINGLE_PAGE_IO )) {
01850
01851 UseMultiplePageIo =
TRUE;
01852 LogFileWrapped =
TRUE;
01853 }
01854
01855
01856
01857
01858
01859
01860 ForceRestartToDisk =
FALSE;
01861 ClearLogFile =
FALSE;
01862 }
01863 }
01864
01865 }
else {
01866
01867
KeQuerySystemTime( &CurrentTime );
01868 }
01869
01870
01871
01872
01873
01874
LfsUpdateLfcbFromPgHeader( ThisLfcb,
01875 LogPageSize,
01876 LogPageSize,
01877 MajorVersion,
01878 MinorVersion,
01879 PackLogFile );
01880
01881
LfsUpdateLfcbFromNoRestart( ThisLfcb,
01882 FileSize,
01883 FirstRestartLastLsn,
01884 MaximumClients,
01885 CurrentTime.LowPart,
01886 LogFileWrapped,
01887 UseMultiplePageIo );
01888
01889
LfsAllocateRestartArea( &RestartArea, ThisLfcb->
RestartDataSize );
01890
01891
LfsUpdateRestartAreaFromLfcb( ThisLfcb, RestartArea );
01892
01893 ThisLfcb->
RestartArea = RestartArea;
01894 ThisLfcb->
ClientArray =
Add2Ptr( RestartArea,
01895 ThisLfcb->
ClientArrayOffset,
01896
PLFS_CLIENT_RECORD );
01897 RestartArea =
NULL;
01898
01899
01900
01901
01902
01903
if (FirstRestartPageBcb !=
NULL) {
01904
01905
CcUnpinData( FirstRestartPageBcb );
01906 FirstRestartPageBcb =
NULL;
01907 }
01908
01909
if (SecondRestartPageBcb !=
NULL) {
01910
01911
CcUnpinData( SecondRestartPageBcb );
01912 SecondRestartPageBcb =
NULL;
01913 }
01914
01915
01916
01917
01918
01919 ThisLfcb->
UserWriteData = WriteData;
01920 WriteData->
LfsStructureSize = LogPageSize;
01921 WriteData->Lfcb = ThisLfcb;
01922
01923
01924
01925
01926
01927
01928
LfsInitializeLogFilePriv( ThisLfcb,
01929 ForceRestartToDisk,
01930 ThisLfcb->
RestartDataSize,
01931 StartOffsetForClear,
01932 ClearLogFile );
01933
01934
01935
01936
01937
01938
01939
01940
01941 }
else {
01942
01943
if (LogPageSize != FirstRestartPage->
SystemPageSize) {
01944
01945 FileSize = OriginalFileSize;
01946
LfsNormalizeBasicLogFile( &FileSize,
01947 &LogPageSize,
01948 &MaximumClients,
01949 (BOOLEAN) (FirstRestartPage->
SystemPageSize ==
LFS_DEFAULT_LOG_PAGE_SIZE) );
01950 }
01951
01952
if ((LogPageSize != FirstRestartPage->
SystemPageSize) ||
01953 (LogPageSize != FirstRestartPage->
LogPageSize)) {
01954
01955
DebugTrace( 0,
Dbg,
"Page size mismatch\n", 0 );
01956
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
01957
01958
01959
01960
01961
01962 }
else if (FileSize < DiskRestartArea->
FileSize) {
01963
01964
DebugTrace( 0,
Dbg,
"Log file has shrunk without clean shutdown\n", 0 );
01965
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
01966
01967
01968
01969
01970
01971 }
else {
01972
01973
01974
01975
01976
01977 PackLogFile = FirstLogPacked;
01978
01979
01980
01981
01982
01983
01984
LfsUpdateLfcbFromPgHeader( ThisLfcb,
01985 LogPageSize,
01986 LogPageSize,
01987 FirstRestartPage->
MajorVersion,
01988 FirstRestartPage->
MinorVersion,
01989 FirstLogPacked );
01990
01991
LfsUpdateLfcbFromRestart( ThisLfcb,
01992 DiskRestartArea,
01993 FirstRestartPage->
RestartOffset );
01994
01995
01996
01997
01998
01999
LfsAllocateRestartArea( &RestartArea, ThisLfcb->
RestartDataSize );
02000
02001
02002
02003
02004
02005
02006
if (ThisLfcb->
ClientArrayOffset == FIELD_OFFSET(
LFS_RESTART_AREA, LogClientArray )) {
02007
02008 RtlCopyMemory( RestartArea, DiskRestartArea, ThisLfcb->
RestartAreaSize );
02009
02010 }
else {
02011
02012 LARGE_INTEGER CurrentTime;
02013
02014
02015
02016
02017
02018 RtlCopyMemory( RestartArea, DiskRestartArea, ThisLfcb->
ClientArrayOffset );
02019
02020
02021
02022
02023
02024 RtlCopyMemory( RestartArea->
LogClientArray,
02025
Add2Ptr( DiskRestartArea, ThisLfcb->
ClientArrayOffset, PVOID ),
02026 DiskRestartArea->
RestartAreaLength - ThisLfcb->
ClientArrayOffset );
02027
02028
02029
02030
02031
02032
KeQuerySystemTime( &CurrentTime );
02033
02034 ThisLfcb->
CurrentOpenLogCount =
02035 RestartArea->
RestartOpenLogCount = CurrentTime.LowPart;
02036
02037
02038
02039
02040
02041 ThisLfcb->
ClientArrayOffset = FIELD_OFFSET(
LFS_RESTART_AREA, LogClientArray );
02042 ThisLfcb->
RestartAreaSize = ThisLfcb->
ClientArrayOffset
02043 + (
sizeof(
LFS_CLIENT_RECORD ) * ThisLfcb->
LogClients );
02044
02045 RestartArea->
ClientArrayOffset = ThisLfcb->
ClientArrayOffset;
02046 RestartArea->
RestartAreaLength = (
USHORT) ThisLfcb->
RestartAreaSize;
02047 }
02048
02049
02050
02051
02052
02053 RestartArea->
RestartOpenLogCount += 1;
02054
02055 ThisLfcb->
RestartArea = RestartArea;
02056
02057 ThisLfcb->
ClientArray =
Add2Ptr( RestartArea, ThisLfcb->
ClientArrayOffset,
PLFS_CLIENT_RECORD );
02058 RestartArea =
NULL;
02059
02060
02061
02062
02063
02064
if (FirstRestartPageBcb !=
NULL) {
02065
02066
CcUnpinData( FirstRestartPageBcb );
02067 FirstRestartPageBcb =
NULL;
02068 }
02069
02070
if (SecondRestartPageBcb !=
NULL) {
02071
02072
CcUnpinData( SecondRestartPageBcb );
02073 SecondRestartPageBcb =
NULL;
02074 }
02075
02076
02077
02078
02079
02080 ThisLfcb->
UserWriteData = WriteData;
02081 WriteData->
LfsStructureSize = LogPageSize;
02082 WriteData->Lfcb = ThisLfcb;
02083
02084
02085
02086
02087
02088
02089
LfsFindLastLsn( ThisLfcb );
02090
02091
02092
02093
02094
02095
LfsFindCurrentAvail( ThisLfcb );
02096
02097
02098
02099
02100
02101
if (FirstRestartOffset != 0) {
02102
02103 ThisLfcb->
InitialRestartArea =
TRUE;
02104 }
02105
02106
02107
02108
02109
02110
LfsInitializeLogFilePriv( ThisLfcb,
02111
FALSE,
02112 ThisLfcb->
RestartDataSize,
02113 0,
02114
FALSE );
02115 }
02116 }
02117
02118
02119
02120
02121
02122
02123
02124
02125 }
else if (UninitializedFile) {
02126
02127
02128
02129
02130
02131
LfsUpdateLfcbFromPgHeader( ThisLfcb,
02132 LogPageSize,
02133 LogPageSize,
02134 1,
02135 1,
02136 PackLogFile );
02137
02138
KeQuerySystemTime( &CurrentTime );
02139
LfsUpdateLfcbFromNoRestart( ThisLfcb,
02140 FileSize,
02141
LfsLi0,
02142 MaximumClients,
02143 CurrentTime.LowPart,
02144
FALSE,
02145
FALSE );
02146
02147
LfsAllocateRestartArea( &RestartArea, ThisLfcb->
RestartDataSize );
02148
02149
LfsUpdateRestartAreaFromLfcb( ThisLfcb, RestartArea );
02150
02151 ThisLfcb->
RestartArea = RestartArea;
02152 ThisLfcb->
ClientArray =
Add2Ptr( RestartArea, ThisLfcb->
ClientArrayOffset,
PLFS_CLIENT_RECORD );
02153
02154 ThisLfcb->
InitialRestartArea =
TRUE;
02155 RestartArea =
NULL;
02156
02157
02158
02159
02160
02161 ThisLfcb->
UserWriteData = WriteData;
02162 WriteData->
LfsStructureSize = LogPageSize;
02163 WriteData->Lfcb = ThisLfcb;
02164
02165
02166
02167
02168
02169
02170
LfsInitializeLogFilePriv( ThisLfcb,
02171
FALSE,
02172 ThisLfcb->
RestartDataSize,
02173 0,
02174
FALSE );
02175
02176
02177
02178
02179
02180
02181 }
else {
02182
02183
DebugTrace( 0,
Dbg,
"Log file has no restart area\n", 0 );
02184
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
02185 }
02186
02187 } finally {
02188
02189
DebugUnwind(
LfsRestartLogFile );
02190
02191
02192
02193
02194
02195
if (ThisLfcb !=
NULL) {
02196
02197
LfsReleaseLfcb( ThisLfcb );
02198
02199
02200
02201
02202
02203
if (AbnormalTermination()) {
02204
02205
LfsDeallocateLfcb( ThisLfcb,
TRUE );
02206
02207
if (RestartArea !=
NULL) {
02208
02209
LfsDeallocateRestartArea( RestartArea );
02210 }
02211 }
02212 }
02213
02214
if (FirstRestartPageBcb !=
NULL) {
02215
02216
CcUnpinData( FirstRestartPageBcb );
02217 }
02218
02219
if (SecondRestartPageBcb !=
NULL) {
02220
02221
CcUnpinData( SecondRestartPageBcb );
02222 }
02223
02224
DebugTrace( -1,
Dbg,
"LfsRestartLogFile: Exit\n", 0 );
02225 }
02226
02227
02228
02229
02230
02231
if (PackLogFile
02232 && *LfsInfo <
LfsPackLog) {
02233
02234 *LfsInfo =
LfsPackLog;
02235 }
02236
02237
return ThisLfcb;
02238 }
02239
02240
02241
02242
02243
02244
02245
VOID
02246 LfsNormalizeBasicLogFile (
02247 IN OUT PLONGLONG FileSize,
02248 IN OUT PULONG LogPageSize,
02249 IN OUT PUSHORT LogClients,
02250 IN BOOLEAN UseDefaultLogPage
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 ULONG LocalLogPageSize;
02283 LONGLONG RestartPageBytes;
02284 LONGLONG LogPages;
02285
02286
USHORT MaximumClients;
02287
02288
PAGED_CODE();
02289
02290
DebugTrace( +1,
Dbg,
"LfsNormalizeBasicLogFile: Entered\n", 0 );
02291
02292
02293
02294
02295
02296
02297
if (!UseDefaultLogPage) {
02298
02299 *LogPageSize =
PAGE_SIZE;
02300
02301 }
else {
02302
02303 *LogPageSize =
LFS_DEFAULT_LOG_PAGE_SIZE;
02304 }
02305
02306
02307
02308
02309
02310
02311
if (*FileSize >
LfsMaximumFileSize) {
02312
02313 *FileSize =
LfsMaximumFileSize;
02314 }
02315
02316
02317
02318
02319
02320
02321 *(PULONG)FileSize &= ~(*LogPageSize - 1);
02322
02323
02324
02325
02326
02327 RestartPageBytes = 2 * *LogPageSize;
02328
02329
if (*FileSize <= RestartPageBytes) {
02330
02331
DebugTrace( 0,
Dbg,
"Log file is too small\n", 0 );
02332
DebugTrace( -1,
Dbg,
"LfsValidateBasicLogFile: Abnormal Exit\n", 0 );
02333
02334
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
02335 }
02336
02337
02338
02339
02340
02341 LogPages = *FileSize - RestartPageBytes;
02342 LocalLogPageSize = *LogPageSize >> 1;
02343
02344
while (LocalLogPageSize) {
02345
02346 LocalLogPageSize = LocalLogPageSize >> 1;
02347 LogPages = ((ULONGLONG)(LogPages)) >> 1;
02348 }
02349
02350
02351
02352
02353
02354
if (((PLARGE_INTEGER)&LogPages)->HighPart == 0
02355 && (ULONG)LogPages <
MINIMUM_LFS_PAGES) {
02356
02357
DebugTrace( 0,
Dbg,
"Not enough log pages -> %08lx\n", LogPages.LowPart );
02358
DebugTrace( -1,
Dbg,
"LfsValidateBasicLogFile: Abnormal Exit\n", 0 );
02359
02360
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
02361 }
02362
02363
02364
02365
02366
02367
02368 MaximumClients = (
USHORT) ((*LogPageSize / 2) /
sizeof(
LFS_CLIENT_RECORD ));
02369
02370
if (*LogClients == 0) {
02371
02372 *LogClients = 1;
02373
02374 }
else if (*LogClients > MaximumClients) {
02375
02376 *LogClients = MaximumClients;
02377 }
02378
02379
DebugTrace( -1,
Dbg,
"LfsNormalizeBasicLogFile: Exit\n", 0 );
02380
02381
return;
02382 }
02383
02384
02385
02386
02387
02388
02389
VOID
02390 LfsUpdateLfcbFromPgHeader (
02391 IN
PLFCB Lfcb,
02392 IN ULONG SystemPageSize,
02393 IN ULONG LogPageSize,
02394 IN SHORT MajorVersion,
02395 IN SHORT MinorVersion,
02396 IN BOOLEAN PackLog
02397 )
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426 {
02427
PAGED_CODE();
02428
02429
DebugTrace( +1,
Dbg,
"LfsUpdateLfcbFromPgHeader: Entered\n", 0 );
02430
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
02431
DebugTrace( 0,
Dbg,
"System Page Size -> %08lx\n", SystemPageSize );
02432
DebugTrace( 0,
Dbg,
"Log Page Size -> %08lx\n", LogPageSize );
02433
DebugTrace( 0,
Dbg,
"Major Version -> %04x\n", MajorVersion );
02434
DebugTrace( 0,
Dbg,
"Minor Version -> %04x\n", MinorVersion );
02435
02436
02437
02438
02439
02440 Lfcb->SystemPageSize = SystemPageSize;
02441 Lfcb->SystemPageMask = SystemPageSize - 1;
02442 Lfcb->SystemPageInverseMask = ~Lfcb->SystemPageMask;
02443
02444
02445
02446
02447
02448 Lfcb->LogPageSize = LogPageSize;
02449 Lfcb->LogPageMask = LogPageSize - 1;
02450 Lfcb->LogPageInverseMask = ~Lfcb->LogPageMask;
02451
02452 Lfcb->LogPageShift = 0;
02453
02454
while (
TRUE) {
02455
02456 LogPageSize = LogPageSize >> 1;
02457
02458
if (LogPageSize == 0) {
02459
02460
break;
02461 }
02462
02463 Lfcb->LogPageShift += 1;
02464 }
02465
02466
02467
02468
02469
02470
02471
02472 Lfcb->FirstLogPage = Lfcb->SystemPageSize << 1;
02473
02474
if (PackLog) {
02475
02476 Lfcb->FirstLogPage = ( Lfcb->LogPageSize << 1 ) + Lfcb->FirstLogPage;
02477
02478 Lfcb->LogRecordUsaOffset = (
USHORT)
LFS_PACKED_RECORD_PAGE_HEADER_SIZE;
02479
02480
SetFlag( Lfcb->Flags,
LFCB_PACK_LOG );
02481
02482 }
else {
02483
02484 Lfcb->LogRecordUsaOffset = (
USHORT)
LFS_UNPACKED_RECORD_PAGE_HEADER_SIZE;
02485 }
02486
02487
02488
02489
02490
02491 Lfcb->MajorVersion = MajorVersion;
02492 Lfcb->MinorVersion = MinorVersion;
02493
02494
02495
02496
02497
02498 Lfcb->RestartUsaOffset =
LFS_RESTART_PAGE_HEADER_SIZE;
02499
02500 Lfcb->RestartUsaArraySize = (
USHORT)
UpdateSequenceArraySize( (ULONG)Lfcb->SystemPageSize );
02501 Lfcb->LogRecordUsaArraySize = (
USHORT)
UpdateSequenceArraySize( (ULONG)Lfcb->LogPageSize );
02502
02503
DebugTrace( -1,
Dbg,
"LfsUpdateLfcbFromPgHeader: Exit\n", 0 );
02504
02505
return;
02506 }
02507
02508
02509
02510
02511
02512
02513
VOID
02514 LfsUpdateLfcbFromNoRestart (
02515 IN
PLFCB Lfcb,
02516 IN LONGLONG FileSize,
02517 IN LSN LastLsn,
02518 IN ULONG LogClients,
02519 IN ULONG OpenLogCount,
02520 IN BOOLEAN LogFileWrapped,
02521 IN BOOLEAN UseMultiplePageIo
02522 )
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554 {
02555 ULONG
Count;
02556
02557
PAGED_CODE();
02558
02559
DebugTrace( +1,
Dbg,
"LfsUpdateLfcbFromNoRestart: Entered\n", 0 );
02560
02561 Lfcb->FileSize = FileSize;
02562
02563
02564
02565
02566
02567
02568
02569
for (
Count = 0;
02570 ( FileSize != 0 );
02571
Count += 1,
02572 FileSize = ((ULONGLONG)(FileSize)) >> 1) {
02573 }
02574
02575 Lfcb->FileDataBits =
Count - 3;
02576
02577 Lfcb->SeqNumberBits = (
sizeof(
LSN ) * 8) - Lfcb->FileDataBits;
02578
02579
02580
02581
02582
02583
02584 Lfcb->SeqNumber =
LfsLsnToSeqNumber( Lfcb, LastLsn ) + 2;
02585
02586 Lfcb->SeqNumberForWrap = Lfcb->SeqNumber + 1;
02587
02588 Lfcb->NextLogPage = Lfcb->FirstLogPage;
02589
02590
SetFlag( Lfcb->Flags,
LFCB_NO_LAST_LSN |
LFCB_NO_OLDEST_LSN );
02591
02592
02593
02594
02595
02596 Lfcb->OldestLsn.QuadPart =
LfsFileOffsetToLsn( Lfcb, 0, Lfcb->SeqNumber );
02597 Lfcb->OldestLsnOffset = 0;
02598
02599 Lfcb->LastFlushedLsn = Lfcb->OldestLsn;
02600
02601
02602
02603
02604
02605
if (LogFileWrapped) {
02606
02607
SetFlag( Lfcb->Flags,
LFCB_LOG_WRAPPED );
02608 }
02609
02610
if (UseMultiplePageIo) {
02611
02612
SetFlag( Lfcb->Flags,
LFCB_MULTIPLE_PAGE_IO );
02613 }
02614
02615
02616
02617
02618
02619 (ULONG)Lfcb->LogPageDataOffset =
QuadAlign( Lfcb->LogRecordUsaOffset
02620 + (
sizeof(
UPDATE_SEQUENCE_NUMBER ) * Lfcb->LogRecordUsaArraySize) );
02621
02622 Lfcb->LogPageDataSize = Lfcb->LogPageSize - Lfcb->LogPageDataOffset;
02623 Lfcb->RecordHeaderLength =
LFS_RECORD_HEADER_SIZE;
02624
02625
if (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG )) {
02626
02627
02628
02629
02630
02631
LfsAllocateLbcb( Lfcb, &Lfcb->PrevTail );
02632 Lfcb->PrevTail->FileOffset = Lfcb->FirstLogPage - Lfcb->LogPageSize;
02633
02634
LfsAllocateLbcb( Lfcb, &Lfcb->ActiveTail );
02635 Lfcb->ActiveTail->FileOffset = Lfcb->PrevTail->FileOffset - Lfcb->LogPageSize;
02636
02637
02638
02639
02640
02641 (ULONG)Lfcb->ReservedLogPageSize = (ULONG)Lfcb->LogPageDataSize - Lfcb->RecordHeaderLength;
02642
02643 }
else {
02644
02645 (ULONG)Lfcb->ReservedLogPageSize = (ULONG)Lfcb->LogPageDataSize;
02646 }
02647
02648
02649
02650
02651
02652 Lfcb->RestartDataOffset =
QuadAlign(
LFS_RESTART_PAGE_HEADER_SIZE
02653 + (
sizeof(
UPDATE_SEQUENCE_NUMBER ) * Lfcb->RestartUsaArraySize) );
02654
02655 Lfcb->RestartDataSize = (ULONG)Lfcb->SystemPageSize - Lfcb->RestartDataOffset;
02656
02657 Lfcb->LogClients = (
USHORT) LogClients;
02658
02659 Lfcb->ClientArrayOffset = FIELD_OFFSET(
LFS_RESTART_AREA, LogClientArray );
02660
02661 Lfcb->RestartAreaSize = Lfcb->ClientArrayOffset
02662 + (
sizeof(
LFS_CLIENT_RECORD ) * Lfcb->LogClients );
02663
02664 Lfcb->CurrentOpenLogCount = OpenLogCount;
02665
02666
02667
02668
02669
02670
02671 Lfcb->TotalAvailInPages = Lfcb->FileSize - Lfcb->FirstLogPage;
02672 Lfcb->TotalAvailable = Int64ShrlMod32(((ULONGLONG)(Lfcb->TotalAvailInPages)), Lfcb->LogPageShift);
02673
02674
02675
02676
02677
02678
02679
02680 Lfcb->MaxCurrentAvail = Lfcb->TotalAvailable * (ULONG)Lfcb->ReservedLogPageSize;
02681
02682 Lfcb->TotalAvailable = Lfcb->TotalAvailable * (ULONG)Lfcb->LogPageDataSize;
02683
02684 Lfcb->CurrentAvailable = Lfcb->MaxCurrentAvail;
02685
02686
DebugTrace( -1,
Dbg,
"LfsUpdateLfcbFromNoRestart: Exit\n", 0 );
02687
02688
return;
02689 }
02690
02691
02692
02693
02694
02695
02696
VOID
02697 LfsUpdateLfcbFromRestart (
02698 IN OUT
PLFCB Lfcb,
02699 IN
PLFS_RESTART_AREA RestartArea,
02700 IN USHORT RestartOffset
02701 )
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724 {
02725 LONGLONG LsnFileOffset;
02726
02727
PAGED_CODE();
02728
02729
DebugTrace( +1,
Dbg,
"LfsUpdateLfcbFromRestartArea: Entered\n", 0 );
02730
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
02731
DebugTrace( 0,
Dbg,
"RestartArea -> %08lx\n", RestartArea );
02732
02733 Lfcb->FileSize = RestartArea->FileSize;
02734
02735
02736
02737
02738
02739
02740 Lfcb->SeqNumberBits = RestartArea->SeqNumberBits;
02741 Lfcb->FileDataBits = (
sizeof(
LSN ) * 8) - Lfcb->SeqNumberBits;
02742
02743
02744
02745
02746
02747
02748 Lfcb->LastFlushedLsn = RestartArea->CurrentLsn;
02749
02750 Lfcb->SeqNumber =
LfsLsnToSeqNumber( Lfcb, Lfcb->LastFlushedLsn );
02751 Lfcb->SeqNumberForWrap = Lfcb->SeqNumber + 1;
02752
02753
02754
02755
02756
02757
02758 Lfcb->LogClients = RestartArea->LogClients;
02759
02760
02761
02762
02763
02764 Lfcb->RestartDataOffset = RestartOffset;
02765 Lfcb->RestartDataSize = (ULONG)Lfcb->SystemPageSize - RestartOffset;
02766
02767
02768
02769
02770
02771
02772
if (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG )) {
02773
02774 Lfcb->RecordHeaderLength = RestartArea->RecordHeaderLength;
02775
02776 Lfcb->ClientArrayOffset = RestartArea->ClientArrayOffset;
02777
02778 Lfcb->RestartAreaSize = RestartArea->RestartAreaLength;
02779
02780 (ULONG)Lfcb->LogPageDataOffset = RestartArea->LogPageDataOffset;
02781 Lfcb->LogPageDataSize = Lfcb->LogPageSize - Lfcb->LogPageDataOffset;
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
LfsAllocateLbcb( Lfcb, &Lfcb->PrevTail );
02792 Lfcb->PrevTail->FileOffset = Lfcb->FirstLogPage - Lfcb->LogPageSize;
02793
02794
LfsAllocateLbcb( Lfcb, &Lfcb->ActiveTail );
02795 Lfcb->ActiveTail->FileOffset = Lfcb->PrevTail->FileOffset - Lfcb->LogPageSize;
02796
02797
02798
02799
02800
02801 (ULONG)Lfcb->ReservedLogPageSize = (ULONG)Lfcb->LogPageDataSize - Lfcb->RecordHeaderLength;
02802
02803 }
else {
02804
02805 Lfcb->RecordHeaderLength =
LFS_RECORD_HEADER_SIZE;
02806 Lfcb->ClientArrayOffset = FIELD_OFFSET(
LFS_OLD_RESTART_AREA, LogClientArray );
02807
02808 Lfcb->RestartAreaSize = Lfcb->ClientArrayOffset
02809 + (
sizeof(
LFS_CLIENT_RECORD ) * Lfcb->LogClients);
02810
02811 (ULONG)Lfcb->LogPageDataOffset =
QuadAlign( Lfcb->LogRecordUsaOffset
02812 + (
sizeof(
UPDATE_SEQUENCE_NUMBER ) * Lfcb->LogRecordUsaArraySize) );
02813
02814 Lfcb->LogPageDataSize = Lfcb->LogPageSize - Lfcb->LogPageDataOffset;
02815
02816 (ULONG)Lfcb->ReservedLogPageSize = (ULONG)Lfcb->LogPageDataSize;
02817 }
02818
02819
02820
02821
02822
02823
02824 LsnFileOffset =
LfsLsnToFileOffset( Lfcb, Lfcb->LastFlushedLsn );
02825
02826
if ( LsnFileOffset < Lfcb->FirstLogPage ) {
02827
02828
SetFlag( Lfcb->Flags,
LFCB_NO_LAST_LSN );
02829 Lfcb->NextLogPage = Lfcb->FirstLogPage;
02830
02831
02832
02833
02834
02835 }
else {
02836
02837 LONGLONG LsnFinalOffset;
02838 BOOLEAN Wrapped;
02839
02840 ULONG DataLength;
02841 ULONG RemainingPageBytes;
02842
02843 DataLength = RestartArea->LastLsnDataLength;
02844
02845
02846
02847
02848
02849
LfsLsnFinalOffset( Lfcb,
02850 Lfcb->LastFlushedLsn,
02851 DataLength,
02852 &LsnFinalOffset );
02853
02854
02855
02856
02857
02858
if ( LsnFinalOffset <= LsnFileOffset ) {
02859
02860 Lfcb->SeqNumber = 1 + Lfcb->SeqNumber;
02861
02862
SetFlag( Lfcb->Flags,
LFCB_LOG_WRAPPED );
02863 }
02864
02865
02866
02867
02868
02869
02870
LfsTruncateOffsetToLogPage( Lfcb, LsnFinalOffset, &LsnFileOffset );
02871
02872 RemainingPageBytes = (ULONG)Lfcb->LogPageSize
02873 - ((((ULONG)LsnFinalOffset) & Lfcb->LogPageMask) + 1);
02874
02875
02876
02877
02878
02879
02880
if (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG )
02881 && (RemainingPageBytes >= Lfcb->RecordHeaderLength)) {
02882
02883
SetFlag( Lfcb->Flags,
LFCB_REUSE_TAIL );
02884 Lfcb->NextLogPage = LsnFileOffset;
02885 Lfcb->ReusePageOffset = (ULONG)Lfcb->LogPageSize - RemainingPageBytes;
02886
02887 }
else {
02888
02889
LfsNextLogPageOffset( Lfcb, LsnFileOffset, &Lfcb->NextLogPage, &Wrapped );
02890 }
02891 }
02892
02893
02894
02895
02896
02897 Lfcb->OldestLsn = Lfcb->LastFlushedLsn;
02898
02899
LfsFindOldestClientLsn( RestartArea,
02900
Add2Ptr( RestartArea, Lfcb->ClientArrayOffset,
PLFS_CLIENT_RECORD ),
02901 &Lfcb->OldestLsn );
02902
02903 Lfcb->OldestLsnOffset =
LfsLsnToFileOffset( Lfcb, Lfcb->OldestLsn );
02904
02905
02906
02907
02908
02909
if ( Lfcb->OldestLsnOffset < Lfcb->FirstLogPage ) {
02910
02911
SetFlag( Lfcb->Flags,
LFCB_NO_OLDEST_LSN );
02912 }
02913
02914
02915
02916
02917
02918
02919
if (!
FlagOn( RestartArea->Flags,
RESTART_SINGLE_PAGE_IO )) {
02920
02921
SetFlag( Lfcb->Flags,
LFCB_LOG_WRAPPED |
LFCB_MULTIPLE_PAGE_IO );
02922 }
02923
02924
02925
02926
02927
02928
02929
02930 Lfcb->CurrentOpenLogCount = RestartArea->RestartOpenLogCount;
02931
02932
02933
02934
02935
02936
02937 Lfcb->TotalAvailInPages = Lfcb->FileSize - Lfcb->FirstLogPage;
02938
02939 Lfcb->TotalAvailable = Int64ShrlMod32(((ULONGLONG)(Lfcb->TotalAvailInPages)), Lfcb->LogPageShift);
02940
02941
02942
02943
02944
02945
02946
02947 Lfcb->MaxCurrentAvail = Lfcb->TotalAvailable * (ULONG)Lfcb->ReservedLogPageSize;
02948
02949 Lfcb->TotalAvailable = Lfcb->TotalAvailable * (ULONG)Lfcb->LogPageDataSize;
02950
02951
LfsFindCurrentAvail( Lfcb );
02952
02953
DebugTrace( -1,
Dbg,
"LfsUpdateLfcbFromRestartArea: Exit\n", 0 );
02954
02955
return;
02956 }
02957
02958
02959
02960
02961
02962
02963
VOID
02964 LfsUpdateRestartAreaFromLfcb (
02965 IN
PLFCB Lfcb,
02966 IN
PLFS_RESTART_AREA RestartArea
02967 )
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989 {
02990
PLFS_CLIENT_RECORD Client;
02991
USHORT ClientIndex;
02992
USHORT PrevClient =
LFS_NO_CLIENT;
02993
02994
PAGED_CODE();
02995
02996
DebugTrace( +1,
Dbg,
"LfsUpdateRestartAreaFromLfcb: Entered\n", 0 );
02997
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
02998
02999
03000
03001
03002
03003 RestartArea->CurrentLsn = Lfcb->LastFlushedLsn;
03004 RestartArea->LogClients = Lfcb->LogClients;
03005
03006
if (!
FlagOn( Lfcb->Flags,
LFCB_MULTIPLE_PAGE_IO )) {
03007
03008
SetFlag( RestartArea->Flags,
RESTART_SINGLE_PAGE_IO );
03009 }
03010
03011 RestartArea->SeqNumberBits = Lfcb->SeqNumberBits;
03012
03013 RestartArea->FileSize = Lfcb->FileSize;
03014 RestartArea->LastLsnDataLength = 0;
03015 RestartArea->ClientArrayOffset = Lfcb->ClientArrayOffset;
03016 RestartArea->RestartAreaLength = (
USHORT) Lfcb->RestartAreaSize;
03017
03018 RestartArea->RecordHeaderLength = Lfcb->RecordHeaderLength;
03019 RestartArea->LogPageDataOffset = (
USHORT)Lfcb->LogPageDataOffset;
03020
03021
03022
03023
03024
03025
03026 RestartArea->ClientInUseList =
LFS_NO_CLIENT;
03027 RestartArea->ClientFreeList = 0;
03028
03029
for (ClientIndex = 1,
03030 Client =
Add2Ptr( RestartArea, Lfcb->ClientArrayOffset,
PLFS_CLIENT_RECORD );
03031 ClientIndex < Lfcb->LogClients;
03032 ClientIndex += 1,
03033 Client++) {
03034
03035 Client->PrevClient = PrevClient;
03036 Client->NextClient = ClientIndex;
03037
03038 PrevClient = ClientIndex - 1;
03039 }
03040
03041
03042
03043
03044
03045 Client->PrevClient = PrevClient;
03046 Client->NextClient =
LFS_NO_CLIENT;
03047
03048
03049
03050
03051
03052 RestartArea->RestartOpenLogCount = Lfcb->CurrentOpenLogCount + 1;
03053
03054
DebugTrace( -1,
Dbg,
"LfsUpdateRestartAreaFromLfcb: Exit\n", 0 );
03055
03056
return;
03057 }
03058
03059
03060
03061
03062
03063
03064
VOID
03065 LfsInitializeLogFilePriv (
03066 IN
PLFCB Lfcb,
03067 IN BOOLEAN ForceRestartToDisk,
03068 IN ULONG RestartAreaSize,
03069 IN LONGLONG StartOffsetForClear,
03070 IN BOOLEAN ClearLogFile
03071 )
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107 {
03108
PAGED_CODE();
03109
03110
DebugTrace( +1,
Dbg,
"LfsInitializeLogFilePriv: Entered\n", 0 );
03111
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
03112
DebugTrace( 0,
Dbg,
"Force Restart -> %04x\n", ForceRestartToDisk );
03113
DebugTrace( 0,
Dbg,
"RestartAreaSize -> %08lx\n", RestartAreaSize );
03114
DebugTrace( 0,
Dbg,
"StartOffset (Low) -> %08lx\n", StartOffsetForClear.LowPart );
03115
DebugTrace( 0,
Dbg,
"StartOffset (High) -> %08lx\n", StartOffsetForClear.HighPart );
03116
DebugTrace( 0,
Dbg,
"Clear Log File -> %04x\n", ClearLogFile );
03117
03118
03119
03120
03121
03122
LfsWriteLfsRestart( Lfcb,
03123 RestartAreaSize,
03124
FALSE );
03125
03126
LfsWriteLfsRestart( Lfcb,
03127 RestartAreaSize,
03128 ForceRestartToDisk );
03129
03130
03131
03132
03133
03134
03135
if (ClearLogFile) {
03136
03137 PCHAR LogPage;
03138
PBCB LogPageBcb =
NULL;
03139
03140
try {
03141
03142
while ( StartOffsetForClear < Lfcb->FileSize ) {
03143
03144 BOOLEAN UsaError;
03145
03146
03147
03148
03149
03150
if (
NT_SUCCESS(
LfsPinOrMapData( Lfcb,
03151 StartOffsetForClear,
03152 (ULONG)Lfcb->LogPageSize,
03153
TRUE,
03154
FALSE,
03155
TRUE,
03156 &UsaError,
03157 (PVOID *) &LogPage,
03158 &LogPageBcb ))) {
03159
03160 RtlFillMemoryUlong( (PVOID)LogPage,
03161 (ULONG)Lfcb->LogPageSize,
03162
LFS_SIGNATURE_UNINITIALIZED_ULONG );
03163
03164
LfsFlushLogPage( Lfcb,
03165 LogPage,
03166 StartOffsetForClear,
03167 &LogPageBcb );
03168
03169 StartOffsetForClear = Lfcb->LogPageSize + StartOffsetForClear;
03170 }
03171 }
03172
03173 } finally {
03174
03175
if (LogPageBcb !=
NULL) {
03176
03177
CcUnpinData( LogPageBcb );
03178 }
03179 }
03180 }
03181
03182
DebugTrace( -1,
Dbg,
"LfsInitializeLogFilePriv: Exit\n", 0 );
03183
03184
return;
03185 }
03186
03187
03188
03189
03190
03191
03192
VOID
03193 LfsFindLastLsn (
03194 IN OUT
PLFCB Lfcb
03195 )
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231 {
03232
USHORT PageCount;
03233
USHORT PagePosition;
03234
03235 LONGLONG CurrentLogPageOffset;
03236 LONGLONG NextLogPageOffset;
03237
03238
LSN LastKnownLsn;
03239
03240 BOOLEAN Wrapped;
03241 BOOLEAN WrappedLogFile =
FALSE;
03242
03243 LONGLONG ExpectedSeqNumber;
03244
03245 LONGLONG FirstPartialIo;
03246 ULONG PartialIoCount = 0;
03247
03248
PLFS_RECORD_PAGE_HEADER LogPageHeader;
03249
PBCB LogPageHeaderBcb =
NULL;
03250
03251
PLFS_RECORD_PAGE_HEADER TestPageHeader;
03252
PBCB TestPageHeaderBcb =
NULL;
03253
03254 LONGLONG FirstTailFileOffset;
03255
PLFS_RECORD_PAGE_HEADER FirstTailPage;
03256 LONGLONG FirstTailOffset = 0;
03257
PBCB FirstTailPageBcb =
NULL;
03258
03259 LONGLONG SecondTailFileOffset;
03260
PLFS_RECORD_PAGE_HEADER SecondTailPage;
03261 LONGLONG SecondTailOffset = 0;
03262
PBCB SecondTailPageBcb =
NULL;
03263
03264
PLFS_RECORD_PAGE_HEADER TailPage;
03265
03266 BOOLEAN UsaError;
03267 BOOLEAN ReplacePage =
FALSE;
03268 BOOLEAN ValidFile =
FALSE;
03269
03270 BOOLEAN InitialReusePage =
FALSE;
03271
03272
NTSTATUS Status;
03273
03274
PAGED_CODE();
03275
03276
DebugTrace( +1,
Dbg,
"LfsFindLastLsn: Entered\n", 0 );
03277
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
03278
03279
03280
03281
03282
03283
03284
03285 PageCount = 1;
03286 PagePosition = 1;
03287
03288
03289
03290
03291
03292
03293
03294 CurrentLogPageOffset = Lfcb->NextLogPage;
03295
03296
03297
03298
03299
03300
03301
03302
if (( CurrentLogPageOffset == Lfcb->FirstLogPage )
03303 && !
FlagOn( Lfcb->Flags,
LFCB_NO_LAST_LSN |
LFCB_REUSE_TAIL )) {
03304
03305 ExpectedSeqNumber = Lfcb->SeqNumber + 1;
03306 WrappedLogFile =
TRUE;
03307
03308 }
else {
03309
03310 ExpectedSeqNumber = Lfcb->SeqNumber;
03311 }
03312
03313
03314
03315
03316
03317
03318
if (
FlagOn( Lfcb->Flags,
LFCB_REUSE_TAIL )) {
03319
03320 LastKnownLsn = Lfcb->LastFlushedLsn;
03321
03322
03323
03324
03325
03326
03327
03328 InitialReusePage =
TRUE;
03329
03330 }
else {
03331
03332 LastKnownLsn =
LfsLi0;
03333 }
03334
03335
03336
03337
03338
03339
try {
03340
03341
03342
03343
03344
03345
if (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG )) {
03346
03347
03348
03349
03350
03351 SecondTailFileOffset = Lfcb->FirstLogPage - Lfcb->LogPageSize;
03352
03353
if (
NT_SUCCESS(
LfsPinOrMapData( Lfcb,
03354 SecondTailFileOffset,
03355 (ULONG)Lfcb->LogPageSize,
03356
TRUE,
03357
TRUE,
03358
TRUE,
03359 &UsaError,
03360 &SecondTailPage,
03361 &SecondTailPageBcb ))) {
03362
03363
03364
03365
03366
03367
if (UsaError
03368 || *((PULONG) &SecondTailPage->
MultiSectorHeader.
Signature) !=
LFS_SIGNATURE_RECORD_PAGE_ULONG) {
03369
03370
CcUnpinData( SecondTailPageBcb );
03371 SecondTailPageBcb = SecondTailPage =
NULL;
03372
03373 }
else {
03374
03375 SecondTailOffset = SecondTailPage->
Copy.FileOffset;
03376 }
03377
03378 }
else if (SecondTailPageBcb !=
NULL) {
03379
03380
CcUnpinData( SecondTailPageBcb );
03381 SecondTailPageBcb = SecondTailPage =
NULL;
03382 }
03383
03384 FirstTailFileOffset = SecondTailFileOffset - Lfcb->LogPageSize;
03385
03386
03387
03388
03389
03390
if (
NT_SUCCESS(
LfsPinOrMapData( Lfcb,
03391 FirstTailFileOffset,
03392 (ULONG)Lfcb->LogPageSize,
03393
TRUE,
03394
TRUE,
03395
TRUE,
03396 &UsaError,
03397 &FirstTailPage,
03398 &FirstTailPageBcb ))) {
03399
03400
03401
03402
03403
03404
if (UsaError
03405 || *((PULONG) &FirstTailPage->
MultiSectorHeader.
Signature) !=
LFS_SIGNATURE_RECORD_PAGE_ULONG) {
03406
03407
CcUnpinData( FirstTailPageBcb );
03408 FirstTailPageBcb = FirstTailPage =
NULL;
03409
03410 }
else {
03411
03412 FirstTailOffset = FirstTailPage->
Copy.FileOffset;
03413 }
03414
03415 }
else if (FirstTailPageBcb !=
NULL) {
03416
03417
CcUnpinData( FirstTailPageBcb );
03418 FirstTailPageBcb = FirstTailPage =
NULL;
03419 }
03420 }
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
while (
TRUE) {
03436
03437 LONGLONG ActualSeqNumber;
03438 TailPage =
NULL;
03439
03440
03441
03442
03443
03444
Status =
LfsPinOrMapData( Lfcb,
03445 CurrentLogPageOffset,
03446 (ULONG)Lfcb->LogPageSize,
03447
TRUE,
03448
TRUE,
03449
TRUE,
03450 &UsaError,
03451 (PVOID *) &LogPageHeader,
03452 &LogPageHeaderBcb );
03453
03454
03455
03456
03457
03458
LfsNextLogPageOffset( Lfcb,
03459 CurrentLogPageOffset,
03460 &NextLogPageOffset,
03461 &Wrapped );
03462
03463
03464
03465
03466
03467
03468
03469
03470
if (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG ) &&
03471 ((PageCount == PagePosition) ||
03472 (PageCount == PagePosition + 1))) {
03473
03474
03475
03476
03477
03478
03479
if (CurrentLogPageOffset == FirstTailOffset) {
03480
03481 TailPage = FirstTailPage;
03482 }
03483
03484
if (CurrentLogPageOffset == SecondTailOffset) {
03485
03486
03487
03488
03489
03490
03491
if ((TailPage ==
NULL) ||
03492 (SecondTailPage->
Header.Packed.LastEndLsn.QuadPart >
03493 FirstTailPage->
Header.Packed.LastEndLsn.QuadPart )) {
03494
03495 TailPage = SecondTailPage;
03496 }
03497 }
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
if (TailPage) {
03508
03509
if (LastKnownLsn.QuadPart < TailPage->
Header.Packed.LastEndLsn.QuadPart) {
03510
03511 ActualSeqNumber =
LfsLsnToSeqNumber( Lfcb, TailPage->
Header.Packed.LastEndLsn );
03512
03513
03514
03515
03516
03517
03518
if (ExpectedSeqNumber != ActualSeqNumber) {
03519
03520 TailPage =
NULL;
03521 }
03522
03523
03524
03525
03526
03527
03528 }
else if (LastKnownLsn.QuadPart > TailPage->
Header.Packed.LastEndLsn.QuadPart) {
03529
03530 TailPage =
NULL;
03531 }
03532 }
03533 }
03534
03535
03536
03537
03538
03539
03540
if (!
NT_SUCCESS(
Status ) || UsaError) {
03541
03542
break;
03543 }
03544
03545
03546
03547
03548
03549
03550
03551 ActualSeqNumber =
LfsLsnToSeqNumber( Lfcb,
03552 LogPageHeader->Copy.LastLsn );
03553
03554
if ((LastKnownLsn.QuadPart != LogPageHeader->Copy.LastLsn.QuadPart) &&
03555 (ActualSeqNumber != ExpectedSeqNumber)) {
03556
03557
break;
03558 }
03559
03560
03561
03562
03563
03564
03565
03566
if (PageCount == PagePosition) {
03567
03568
03569
03570
03571
03572
03573
03574
03575
if ((LogPageHeader->PagePosition != 1) &&
03576 (!InitialReusePage ||
03577 (LogPageHeader->PagePosition != LogPageHeader->PageCount))) {
03578
03579
break;
03580 }
03581
03582
03583
03584
03585
03586
03587 }
else if ((LogPageHeader->PageCount != PageCount) ||
03588 (LogPageHeader->PagePosition != PagePosition + 1)) {
03589
03590
break;
03591 }
03592
03593
03594
03595
03596
03597
03598
03599
if (TailPage &&
03600 (TailPage->
Header.Packed.LastEndLsn.QuadPart >= LogPageHeader->Copy.LastLsn.QuadPart)) {
03601
03602
03603
03604
03605
03606 ReplacePage =
TRUE;
03607
break;
03608 }
03609
03610 TailPage =
NULL;
03611
03612
03613
03614
03615
03616
03617
if (
FlagOn( LogPageHeader->Flags,
LOG_PAGE_LOG_RECORD_END )) {
03618
03619
03620
03621
03622
03623
03624
03625 Lfcb->SeqNumber = ExpectedSeqNumber;
03626
ClearFlag( Lfcb->Flags,
LFCB_REUSE_TAIL );
03627
03628
if (
FlagOn( Lfcb->Flags,
LFCB_PACK_LOG )) {
03629
03630 Lfcb->LastFlushedLsn = LogPageHeader->Header.Packed.LastEndLsn;
03631
03632
03633
03634
03635
03636
03637
if (Lfcb->RecordHeaderLength <=
03638 ((ULONG)Lfcb->LogPageSize - LogPageHeader->Header.Packed.NextRecordOffset )) {
03639
03640
SetFlag( Lfcb->Flags,
LFCB_REUSE_TAIL );
03641 Lfcb->ReusePageOffset = LogPageHeader->Header.Packed.NextRecordOffset;
03642 }
03643
03644 }
else {
03645
03646 Lfcb->LastFlushedLsn = LogPageHeader->Copy.LastLsn;
03647 }
03648
03649 Lfcb->RestartArea->CurrentLsn = Lfcb->LastFlushedLsn;
03650
03651
ClearFlag( Lfcb->Flags,
LFCB_NO_LAST_LSN );
03652
03653
03654
03655
03656
03657
03658
03659
if (
FlagOn( Lfcb->Flags,
LFCB_REUSE_TAIL )) {
03660
03661 Lfcb->NextLogPage = CurrentLogPageOffset;
03662
03663 }
else {
03664
03665 Lfcb->NextLogPage = NextLogPageOffset;
03666 }
03667
03668
03669
03670
03671
03672
if (WrappedLogFile) {
03673
03674
SetFlag( Lfcb->Flags,
LFCB_LOG_WRAPPED );
03675 }
03676 }
03677
03678
03679
03680
03681
03682
03683 PageCount = LogPageHeader->PageCount;
03684 PagePosition = LogPageHeader->PagePosition;
03685 LastKnownLsn = LogPageHeader->Copy.LastLsn;
03686
03687
03688
03689
03690
03691
03692
if (Wrapped) {
03693
03694 ExpectedSeqNumber = ExpectedSeqNumber + 1;
03695 WrappedLogFile =
TRUE;
03696 }
03697
03698 CurrentLogPageOffset = NextLogPageOffset;
03699
03700
03701
03702
03703
03704
CcUnpinData( LogPageHeaderBcb );
03705 LogPageHeaderBcb =
NULL;
03706
03707 InitialReusePage =
FALSE;
03708 }
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
if (TailPage !=
NULL) {
03724
03725
03726
03727
03728
03729
03730 Lfcb->SeqNumber = ExpectedSeqNumber;
03731
03732 Lfcb->LastFlushedLsn = TailPage->
Header.Packed.LastEndLsn;
03733
03734 Lfcb->RestartArea->CurrentLsn = Lfcb->LastFlushedLsn;
03735
03736
ClearFlag( Lfcb->Flags,
LFCB_NO_LAST_LSN );
03737
03738
03739
03740
03741
03742
03743
if (((ULONG)Lfcb->LogPageSize - TailPage->
Header.Packed.NextRecordOffset )
03744 >= Lfcb->RecordHeaderLength) {
03745
03746
SetFlag( Lfcb->Flags,
LFCB_REUSE_TAIL );
03747 Lfcb->NextLogPage = CurrentLogPageOffset;
03748 Lfcb->ReusePageOffset = TailPage->
Header.Packed.NextRecordOffset;
03749
03750 }
else {
03751
03752
ClearFlag( Lfcb->Flags,
LFCB_REUSE_TAIL );
03753 Lfcb->NextLogPage = NextLogPageOffset;
03754 }
03755
03756
03757
03758
03759
03760
if (WrappedLogFile) {
03761
03762
SetFlag( Lfcb->Flags,
LFCB_LOG_WRAPPED );
03763 }
03764 }
03765
03766
03767
03768
03769
03770 FirstPartialIo = NextLogPageOffset;
03771
03772
03773
03774
03775
03776
03777
03778
if (Wrapped) {
03779
03780 ExpectedSeqNumber = ExpectedSeqNumber + 1;
03781 }
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
if (ReplacePage ||
03798
FlagOn( Lfcb->RestartArea->Flags,
RESTART_SINGLE_PAGE_IO )) {
03799
03800
03801
03802
03803
03804 PageCount = 2;
03805 PagePosition = 1;
03806
03807
03808
03809
03810
03811
03812
03813 }
else if (PagePosition == PageCount) {
03814
03815
USHORT CurrentPosition;
03816
03817
03818
03819
03820
03821
03822
if (Wrapped) {
03823
03824
03825
03826
03827
03828 PageCount = 2;
03829 PagePosition = 1;
03830
03831
03832
03833
03834
03835
03836 }
else {
03837
03838
03839
03840
03841
03842
03843
03844
03845 CurrentPosition = 2;
03846
03847
do {
03848
03849
03850
03851
03852
03853
03854
03855
if (TestPageHeaderBcb !=
NULL) {
03856
03857
CcUnpinData( TestPageHeaderBcb );
03858 TestPageHeaderBcb =
NULL;
03859 }
03860
03861
Status =
LfsPinOrMapData( Lfcb,
03862 NextLogPageOffset,
03863 (ULONG)Lfcb->LogPageSize,
03864
TRUE,
03865
TRUE,
03866
TRUE,
03867 &UsaError,
03868 (PVOID *) &TestPageHeader,
03869 &TestPageHeaderBcb );
03870
03871
03872
03873
03874
03875
03876
if (UsaError) {
03877
03878 ValidFile =
TRUE;
03879
break;
03880
03881
03882
03883
03884
03885
03886 }
else if (
NT_SUCCESS(
Status )) {
03887
03888
03889
03890
03891
03892
03893
03894
if (TestPageHeader->PagePosition == CurrentPosition
03895 &&
LfsCheckSubsequentLogPage( Lfcb,
03896 TestPageHeader,
03897 NextLogPageOffset,
03898 ExpectedSeqNumber )) {
03899
03900 PageCount = TestPageHeader->PageCount + 1;
03901 PagePosition = TestPageHeader->PagePosition;
03902
03903
break;
03904
03905
03906
03907
03908
03909
03910 }
else {
03911
03912 ValidFile =
TRUE;
03913
break;
03914 }
03915
03916
03917
03918
03919
03920 }
else {
03921
03922
03923
03924
03925
03926
LfsNextLogPageOffset( Lfcb,
03927 NextLogPageOffset,
03928 &NextLogPageOffset,
03929 &Wrapped );
03930
03931
03932
03933
03934
03935
03936
03937
if (Wrapped) {
03938
03939 ExpectedSeqNumber = ExpectedSeqNumber + 1;
03940
03941 PageCount = 2;
03942 PagePosition = 1;
03943 }
03944
03945 CurrentPosition += 1;
03946 }
03947
03948
03949
03950
03951
03952 PartialIoCount += 1;
03953
03954 }
while( !Wrapped );
03955 }
03956 }
03957
03958
03959
03960
03961
03962
03963
03964
if (!ValidFile) {
03965
03966 ULONG RemainingPages;
03967
03968
03969
03970
03971
03972 RemainingPages = (PageCount - PagePosition) - 1;
03973
03974 PartialIoCount += RemainingPages;
03975
03976
while (RemainingPages--) {
03977
03978
LfsNextLogPageOffset( Lfcb,
03979 NextLogPageOffset,
03980 &NextLogPageOffset,
03981 &Wrapped );
03982
03983
if (Wrapped) {
03984
03985 ExpectedSeqNumber = ExpectedSeqNumber + 1;
03986 }
03987 }
03988
03989
03990
03991
03992
03993
if (TestPageHeaderBcb !=
NULL) {
03994
03995
CcUnpinData( TestPageHeaderBcb );
03996 TestPageHeaderBcb =
NULL;
03997 }
03998
03999
Status =
LfsPinOrMapData( Lfcb,
04000 NextLogPageOffset,
04001 (ULONG)Lfcb->LogPageSize,
04002
TRUE,
04003
TRUE,
04004
TRUE,
04005 &UsaError,
04006 (PVOID *) &TestPageHeader,
04007 &TestPageHeaderBcb );
04008
04009
if (
NT_SUCCESS(
Status )
04010 && !UsaError) {
04011
04012
if (
LfsCheckSubsequentLogPage( Lfcb,
04013 TestPageHeader,
04014 NextLogPageOffset,
04015 ExpectedSeqNumber )) {
04016
04017
DebugTrace( 0,
Dbg,
"Log file is fatally flawed\n", 0 );
04018
ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
04019 }
04020 }
04021
04022 ValidFile =
TRUE;
04023 }
04024
04025
04026
04027
04028
04029
if (LogPageHeaderBcb !=
NULL) {
04030
04031
CcUnpinData( LogPageHeaderBcb );
04032 LogPageHeaderBcb =
NULL;
04033 }
04034
04035
04036
04037
04038
04039
04040
04041
04042
if (TailPage !=
NULL) {
04043
04044
#ifdef BENL_DBG
04045
KdPrint((
"LFS: copying tail page at 0x%x to 0x%I64x, 1st:0x%x 2nd:0x%x \n", TailPage, TailPage->
Copy.FileOffset, FirstTailPage, SecondTailPage ));
04046
#endif
04047
04048
04049
04050
04051
04052
04053
LfsPinOrMapData( Lfcb,
04054 TailPage->
Copy.FileOffset,
04055 (ULONG)Lfcb->LogPageSize,
04056
TRUE,
04057
FALSE,
04058
TRUE,
04059 &UsaError,
04060 (PVOID *) &LogPageHeader,
04061 &LogPageHeaderBcb );
04062
04063 RtlCopyMemory( LogPageHeader,
04064 TailPage,
04065 (ULONG)Lfcb->LogPageSize );
04066
04067
04068
04069
04070
04071 LogPageHeader->Copy.LastLsn = TailPage->
Header.Packed.LastEndLsn;
04072
04073
LfsFlushLogPage( Lfcb,
04074 LogPageHeader,
04075 TailPage->
Copy.FileOffset,
04076 &LogPageHeaderBcb );
04077 }
04078
04079
04080
04081
04082
04083
04084
04085
04086
while (PartialIoCount--) {
04087
04088
04089
04090
04091
04092
if (LogPageHeaderBcb !=
NULL) {
04093
04094
CcUnpinData( LogPageHeaderBcb );
04095 LogPageHeaderBcb =
NULL;
04096 }
04097
04098
if (
NT_SUCCESS(
LfsPinOrMapData( Lfcb,
04099 FirstPartialIo,
04100 (ULONG)Lfcb->LogPageSize,
04101
TRUE,
04102
TRUE,
04103
TRUE,
04104 &UsaError,
04105 (PVOID *) &LogPageHeader,
04106 &LogPageHeaderBcb ))) {
04107
04108
04109
04110
04111
04112
04113 *((PULONG) &LogPageHeader->MultiSectorHeader.Signature) =
LFS_SIGNATURE_BAD_USA_ULONG;
04114
04115
LfsFlushLogPage( Lfcb,
04116 LogPageHeader,
04117 FirstPartialIo,
04118 &LogPageHeaderBcb );
04119 }
04120
04121
LfsNextLogPageOffset( Lfcb,
04122 FirstPartialIo,
04123 &FirstPartialIo,
04124 &Wrapped );
04125 }
04126
04127
04128
04129
04130
04131
04132
#ifdef BENL_DBG
04133
04134
if (FirstTailPageBcb !=
NULL) {
04135 KdPrint((
"LFS: not spitting BAAD to 1st page\n" ));
04136 }
04137
04138
if (SecondTailPageBcb !=
NULL) {
04139 KdPrint((
"LFS: not spitting BAAD to 2nd page\n" ));
04140 }
04141
#endif
04142
04143
04144 } finally {
04145
04146
DebugUnwind(
LfsFindLastLsn );
04147
04148
04149
04150
04151
04152
if (SecondTailPageBcb !=
NULL) {
04153
04154
CcUnpinData( SecondTailPageBcb );
04155 }
04156
04157
if (FirstTailPageBcb !=
NULL) {
04158
04159
CcUnpinData( FirstTailPageBcb );
04160 }
04161
04162
04163
04164
04165
04166
if (LogPageHeaderBcb !=
NULL) {
04167
04168
CcUnpinData( LogPageHeaderBcb );
04169 }
04170
04171
if (TestPageHeaderBcb !=
NULL) {
04172
04173
CcUnpinData( TestPageHeaderBcb );
04174 }
04175
04176
DebugTrace( -1,
Dbg,
"LfsFindLastLsn: Exit\n", 0 );
04177 }
04178
04179
return;
04180 }
04181
04182
04183
04184
04185
04186
04187 BOOLEAN
04188 LfsCheckSubsequentLogPage (
04189 IN
PLFCB Lfcb,
04190 IN
PLFS_RECORD_PAGE_HEADER RecordPageHeader,
04191 IN LONGLONG LogFileOffset,
04192 IN LONGLONG SequenceNumber
04193 )
04194
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234 {
04235 BOOLEAN IsSubsequent;
04236
04237
LSN Lsn;
04238 LONGLONG LsnSeqNumber;
04239 LONGLONG SeqNumberMinus1;
04240 LONGLONG LogPageFileOffset;
04241
04242
PAGED_CODE();
04243
04244
DebugTrace( +1,
Dbg,
"LfsCheckSubsequentLogPage: Entered\n", 0 );
04245
DebugTrace( 0,
Dbg,
"Lfcb -> %08lx\n", Lfcb );
04246
DebugTrace( 0,
Dbg,
"RecordPageHeader -> %08lx\n", RecordPageHeader );
04247
DebugTrace( 0,
Dbg,
"LogFileOffset (Low) -> %08lx\n", LogFileOffset.LowPart );
04248
DebugTrace( 0,
Dbg,
"LogFileOffset (High) -> %08lx\n", LogFileOffset.HighPart );
04249
DebugTrace( 0,
Dbg,
"SequenceNumber (Low) -> %08lx\n", SequenceNumber.LowPart );
04250
DebugTrace( 0,
Dbg,
"SequenceNumber (High) -> %08lx\n", SequenceNumber.HighPart );
04251
04252
04253
04254
04255
04256
04257
if (*((PULONG) RecordPageHeader->MultiSectorHeader.Signature) ==
LFS_SIGNATURE_UNINITIALIZED_ULONG
04258 || *((PULONG) RecordPageHeader->MultiSectorHeader.Signature) == 0) {
04259
04260
DebugTrace( -1,
Dbg,
"LfsCheckSubsequentLogPage: Exit -> %08x\n",
FALSE );
04261
return FALSE;
04262 }
04263
04264
04265
04266
04267
04268
04269
04270 Lsn = RecordPageHeader->Copy.LastLsn;
04271
04272
LfsTruncateLsnToLogPage( Lfcb, Lsn, &LogPageFileOffset );
04273 LsnSeqNumber =
LfsLsnToSeqNumber( Lfcb, Lsn );
04274
04275 SeqNumberMinus1 = SequenceNumber - 1;
04276
04277
04278
04279
04280
04281
04282
if ( LsnSeqNumber >= SequenceNumber ) {
04283
04284 IsSubsequent =
TRUE;
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299 }
else if (( LsnSeqNumber == SeqNumberMinus1 )
04300 && ( Lfcb->FirstLogPage == LogFileOffset )
04301 && ( LogFileOffset != LogPageFileOffset )) {
04302
04303 IsSubsequent =
TRUE;
04304
04305 }
else {
04306
04307 IsSubsequent =
FALSE;
04308 }
04309
04310
DebugTrace( -1,
Dbg,
"LfsCheckSubsequentLogPage: Exit -> %08x\n", IsSubsequent );
04311
04312
return IsSubsequent;
04313 }
04314
04315
04316
04317
04318
04319
04320
VOID
04321 LfsFlushLogPage (
04322 IN
PLFCB Lfcb,
04323 PVOID LogPage,
04324 IN LONGLONG FileOffset,
04325 OUT
PBCB *Bcb
04326 )
04327
04328
04329
04330
04331
04332
04333
04334
04335
04336
04337
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351 {
04352
PAGED_CODE();
04353
04354
04355
04356
04357
04358
CcSetDirtyPinnedData( *Bcb,
NULL );
04359
CcUnpinData( *Bcb );
04360 *Bcb =
NULL;
04361
04362
04363
04364
04365
04366 Lfcb->UserWriteData->FileOffset = FileOffset;
04367 Lfcb->UserWriteData->Length = (ULONG) Lfcb->LogPageSize;
04368
04369
CcFlushCache( Lfcb->FileObject->SectionObjectPointer,
04370 (PLARGE_INTEGER) &FileOffset,
04371 (ULONG) Lfcb->LogPageSize,
04372
NULL );
04373
04374
return;
04375 }
04376
04377
04378
04379
04380
04381
04382
VOID
04383 LfsRemoveClientFromList (
04384
PLFS_CLIENT_RECORD ClientArray,
04385
PLFS_CLIENT_RECORD ClientRecord,
04386 IN PUSHORT ListHead
04387 )
04388
04389
04390
04391
04392
04393
04394
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411 {
04412
PLFS_CLIENT_RECORD TempClientRecord;
04413
04414
PAGED_CODE();
04415
04416
DebugTrace( +1,
Dbg,
"LfsRemoveClientFromList: Entered\n", 0 );
04417
DebugTrace( 0,
Dbg,
"Client Array -> %08lx\n", ClientArray );
04418
DebugTrace( 0,
Dbg,
"Client Record -> %08lx\n", ClientRecord );
04419
DebugTrace( 0,
Dbg,
"List Head -> %08lx\n", ListHead );
04420
04421
04422
04423
04424
04425
04426
if (ClientRecord->
PrevClient ==
LFS_NO_CLIENT) {
04427
04428
DebugTrace( 0,
Dbg,
"Element is first element in the list\n", 0 );
04429 *ListHead = ClientRecord->
NextClient;
04430
04431
04432
04433
04434
04435 }
else {
04436
04437 TempClientRecord = ClientArray + ClientRecord->
PrevClient;
04438 TempClientRecord->
NextClient = ClientRecord->
NextClient;
04439 }
04440
04441
04442
04443
04444
04445
04446
if (ClientRecord->
NextClient !=
LFS_NO_CLIENT) {
04447
04448 TempClientRecord = ClientArray + ClientRecord->
NextClient;
04449 TempClientRecord->
PrevClient = ClientRecord->
PrevClient;
04450 }
04451
04452
DebugTrace( -1,
Dbg,
"LfsRemoveClientFromList: Exit\n", 0 );
04453
04454
return;
04455 }
04456
04457
04458
04459
04460
04461
04462
VOID
04463 LfsAddClientToList (
04464 IN
PLFS_CLIENT_RECORD ClientArray,
04465 IN USHORT ClientIndex,
04466 IN PUSHORT ListHead
04467 )
04468
04469
04470
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490 {
04491
PLFS_CLIENT_RECORD ClientRecord;
04492
PLFS_CLIENT_RECORD TempClientRecord;
04493
04494
PAGED_CODE();
04495
04496
DebugTrace( +1,
Dbg,
"LfsAddClientToList: Entered\n", 0 );
04497
DebugTrace( 0,
Dbg,
"Client Array -> %08lx\n", ClientArray );
04498
DebugTrace( 0,
Dbg,
"Client Index -> %04x\n", ClientIndex );
04499
DebugTrace( 0,
Dbg,
"List Head -> %08lx\n", ListHead );
04500
04501 ClientRecord = ClientArray + ClientIndex;
04502
04503
04504
04505
04506
04507 ClientRecord->
PrevClient =
LFS_NO_CLIENT;
04508
04509
04510
04511
04512
04513 ClientRecord->
NextClient = *ListHead;
04514
04515
04516
04517
04518
04519
04520
if (*ListHead !=
LFS_NO_CLIENT) {
04521
04522 TempClientRecord = ClientArray + *ListHead;
04523 TempClientRecord->
PrevClient = ClientIndex;
04524 }
04525
04526
04527
04528
04529
04530 *ListHead = ClientIndex;
04531
04532
DebugTrace( -1,
Dbg,
"LfsAddClientToList: Exit\n", 0 );
04533
04534
return;
04535 }
04536