00558 :
00559
00560 This routine
is called to flush
the current Lbcbs in on
the Lfcb
00561 work queue. It will flush up to
the I/O which contains
the desired
00562 Lbcb.
00563
00564 Arguments:
00565
00566 Lfcb - This
is the file control block
for the log
file.
00567
00568 Lbcb - This
is the block which
is needed to be flushed to disk.
00569
00570 Return Value:
00571
00572 None.
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 }