test: lfs/registry.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# registry.c File Reference

`#include "lfsprocs.h"`

Go to the source code of this file.

## Defines

#define | Dbg (DEBUG_TRACE_REGISTRY)

## Functions

PLFCB | LfsRestartLogFile (IN PFILE_OBJECT LogFile, IN USHORT MaximumClients, IN ULONG LogPageSize OPTIONAL, IN LONGLONG FileSize, IN OUT PLFS_INFO LfsInfo, OUT PLFS_WRITE_DATA WriteData)
VOID | LfsNormalizeBasicLogFile (IN OUT PLONGLONG FileSize, IN OUT PULONG LogPageSize, IN OUT PUSHORT LogClients, IN BOOLEAN UseDefaultLogPage)
VOID | LfsUpdateLfcbFromPgHeader (IN PLFCB Lfcb, IN ULONG SystemPageSize, IN ULONG LogPageSize, IN SHORT MajorVersion, IN SHORT MinorVersion, IN BOOLEAN PackLog)
VOID | LfsUpdateLfcbFromNoRestart (IN PLFCB Lfcb, IN LONGLONG FileSize, IN LSN LastLsn, IN ULONG LogClients, IN ULONG OpenLogCount, IN BOOLEAN LogFileWrapped, IN BOOLEAN UseMultiplePageIo)
VOID | LfsUpdateLfcbFromRestart (IN PLFCB Lfcb, IN PLFS_RESTART_AREA RestartArea, IN USHORT RestartOffset)
VOID | LfsUpdateRestartAreaFromLfcb (IN PLFCB Lfcb, IN PLFS_RESTART_AREA RestartArea)
VOID | LfsInitializeLogFilePriv (IN PLFCB Lfcb, IN BOOLEAN ForceRestartToDisk, IN ULONG RestartAreaSize, IN LONGLONG StartOffsetForClear, IN BOOLEAN ClearLogFile)
VOID | LfsFindLastLsn (IN OUT PLFCB Lfcb)
BOOLEAN | LfsCheckSubsequentLogPage (IN PLFCB Lfcb, IN PLFS_RECORD_PAGE_HEADER RecordPageHeader, IN LONGLONG LogFileOffset, IN LONGLONG SequenceNumber)
VOID | LfsFlushLogPage (IN PLFCB Lfcb, PVOID LogPage, IN LONGLONG FileOffset, OUT PBCB *Bcb)
VOID | LfsRemoveClientFromList (IN PLFS_CLIENT_RECORD ClientArray, IN PLFS_CLIENT_RECORD ClientRecord, IN PUSHORT ListHead)
VOID | LfsAddClientToList (IN PLFS_CLIENT_RECORD ClientArray, IN USHORT ClientIndex, IN PUSHORT ListHead)
VOID | LfsInitializeLogFile (IN PFILE_OBJECT LogFile, IN USHORT MaximumClients, IN ULONG LogPageSize OPTIONAL, IN LONGLONG FileSize, OUT PLFS_WRITE_DATA WriteData)
ULONG | LfsOpenLogFile (IN PFILE_OBJECT LogFile, IN UNICODE_STRING ClientName, IN USHORT MaximumClients, IN ULONG LogPageSize OPTIONAL, IN LONGLONG FileSize, IN OUT PLFS_INFO LfsInfo, OUT PLFS_LOG_HANDLE LogHandle, OUT PLFS_WRITE_DATA WriteData)
VOID | LfsCloseLogFile (IN LFS_LOG_HANDLE LogHandle)
VOID | LfsDeleteLogHandle (IN LFS_LOG_HANDLE LogHandle)
VOID | LfsReadLogFileInformation (IN LFS_LOG_HANDLE LogHandle, IN PLOG_FILE_INFORMATION Buffer, IN OUT PULONG Length)
BOOLEAN | LfsVerifyLogFile (IN LFS_LOG_HANDLE LogHandle, IN PVOID LogFileHeader, IN ULONG Length)
VOID | LfsResetUndoTotal (IN LFS_LOG_HANDLE LogHandle, IN ULONG NumberRecords, IN LONG ResetTotal)
VOID | LfsUpdateLfcbFromRestart (IN OUT PLFCB Lfcb, IN PLFS_RESTART_AREA RestartArea, IN USHORT RestartOffset)
VOID | LfsRemoveClientFromList (PLFS_CLIENT_RECORD ClientArray, PLFS_CLIENT_RECORD ClientRecord, IN PUSHORT ListHead)

## Define Documentation

#define Dbg (DEBUG_TRACE_REGISTRY)

| Definition at line 28 of file lfs/registry.c.

## Function Documentation

VOID LfsAddClientToList | ( | IN PLFS_CLIENT_RECORD | ClientArray,
|  | IN USHORT | ClientIndex,
|  | IN PUSHORT | ListHead
| ) |

Definition at line 4463 of file lfs/registry.c.

References Dbg, DebugTrace, LFS_NO_CLIENT, _LFS_CLIENT_RECORD::NextClient, PAGED_CODE, and _LFS_CLIENT_RECORD::PrevClient.

Referenced by LfsCloseLogFile(), and LfsOpenLogFile().

    04471                    :
    04472
    04473     This routine is called to add a client record to the start of a list.
    04474
    04475 Arguments:
    04476
    04477     ClientArray - This is the base of the client record.
    04478
    04479     ClientIndex - The index for the record to add.
    04480
    04481     ListHead - A pointer to the beginning of the list.  This points to a
    04482                USHORT which is the value of the first element in the list.
    04483
    04484 Return Value:
    04485
    04486     None.
    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     //  This element will become the first element on the list.
    04505     //
    04506
    04507     ClientRecord->PrevClient = LFS_NO_CLIENT;
    04508
    04509     //
    04510     //  The next element for this record is the previous head of the list.
    04511     //
    04512
    04513     ClientRecord->NextClient = *ListHead;
    04514
    04515     //
    04516     //  If there is at least one element currently on the list, we point
    04517     //  the first element to this new record.
    04518     //
    04519
    04520     if (*ListHead != LFS_NO_CLIENT) {
    04521
    04522         TempClientRecord = ClientArray + *ListHead;
    04523         TempClientRecord->PrevClient = ClientIndex;
    04524     }
    04525
    04526     //
    04527     //  This index is now the head of the list.
    04528     //
    04529
    04530     *ListHead = ClientIndex;
    04531
    04532     DebugTrace( -1, Dbg, "LfsAddClientToList:  Exit\n", 0 );
    04533
    04534     return;
    04535 }

BOOLEAN LfsCheckSubsequentLogPage | ( | IN PLFCB | Lfcb,
|  | IN PLFS_RECORD_PAGE_HEADER | RecordPageHeader,
|  | IN LONGLONG | LogFileOffset,
|  | IN LONGLONG | SequenceNumber
| ) |

Definition at line 4188 of file lfs/registry.c.

References Dbg, DebugTrace, FALSE, LFS_SIGNATURE_UNINITIALIZED_ULONG, LfsLsnToSeqNumber, LfsTruncateLsnToLogPage, LSN, PAGED_CODE, and TRUE.

Referenced by LfsFindLastLsn().

    04197                    :
    04198
    04199     This routine is called to check that a particular log page could not
    04200     have been written after a prior Io transfer.  What we are looking for
    04201     is the start of a transfer which was written after an Io which we
    04202     we cannot read from during restart.  The presence of an additional
    04203     Io means that we cannot guarantee that we can recover all of the
    04204     restart data for the disk.  This makes the disk unrecoverable.
    04205
    04206     We are given the sequence number of the Lsn that would occur on this page
    04207     (if it is not part of an Log record which spans the end of a file).
    04208     If we haven't wrapped the file and find an Lsn whose
    04209     sequence number matches this, then we have an error.  If we have
    04210     wrapped the file, and the sequence number in the Lsn in the
    04211     first log page is
    04212     written subsequent to a previous failing Io.
    04213
    04214 Arguments:
    04215
    04216     Lfcb - Log file control block for this log file.
    04217
    04218     RecordPageHeader - This is the header of a log page to check.
    04219
    04220     LogFileOffset - This is the offset in the log file of this page.
    04221
    04222     SequenceNumber - This is the sequence number that this log page should
    04223                      not have.  This will be the sequence number for
    04224                      any log records which begin on this page if written
    04225                      after the page that failed.
    04226
    04227 Return Value:
    04228
    04229     BOOLEAN - TRUE if this log page was written after some previous page,
    04230               FALSE otherwise.
    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     //  If the page header is either 0 or -1 then we say this page was not written
    04254     //  after some previous page.
    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     //  If the last Lsn on the page occurs was
    04266     //  written after the page that caused the original error.  Then we
    04267     //  have a fatal error.
    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     //  If the sequence number for the Lsn in the page is equal or greater than
    04279     //  Lsn we expect, then this is a subsequent write.
    04280     //
    04281
    04282     if ( LsnSeqNumber >= SequenceNumber ) {
    04283
    04284         IsSubsequent = TRUE;
    04285
    04286     //
    04287     //  If this page is the start of the file and the sequence number is 1 less
    04288     //  than we expect and the Lsn indicates that we wrapped the file, then it
    04289     //  is also part of a subsequent io.
    04290     //
    04291     //  The following test checks
    04292     //
    04293     //      1 - The sequence number for the Lsn is from the previous pass
    04294     //          through the file.
    04295     //      2 - We are at the first page in the file.
    04296     //      3 - The log record didn't begin on the current page.
    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 }

VOID LfsCloseLogFile | ( | IN LFS_LOG_HANDLE | LogHandle | ) |

Definition at line 706 of file lfs/registry.c.

References _LBCB::ActiveLinks, Add2Ptr, CcUnpinDataForThread(), ClearFlag, _LFCB::ClientArray, _LCH::ClientArrayByteOffset, _LFS_RESTART_AREA::ClientFreeList, _LCH::ClientId, _LFS_CLIENT_ID::ClientIndex, _LFS_RESTART_AREA::ClientInUseList, _LFS_CLIENT_RECORD::ClientRestartLsn, Dbg, DebugTrace, DebugUnwind, _LFCB_SYNC::Event, Executive, FALSE, FlagOn, _LFCB::Flags, KernelMode, KeWaitForSingleObject(), LBCB_NOT_EMPTY, LBCB_ON_ACTIVE_QUEUE, _LFCB::LbcbActive, _LBCB::LbcbFlags, _LFCB::LbcbWorkque, _LCH::LchLinks, _LCH::Lfcb, LFCB_FINAL_SHUTDOWN, _LFCB::LfcbLinks, LFS_NO_CLIENT, LfsAcquireLch, LfsAcquireLfcb, LfsAcquireLfsData, LfsAddClientToList(), LfsCloseLogFile(), LfsDeallocateLbcb(), LfsDeallocateLfcb(), LfsExceptionFilter(), _LFCB::LfsIoState, LfsLbcbIsRestart, LfsNoIoInProgress, LfsReleaseLch, LfsReleaseLfcb, LfsReleaseLfsData, LfsRemoveClientFromList(), LfsValidateClientId, LfsValidateLch, LfsWriteLfsRestart(), LfsZeroLsn, _LBCB::LogPageBcb, NTSTATUS(), NULL, PAGED_CODE, _LBCB::ResourceThread, _LFCB::RestartArea, _LFCB::RestartAreaSize, _LFS_CLIENT_RECORD::SeqNumber, SetFlag, Status, _LFCB::Sync, TRUE, try_return, USHORT, _LFCB::Waiters, and _LBCB::WorkqueLinks.

Referenced by LfsCloseLogFile().

    00712                    :
    00713
    00714     This routine is called when a client detaches itself from the log
    00715     file.  On return, all prior references to this client in the log
    00716     file are inaccessible.
    00717
    00718 Arguments:
    00719
    00720     LogHandle - Pointer to private Lfs structure used to identify this
    00721                 client.
    00722
    00723 Return Value:
    00724
    00725     None
    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     //  Enclose this in a loop.  We will loop as long as there are waiters or there is an IO
    00751     //  in progress.
    00752     //
    00753
    00754     while (TRUE) {
    00755
    00756         //
    00757         //  Always assume we exit the loop.
    00758         //
    00759
    00760         ExitLoop = TRUE;
    00761
    00762         //
    00763         //  Check that the structure is a valid log handle structure.
    00764         //
    00765
    00766         LfsValidateLch( Lch );
    00767
    00768         //
    00769         //  Protect this entry point with a try-except.
    00770         //
    00771
    00772         try {
    00773
    00774             //
    00775             //  Use a try-finally to facilitate cleanup.
    00776             //
    00777
    00778             //
    00779             //  Acquire the global data block and the log file control block.
    00780             //
    00781
    00782             LfsAcquireLfsData();
    00783
    00784             try {
    00785
    00786                 PLBCB ThisLbcb;
    00787
    00788                 LfsAcquireLch( Lch );
    00789
    00790                 Lfcb = Lch->Lfcb;
    00791
    00792                 //
    00793                 //  If the Log file has been closed then return immediately.
    00794                 //
    00795
    00796                 if (Lfcb == NULL) {
    00797
    00798                     try_return( NOTHING );
    00799                 }
    00800
    00801                 //
    00802                 //  Check that there are no waiters or IO in progress before proceeding.
    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                 //  Check that the client Id is valid.
    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                 //  Increment the client sequence number in the restart area.
    00826                 //  This will prevent anyone else from accessing this client block.
    00827                 //
    00828
    00829                 ClientIndex = Lch->ClientId.ClientIndex;
    00830
    00831                 ClientRecord->SeqNumber++;
    00832 #endif
    00833
    00834                 //
    00835                 //  Remember if this client wrote a restart area.
    00836                 //
    00837
    00838                 FlushRestart = (BOOLEAN) ( LfsZeroLsn.QuadPart != ClientRecord->ClientRestartLsn.QuadPart );
    00839
    00840 #if 1
    00841                 //
    00842                 //  Remove the client from the log file in use list.
    00843                 //
    00844
    00845                 LfsRemoveClientFromList( Lfcb->ClientArray,
    00846                                          ClientRecord,
    00847                                          &Lfcb->RestartArea->ClientInUseList );
    00848
    00849                 //
    00850                 //  Add the client block to the log file free list
    00851                 //
    00852
    00853                 LfsAddClientToList( Lfcb->ClientArray,
    00854                                     ClientIndex,
    00855                                     &Lfcb->RestartArea->ClientFreeList );
    00856
    00857                 //
    00858                 //  If this is the last client then move the last active Lbcb off
    00859                 //  the active queue.
    00860                 //
    00861
    00862                 if (Lfcb->RestartArea->ClientInUseList == LFS_NO_CLIENT) {
    00863 #endif
    00864                     //
    00865                     //  Set the flag to indicate we are at the final close.
    00866                     //
    00867
    00868                     SetFlag( Lfcb->Flags, LFCB_FINAL_SHUTDOWN );
    00869
    00870                     //
    00871                     //  Walk through the active queue and remove any Lbcb's with
    00872                     //  data from that queue.  That will allow them to get out to disk.
    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                         //  If this page has some new entries, allow it to
    00886                         //  be flushed to disk.  Otherwise deallocate it.
    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                     //  It's possible that we have the two restart areas in the workque.
    00905                     //  They can be removed and the memory deallocated if we have no
    00906                     //  more clients.
    00907                     //
    00908                     //  We skip this action if the there is Io in progress or the user
    00909                     //  had a restart area.
    00910                     //
    00911
    00912                     if ((Lfcb->LfsIoState == LfsNoIoInProgress) && !FlushRestart) {
    00913
    00914                         PLIST_ENTRY Links;
    00915
    00916                         //
    00917                         //  Now walk through the workque list looking for a non-restart
    00918                         //  entry.
    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                             //  If this is not a restart area, we exit and remember that
    00931                             //  we need to flush the restart areas.
    00932                             //
    00933
    00934                             if (!LfsLbcbIsRestart( ThisLbcb )) {
    00935
    00936                                 FlushRestart = TRUE;
    00937                                 break;
    00938                             }
    00939
    00940                             Links = Links->Flink;
    00941                         }
    00942
    00943                         //
    00944                         //  If we are still not to flush the restart areas remove
    00945                         //  all of the restart areas from the queue.
    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                 //  We will have to flush the restart area in this case.
    00969                 //
    00970
    00971                 } else {
    00972
    00973                     FlushRestart = TRUE;
    00974                 }
    00975 #endif
    00976
    00977                 //
    00978                 //  Flush the new restart area if we need to.
    00979                 //
    00980
    00981                 if (FlushRestart) {
    00982
    00983                     LfsWriteLfsRestart( Lfcb, Lfcb->RestartAreaSize, FALSE );
    00984                     LfsWriteLfsRestart( Lfcb, Lfcb->RestartAreaSize, TRUE );
    00985                 }
    00986
    00987                 //
    00988                 //  Clear the Lfcb pointer in the client handle.
    00989                 //
    00990
    00991                 Lch->Lfcb = NULL;
    00992                 RemoveEntryList( &Lch->LchLinks );
    00993
    00994                 //
    00995                 //  If there are no active clients, we can remove this log file
    00996                 //  control block from the active queue.
    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                 //   Release the log file control block if held.
    01016                 //
    01017
    01018                 LfsReleaseLch( Lch );
    01019
    01020                 //
    01021                 //  Release the global data block if held.
    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         //  Test if we want to exit the loop now.
    01036         //
    01037
    01038         if (ExitLoop) { break; }
    01039
    01040         //
    01041         //  Wait for the io to complete.
    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     //  We always let this operation succeed.
    01057     //
    01058
    01059     return;
    01060 }

VOID LfsDeleteLogHandle | ( | IN LFS_LOG_HANDLE | LogHandle | ) |

Definition at line 1063 of file lfs/registry.c.

References ExDeleteResource, ExFreePool(), LFS_NTC_LCH, LfsAcquireLch, LfsDeallocateLch, LfsExceptionFilter(), LfsReleaseLch, _LCH::NodeTypeCode, NULL, PAGED_CODE, _LFCB_SYNC::Resource, _LCH::Sync, and _LFCB_SYNC::UserCount.

    01069                    :
    01070
    01071     This routine is called when a client is tearing down the last of
    01072     his volume structures.  There will be no more references to this
    01073     handle.  If it is the last handle for the log file then we will
    01074     deallocate the Sync structure as well.
    01075
    01076 Arguments:
    01077
    01078     LogHandle - Pointer to private Lfs structure used to identify this
    01079                 client.
    01080
    01081 Return Value:
    01082
    01083     None
    01084
    01085 --*/
    01086
    01087 {
    01088     PLCH Lch;
    01089
    01090     PAGED_CODE();
    01091
    01092     //
    01093     //  If the log handle is null then return immediately.
    01094     //
    01095
    01096     Lch = (PLCH) LogHandle;
    01097
    01098     if ((Lch == NULL) ||
    01099         (Lch->NodeTypeCode != LFS_NTC_LCH)) {
    01100
    01101         return;
    01102     }
    01103
    01104     //
    01105     //  Ignore all errors from now on.
    01106     //
    01107
    01108     try {
    01109
    01110         LfsAcquireLch( Lch );
    01111
    01112         Lch->Sync->UserCount -= 1;
    01113
    01114         //
    01115         //  If we are the last user then deallocate the sync structure.
    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 }

VOID LfsFindLastLsn | ( | IN OUT PLFCB | Lfcb | ) |

Definition at line 3193 of file lfs/registry.c.

References CcUnpinData(), ClearFlag, _LFS_RECORD_PAGE_HEADER::Copy, Dbg, DebugTrace, DebugUnwind, ExRaiseStatus(), FALSE, FlagOn, _LFS_RECORD_PAGE_HEADER::Header, LFCB_LOG_WRAPPED, LFCB_NO_LAST_LSN, LFCB_PACK_LOG, LFCB_REUSE_TAIL, LFS_SIGNATURE_BAD_USA_ULONG, LFS_SIGNATURE_RECORD_PAGE_ULONG, LfsCheckSubsequentLogPage(), LfsFindLastLsn(), LfsFlushLogPage(), LfsLi0, LfsLsnToSeqNumber, LfsNextLogPageOffset(), LfsPinOrMapData(), LOG_PAGE_LOG_RECORD_END, LSN, _LFS_RECORD_PAGE_HEADER::MultiSectorHeader, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, RESTART_SINGLE_PAGE_IO, SetFlag, _MULTI_SECTOR_HEADER::Signature, Status, TRUE, and USHORT.

Referenced by LfsFindLastLsn(), and LfsRestartLogFile().

    03199                    :
    03200
    03201     This routine walks through the log pages for a file, searching for the
    03202     last log page written to the file.  It updates the Lfcb and the current
    03203     restart area as well.
    03204
    03205     We proceed in the following manner.
    03206
    03207         1 - Walk through and find all of the log pages successfully
    03208             flushed to disk.  This search terminates when either we find
    03209             an error or when we find a previous page on the disk.
    03210
    03211         2 - For the error case above, we want to insure that the error found
    03212             was due to a system crash and that there are no complete I/O
    03213             transfers after the bad region.
    03214
    03215         3 - We will look at the 2 pages with the tail copies if the log file
    03216             is packed to check on pages with errors.
    03217
    03218     At the end of this routine we will repair the log file by copying the tail
    03219     copies back to their correct location in the log file.
    03220
    03221 Arguments:
    03222
    03223     Lfcb - Log file control block for this log file.
    03224
    03225 Return Value:
    03226
    03227     None.
    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     //  The page count and page position are from the last page
    03281     //  sucessfully read.  Initialize these to indicate the
    03282     //  'previous' transfer was complete.
    03283     //
    03284
    03285     PageCount = 1;
    03286     PagePosition = 1;
    03287
    03288     //
    03289     //  We have the current Lsn in the restart area.  This is the last
    03290     //  Lsn on a log page.  We compute the next file offset and sequence
    03291     //  number.
    03292     //
    03293
    03294     CurrentLogPageOffset = Lfcb->NextLogPage;
    03295
    03296     //
    03297     //  If the next log page is the first log page in the file and
    03298     //  the last Lsn represented a log record, then remember that we
    03299     //  have wrapped in the log file.
    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     //  If we are going to try to reuse the tail of the last known
    03315     //  page, then remember the last Lsn on this page.
    03316     //
    03317
    03318     if (FlagOn( Lfcb->Flags, LFCB_REUSE_TAIL )) {
    03319
    03320         LastKnownLsn = Lfcb->LastFlushedLsn;
    03321
    03322         //
    03323         //  There are some special conditions allowed for this page when
    03324         //  we read it.  It could be either the first or last of the transfer.
    03325         //  It may also have a tail copy.
    03326         //
    03327
    03328         InitialReusePage = TRUE;
    03329
    03330     } else {
    03331
    03332         LastKnownLsn = LfsLi0;
    03333     }
    03334
    03335     //
    03336     //  Use a try-finally to facilitate cleanup.
    03337     //
    03338
    03339     try {
    03340
    03341         //
    03342         //  If this is a packed log file, let's pin the two tail copy pages.
    03343         //
    03344
    03345         if (FlagOn( Lfcb->Flags, LFCB_PACK_LOG )) {
    03346
    03347             //
    03348             //  Start with the second page.
    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                 //  If this isn't a valid page then ignore it.
    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             //  Now try the first.
    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                 //  If this isn't a valid page then ignore it.
    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         //  We continue walking through the file, log page by log page looking
    03424         //  for the end of the data transferred.  The loop below looks for
    03425         //  a log page which contains the end of a log record.  Each time a
    03426         //  log record is successfully read from the disk, we update our in-memory
    03427         //  structures to reflect this.  We exit this loop when we are at a point
    03428         //  where we don't want to find any subsequent pages.  This occurs when
    03429         //
    03430         //      - we get an I/O error reading a page
    03431         //      - we get a Usa error reading a page
    03432         //      - we have a tail copy with more recent data than contained on the page
    03433         //
    03434
    03435         while (TRUE) {
    03436
    03437             LONGLONG ActualSeqNumber;
    03438             TailPage = NULL;
    03439
    03440             //
    03441             //  Pin the next log page, allowing errors.
    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             //  Compute the next log page offset in the file.
    03456             //
    03457
    03458             LfsNextLogPageOffset( Lfcb,
    03459                                   CurrentLogPageOffset,
    03460                                   &NextLogPageOffset,
    03461                                   &Wrapped );
    03462
    03463             //
    03464             //  If we are at the expected first page of a transfer
    03465             //  check to see if either tail copy is at this offset.
    03466             //  If this page is the last page of a transfer, check
    03467             //  if we wrote a subsequent tail copy.
    03468             //
    03469
    03470             if (FlagOn( Lfcb->Flags, LFCB_PACK_LOG ) &&
    03471                 ((PageCount == PagePosition) ||
    03472                  (PageCount == PagePosition + 1))) {
    03473
    03474                 //
    03475                 //  Check if the offset matches either the first or second
    03476                 //  tail copy.  It is possible it will match both.
    03477                 //
    03478
    03479                 if (CurrentLogPageOffset == FirstTailOffset) {
    03480
    03481                     TailPage = FirstTailPage;
    03482                 }
    03483
    03484                 if (CurrentLogPageOffset == SecondTailOffset) {
    03485
    03486                     //
    03487                     //  If we already matched on the first page then
    03488                     //  check the ending Lsn's.
    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                 //  If we have a candidate for a tail copy, check and see if it is
    03501                 //  in the expected pass through the file.  For that to be true we
    03502                 //  must be at the first page of an I/O block. Also the last Lsn on the
    03503                 //  copy page must match the last known flushed Lsn or the sequence
    03504                 //  number on the page must be the expected sequence number.
    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                         //  If the sequence number is not expected, then don't use the tail
    03515                         //  copy.
    03516                         //
    03517
    03518                         if (ExpectedSeqNumber != ActualSeqNumber) {
    03519
    03520                             TailPage = NULL;
    03521                         }
    03522
    03523                     //
    03524                     //  If the last Lsn is greater than the one on this page
    03525                     //  then forget this tail.
    03526                     //
    03527
    03528                     } else if (LastKnownLsn.QuadPart > TailPage->Header.Packed.LastEndLsn.QuadPart) {
    03529
    03530                         TailPage = NULL;
    03531                     }
    03532                 }
    03533             }
    03534
    03535             //
    03536             //  If we have an error on the current page, we will break out of
    03537             //  this loop.
    03538             //
    03539
    03540             if (!NT_SUCCESS( Status ) || UsaError) {
    03541
    03542                 break;
    03543             }
    03544
    03545             //
    03546             //  If the last Lsn on this page doesn't match the previous
    03547             //  known last Lsn or the sequence number is not expected
    03548             //  we are done.
    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             //  Check that the page position and page count values are correct.
    03562             //  If this is the first page of a transfer the position must be
    03563             //  1 and the count will be unknown.
    03564             //
    03565
    03566             if (PageCount == PagePosition) {
    03567
    03568                 //
    03569                 //  If the current page is the first page we are looking at
    03570                 //  and we are reusing this page then it can be either the
    03571                 //  first or last page of a transfer.  Otherwise it can only
    03572                 //  be the first.
    03573                 //
    03574
    03575                 if ((LogPageHeader->PagePosition != 1) &&
    03576                     (!InitialReusePage ||
    03577                      (LogPageHeader->PagePosition != LogPageHeader->PageCount))) {
    03578
    03579                     break;
    03580                 }
    03581
    03582             //
    03583             //  The page position better be 1 more than the last page position
    03584             //  and the page count better match.
    03585             //
    03586
    03587             } else if ((LogPageHeader->PageCount != PageCount) ||
    03588                        (LogPageHeader->PagePosition != PagePosition + 1)) {
    03589
    03590                 break;
    03591             }
    03592
    03593             //
    03594             //  We have a valid page in the file and may have a valid page in
    03595             //  the tail copy area.  If the tail page was written after
    03596             //  the page in the file then break out of the loop.
    03597             //
    03598
    03599             if (TailPage &&
    03600                 (TailPage->Header.Packed.LastEndLsn.QuadPart >= LogPageHeader->Copy.LastLsn.QuadPart)) {
    03601
    03602                 //
    03603                 //  Remember if we will replace the page.
    03604                 //
    03605
    03606                 ReplacePage = TRUE;
    03607                 break;
    03608             }
    03609
    03610             TailPage = NULL;
    03611
    03612             //
    03613             //  The log page is expected.  If this contains the end of
    03614             //  some log record we can update some fields in the Lfcb.
    03615             //
    03616
    03617             if (FlagOn( LogPageHeader->Flags, LOG_PAGE_LOG_RECORD_END )) {
    03618
    03619                 //
    03620                 //  Since we have read this page we know the Lfcb sequence
    03621                 //  number is the same as our expected value.  We also
    03622                 //  assume we will not reuse the tail.
    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                     //  If there is room on this page for another header then
    03634                     //  remember we want to reuse the page.
    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                 //  If we may try to reuse the current page then use
    03655                 //  that as the next page offset.  Otherwise move to the
    03656                 //  next page in the file.
    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                 //  If we wrapped the log file, then we set the bit indicating so.
    03670                 //
    03671
    03672                 if (WrappedLogFile) {
    03673
    03674                     SetFlag( Lfcb->Flags, LFCB_LOG_WRAPPED );
    03675                 }
    03676             }
    03677
    03678             //
    03679             //  Remember the last page count and position.  Also remember
    03680             //  the last known lsn.
    03681             //
    03682
    03683             PageCount = LogPageHeader->PageCount;
    03684             PagePosition = LogPageHeader->PagePosition;
    03685             LastKnownLsn = LogPageHeader->Copy.LastLsn;
    03686
    03687             //
    03688             //  If we are wrapping to the beginning of the file then update
    03689             //  the expected sequence number.
    03690             //
    03691
    03692             if (Wrapped) {
    03693
    03694                 ExpectedSeqNumber = ExpectedSeqNumber + 1;
    03695                 WrappedLogFile = TRUE;
    03696             }
    03697
    03698             CurrentLogPageOffset = NextLogPageOffset;
    03699
    03700             //
    03701             //  Unpin the last log page pinned.
    03702             //
    03703
    03704             CcUnpinData( LogPageHeaderBcb );
    03705             LogPageHeaderBcb = NULL;
    03706
    03707             InitialReusePage = FALSE;
    03708         }
    03709
    03710         //
    03711         //  At this point we expect that there will be no more new pages in
    03712         //  the log file.  We could have had an error of some sort on the most recent
    03713         //  page or we may have found a tail copy for the current page.
    03714         //  If the error occurred on the last Io to the file then
    03715         //  this log file is useful.  Otherwise the log file can't be used.
    03716         //
    03717
    03718         //
    03719         //  If we have a tail copy page then update the values in the
    03720         //  Lfcb and restart area.
    03721         //
    03722
    03723         if (TailPage != NULL) {
    03724
    03725             //
    03726             //  Since we have read this page we know the Lfcb sequence
    03727             //  number is the same as our expected value.
    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             //  If there is room on this page for another header then
    03740             //  remember we want to reuse the page.
    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             //  If we wrapped the log file, then we set the bit indicating so.
    03758             //
    03759
    03760             if (WrappedLogFile) {
    03761
    03762                 SetFlag( Lfcb->Flags, LFCB_LOG_WRAPPED );
    03763             }
    03764         }
    03765
    03766         //
    03767         //  Remember that the partial IO will start at the next page.
    03768         //
    03769
    03770         FirstPartialIo = NextLogPageOffset;
    03771
    03772         //
    03773         //  If the next page is the first page of the file then update
    03774         //  the sequence number for log records which begin on the next
    03775         //  page.
    03776         //
    03777
    03778         if (Wrapped) {
    03779
    03780             ExpectedSeqNumber = ExpectedSeqNumber + 1;
    03781         }
    03782
    03783         //
    03784         //  If we know the length of the transfer containing the page we stopped
    03785         //  on we can just go to the page following the transfer and check
    03786         //  the sequence number.  If we replaced the page then we have already
    03787         //  modified the numbers.  If we know that only single pages were written
    03788         //  to disk then we will munge the numbers now.  If we were in the
    03789         //  middle of a multi-page I/O then the numbers are already set up.
    03790         //
    03791
    03792         //
    03793         //  If we have a tail copy or are performing single page I/O
    03794         //  we can immediately look at the next page.
    03795         //
    03796
    03797         if (ReplacePage ||
    03798             FlagOn( Lfcb->RestartArea->Flags, RESTART_SINGLE_PAGE_IO )) {
    03799
    03800             //
    03801             //  Fudge the counts to show that we don't need swallow any pages.
    03802             //
    03803
    03804             PageCount = 2;
    03805             PagePosition = 1;
    03806
    03807         //
    03808         //  If the counts match it means the current page should be the first
    03809         //  page of a transfer.  We need to walk forward enough to guarantee
    03810         //  that there was no subsequent transfer that made it out to disk.
    03811         //
    03812
    03813         } else if (PagePosition == PageCount) {
    03814
    03815             USHORT CurrentPosition;
    03816
    03817             //
    03818             //  If the next page causes us to wrap to the beginning of the log
    03819             //  file then we know which page to check next.
    03820             //
    03821
    03822             if (Wrapped) {
    03823
    03824                 //
    03825                 //  Fudge the counts to show that we don't need swallow any pages.
    03826                 //
    03827
    03828                 PageCount = 2;
    03829                 PagePosition = 1;
    03830
    03831             //
    03832             //  Walk forward looking for a page which is from a different IO transfer
    03833             //  from the page we failed on.
    03834             //
    03835
    03836             } else {
    03837
    03838                 //
    03839                 //  We need to find a log page we know is not part of the log
    03840                 //  page which caused the original error.
    03841                 //
    03842                 //  Maintain the count within the current transfer.
    03843                 //
    03844
    03845                 CurrentPosition = 2;
    03846
    03847                 do {
    03848
    03849                     //
    03850                     //  We walk through the file, reading log pages.  If we find
    03851                     //  a readable log page that must lie in a subsequent Io block,
    03852                     //  we exit.
    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                     //  If we get a USA error then assume that we correctly
    03873                     //  found the end of the original transfer.
    03874                     //
    03875
    03876                     if (UsaError) {
    03877
    03878                         ValidFile = TRUE;
    03879                         break;
    03880
    03881                     //
    03882                     //  If we were able to read the page, we examine it to see
    03883                     //  if it is in the same or different Io block.
    03884                     //
    03885
    03886                     } else if (NT_SUCCESS( Status )) {
    03887
    03888                         //
    03889                         //  If this page is part of the error causing I/O, we will
    03890                         //  use the transfer length to determine the page to
    03891                         //  read for a subsequent error.
    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                         //  We found know the Io causing the error didn't
    03907                         //  complete.  So we have no more checks to do.
    03908                         //
    03909
    03910                         } else {
    03911
    03912                             ValidFile = TRUE;
    03913                             break;
    03914                         }
    03915
    03916                     //
    03917                     //  Try the next page.
    03918                     //
    03919
    03920                     } else {
    03921
    03922                         //
    03923                         //  Move to the next log page.
    03924                         //
    03925
    03926                         LfsNextLogPageOffset( Lfcb,
    03927                                               NextLogPageOffset,
    03928                                               &NextLogPageOffset,
    03929                                               &Wrapped );
    03930
    03931                         //
    03932                         //  If the file wrapped then initialize the page count
    03933                         //  and position so that we will not skip over any
    03934                         //  pages in the final verification below.
    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                     //  This is one more page we will want to uninitialize.
    03950                     //
    03951
    03952                     PartialIoCount += 1;
    03953
    03954                 } while( !Wrapped );
    03955             }
    03956         }
    03957
    03958         //
    03959         //  If we are unsure whether the file is valid then we will have
    03960         //  the count and position in the current transfer.  We will walk through
    03961         //  this transfer and read the subsequent page.
    03962         //
    03963
    03964         if (!ValidFile) {
    03965
    03966             ULONG RemainingPages;
    03967
    03968             //
    03969             //  Skip over the remaining pages in this transfer.
    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             //  Call our routine to check this log page.
    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         //  Make sure the current page is unpinned.
    04027         //
    04028
    04029         if (LogPageHeaderBcb != NULL) {
    04030
    04031             CcUnpinData( LogPageHeaderBcb );
    04032             LogPageHeaderBcb = NULL;
    04033         }
    04034
    04035         //
    04036         //  We have a valid file.  The Lfcb is initialized to the point where
    04037         //  the last log record was found.  We possibly have a copy of the
    04038         //  last page in the log file stored as a copy.  Or we could just have
    04039         //  a page that we would like to reuse the end of.
    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             //  We will pin the correct page and copy the data from this
    04050             //  page into it.  We will then flush it out to disk.
    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             //  Fill in last flushed lsn value flush the page.
    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         //  We also want to write over any partial I/O so it doesn't cause
    04081         //  us problems on a subsequent restart.  We have the starting offset
    04082         //  and the number of blocks.  We will simply write a Baad signature into
    04083         //  each of these pages.  Any subsequent reads will have a Usa error.
    04084         //
    04085
    04086         while (PartialIoCount--) {
    04087
    04088             //
    04089             //  Make sure the current page is unpinned.
    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                 //  Just store a the usa array header in the multi-section
    04110                 //  header.
    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         //  We used to invalidate any tail pages we reused, now we let them
    04129         //  be recopied every restart even if we fail a little later
    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         //  Unpin the tail pages is pinned.
    04150         //
    04151
    04152         if (SecondTailPageBcb != NULL) {
    04153
    04154             CcUnpinData( SecondTailPageBcb );
    04155         }
    04156
    04157         if (FirstTailPageBcb != NULL) {
    04158
    04159             CcUnpinData( FirstTailPageBcb );
    04160         }
    04161
    04162         //
    04163         //  Unpin the log page header if neccessary.
    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 }

VOID LfsFlushLogPage | ( | IN PLFCB | Lfcb,
|  | PVOID | LogPage,
|  | IN LONGLONG | FileOffset,
|  | OUT PBCB * | Bcb
| ) |

Definition at line 4321 of file lfs/registry.c.

References CcFlushCache(), CcSetDirtyPinnedData(), CcUnpinData(), NULL, and PAGED_CODE.

Referenced by LfsFindLastLsn(), and LfsInitializeLogFilePriv().

    04330                    :
    04331
    04332     This routine is called to write a single log page to the log file.  We will
    04333     mark it dirty in the cache, unpin it and call our flush routine.
    04334
    04335 Arguments:
    04336
    04337     Lfcb - Log file control block for this log file.
    04338
    04339     LogPage - Pointer to the log page in the cache.
    04340
    04341     FileOffset - Offset of the page in the stream.
    04342
    04343     Bcb - Address of the Bcb pointer for the cache.
    04344
    04345 Return Value:
    04346
    04347     None
    04348
    04349 --*/
    04350
    04351 {
    04352     PAGED_CODE();
    04353
    04354     //
    04355     //  Set the page dirty and unpin it.
    04356     //
    04357
    04358     CcSetDirtyPinnedData( *Bcb, NULL );
    04359     CcUnpinData( *Bcb );
    04360     *Bcb = NULL;
    04361
    04362     //
    04363     //  Now flush the data.
    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 }

VOID LfsInitializeLogFile | ( | IN PFILE_OBJECT | LogFile,
|  | IN USHORT | MaximumClients,
|  | IN ULONG LogPageSize | OPTIONAL,
|  | IN LONGLONG | FileSize,
|  | OUT PLFS_WRITE_DATA | WriteData
| ) |

Definition at line 150 of file lfs/registry.c.

References Add2Ptr, CcSetAdditionalCacheAttributes(), _LFCB::ClientArray, _LFCB::ClientArrayOffset, Dbg, DebugTrace, DebugUnwind, ExRaiseStatus(), FALSE, _LFCB::FileObject, _LFCB::FirstLogPage, _LFCB::InitialRestartArea, KeQuerySystemTime(), _LFCB::LfcbLinks, _LFS_DATA::LfcbLinks, LFS_DEFAULT_LOG_PAGE_SIZE, LfsAcquireLfcb, LfsAcquireLfsData, LfsAllocateLfcb(), LfsAllocateRestartArea, LfsData, LfsDeallocateLfcb(), LfsDeallocateRestartArea, LfsExceptionFilter(), LfsInitializeLogFile(), LfsInitializeLogFilePriv(), LfsLi0, LfsNormalizeBasicLogFile(), LfsReleaseLfcb, LfsReleaseLfsData, _LFS_WRITE_DATA::LfsStructureSize, LfsUpdateLfcbFromNoRestart(), LfsUpdateLfcbFromPgHeader(), LfsUpdateRestartAreaFromLfcb(), NTSTATUS(), NULL, PAGE_SIZE, PAGED_CODE, _LFCB::RestartArea, _LFCB::RestartDataSize, Status, TRUE, and _LFCB::UserWriteData.

Referenced by LfsInitializeLogFile().

    00160                    :
    00161
    00162     This routine is called to initialize a log file to prepare it for use
    00163     by log clients.  Any previous data in the file will be overwritten.
    00164
    00165     Lfs will partition the file into 2 Lfs restart areas and as many log
    00166     pages as will fit in the file.  The restart area size is determined
    00167     by computing the amount of space needed for the maximum number
    00168
    00169 Arguments:
    00170
    00171     LogFile - This is the file object for the file to be used as a log file.
    00172
    00173     MaximumClients - This is the maximum number of clients that will be
    00174                      active in the log file at any one time.
    00175
    00176     LogPageSize - If specified (not 0), this is the recommended size of
    00177                   the log page.  Lfs will use this as a guide in
    00178                   determining the log page size.
    00179
    00180     FileSize - This is the available size of the log file.
    00181
    00182     WriteData - Pointer to WRITE_DATA in caller's data structure.
    00183
    00184 Return Value:
    00185
    00186     None
    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     //  Protect this entry point with a try-except.
    00211     //
    00212
    00213     try {
    00214
    00215         //
    00216         //  We grab the global data exclusively.
    00217         //
    00218
    00219         LfsAcquireLfsData();
    00220
    00221         //
    00222         //  Use a try-finally to facilitate cleanup.
    00223         //
    00224
    00225         try {
    00226
    00227             //
    00228             //  We allocate an Lfcb and point it to the log file.
    00229             //
    00230
    00231             Lfcb = LfsAllocateLfcb();
    00232
    00233             LfsAcquireLfcb( Lfcb );
    00234
    00235             Lfcb->FileObject = LogFile;
    00236
    00237             //
    00238             //  Call the Cache Manager to disable read ahead and write behind;
    00239             //  we flush the log file explicitly.
    00240             //
    00241
    00242             CcSetAdditionalCacheAttributes( LogFile, TRUE, TRUE );
    00243
    00244             //
    00245             //  Normalize the values passed in with this call.
    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             //  We can go directly to version 1.1 since we can immediately pack
    00256             //  the log file and use the default system log page size.
    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             //  Now update the caller's WRITE_DATA structure.
    00288             //
    00289
    00290             Lfcb->UserWriteData = WriteData;
    00291             WriteData->LfsStructureSize = LogPageSize;
    00292             WriteData->Lfcb = Lfcb;
    00293
    00294             //
    00295             //  Force two restart areas to disk and reinitialize the file.
    00296             //
    00297
    00298             LfsInitializeLogFilePriv( Lfcb,
    00299                                       TRUE,
    00300                                       Lfcb->RestartDataSize,
    00301                                       Lfcb->FirstLogPage,
    00302                                       TRUE );
    00303
    00304             //
    00305             //  Put the Lfcb into the global queue.
    00306             //
    00307
    00308             InsertHeadList( &LfsData.LfcbLinks, &Lfcb->LfcbLinks );
    00309
    00310         } finally {
    00311
    00312             DebugUnwind( LfsInitializeLogFile );
    00313
    00314             //
    00315             //  If the Lfcb has been acquired, we release it now.
    00316             //
    00317
    00318             if (Lfcb != NULL) {
    00319
    00320                 LfsReleaseLfcb( Lfcb );
    00321
    00322                 //
    00323                 //  If an error occurred and we allocated an Lfcb.  We deallocate
    00324                 //  it now.
    00325                 //
    00326
    00327                 if (AbnormalTermination()) {
    00328
    00329                     LfsDeallocateLfcb( Lfcb, TRUE );
    00330                 }
    00331             }
    00332
    00333             //
    00334             //  Deallocate the restart area.
    00335             //
    00336
    00337             if (RestartArea != NULL) {
    00338
    00339                 LfsDeallocateRestartArea( RestartArea );
    00340             }
    00341
    00342             //
    00343             //  We release the global data.
    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 }

VOID LfsInitializeLogFilePriv | ( | IN PLFCB | Lfcb,
|  | IN BOOLEAN | ForceRestartToDisk,
|  | IN ULONG | RestartAreaSize,
|  | IN LONGLONG | StartOffsetForClear,
|  | IN BOOLEAN | ClearLogFile
| ) |

Definition at line 3065 of file lfs/registry.c.

References CcUnpinData(), Dbg, DebugTrace, FALSE, LFS_SIGNATURE_UNINITIALIZED_ULONG, LfsFlushLogPage(), LfsPinOrMapData(), LfsWriteLfsRestart(), NT_SUCCESS, NULL, PAGED_CODE, and TRUE.

Referenced by LfsInitializeLogFile(), and LfsRestartLogFile().

    03075                    :
    03076
    03077     This routine is our internal routine for initializing a log file.
    03078     This can be the case where we are updating the log file for
    03079     update sequence array, or differing page size or new log file size.
    03080
    03081 Arguments:
    03082
    03083     Lfcb - This is the Lfcb for this log file.  It should already have
    03084         the version number information stored.
    03085
    03086     ForceRestartToDisk - Indicates that we want to actually force restart
    03087         areas to disk instead of simply queueing them to the start of the
    03088         workqueue.
    03089
    03090     RestartAreaSize - This is the size for the restart areas.  This may
    03091         be larger than the size in the Lfcb because we may be clearing
    03092         stale data out of the file.
    03093
    03094     StartOffsetForClear - If we are clearing the file we want to uninitialize
    03095         from this point.
    03096
    03097     ClearLogFile - Indicates if we want to uninitialize the log file to
    03098         remove stale data.  This is done specifically when changing
    03099         system page sizes.
    03100
    03101 Return Value:
    03102
    03103     None
    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     //  We start by queueing the restart areas.
    03120     //
    03121
    03122     LfsWriteLfsRestart( Lfcb,
    03123                         RestartAreaSize,
    03124                         FALSE );
    03125
    03126     LfsWriteLfsRestart( Lfcb,
    03127                         RestartAreaSize,
    03128                         ForceRestartToDisk );
    03129
    03130     //
    03131     //  If we are to clear the log file, we write all 0xff into the
    03132     //  log pages beginning at the log page offset.
    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                 //  We'll do the best we can and ignore all errors.
    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 }

VOID LfsNormalizeBasicLogFile | ( | IN OUT PLONGLONG | FileSize,
|  | IN OUT PULONG | LogPageSize,
|  | IN OUT PUSHORT | LogClients,
|  | IN BOOLEAN | UseDefaultLogPage
| ) |

Definition at line 2246 of file lfs/registry.c.

References Dbg, DebugTrace, ExRaiseStatus(), LFS_DEFAULT_LOG_PAGE_SIZE, LfsMaximumFileSize, MINIMUM_LFS_PAGES, PAGE_SIZE, PAGED_CODE, and USHORT.

Referenced by LfsInitializeLogFile(), and LfsRestartLogFile().

    02255                    :
    02256
    02257     This routine is called to normalize the values which describe the
    02258     log file.  It will make the log page a multiple of the system page.
    02259     Finally we make sure the file size ends on a log page boundary.
    02260
    02261     On input all of the parameters have the requested values, on return
    02262     they have the values to use.
    02263
    02264 Arguments:
    02265
    02266     FileSize - Stated size of the log file.
    02267
    02268     LogPageSize - Suggested size for the log page.
    02269
    02270     LogClients - Requested number of log clients.
    02271
    02272     UseDefaultLogPage - Indicates if we should use the hardwired log page size or base
    02273         it on the system page size.
    02274
    02275 Return Value:
    02276
    02277     None.
    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     //  We always make the log page the same as the system page size.
    02294     //  This may change in the future.
    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     //  If the log file is greater than the maximum log file size, we
    02308     //  set the log file size to the maximum size.
    02309     //
    02310
    02311     if (*FileSize > LfsMaximumFileSize) {
    02312
    02313         *FileSize = LfsMaximumFileSize;
    02314     }
    02315
    02316     //
    02317     //  We round the file size down to a system page boundary.  This
    02318     //  may also change if we allow non-system page sized log pages.
    02319     //
    02320
    02321     *(PULONG)FileSize &= ~(*LogPageSize - 1);
    02322
    02323     //
    02324     //  There better be at least 2 restart pages.
    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     //  Now compute the number of log pages.
    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     //  If there aren't enough log pages then raise an error condition.
    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     //  Now we compute the amount of space available for log clients.
    02365     //  We will limit the clients to half of the restart system page.
    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 }

ULONG LfsOpenLogFile | ( | IN PFILE_OBJECT | LogFile,
|  | IN UNICODE_STRING | ClientName,
|  | IN USHORT | MaximumClients,
|  | IN ULONG LogPageSize | OPTIONAL,
|  | IN LONGLONG | FileSize,
|  | IN OUT PLFS_INFO | LfsInfo,
|  | OUT PLFS_LOG_HANDLE | LogHandle,
|  | OUT PLFS_WRITE_DATA | WriteData
| ) |

Definition at line 366 of file lfs/registry.c.

References CcSetAdditionalCacheAttributes(), _LFCB::ClientArray, _LCH::ClientArrayByteOffset, _LFS_RESTART_AREA::ClientFreeList, _LCH::ClientId, _LFS_CLIENT_ID::ClientIndex, _LFS_RESTART_AREA::ClientInUseList, _LFS_CLIENT_RECORD::ClientName, _LFS_CLIENT_RECORD::ClientNameLength, _LFS_CLIENT_RECORD::ClientRestartLsn, Dbg, DebugTrace, DebugUnwind, ExRaiseStatus(), _LFCB::FileObject, FlagOn, _LFCB::Flags, _LCH::LchLinks, _LFCB::LchLinks, _LCH::Lfcb, LFCB_LOG_FILE_CORRUPT, LFCB_PACK_LOG, _LFCB::LfcbLinks, _LFS_DATA::LfcbLinks, LFS_CLIENT_NAME_MAX, LFS_LOG_HANDLE, LFS_NO_CLIENT, LfsAcquireLfsData, LfsAddClientToList(), LfsAllocateLch, LfsData, LfsDeallocateLch, LfsDeallocateLfcb(), LfsExceptionFilter(), LfsOpenLogFile(), LfsReleaseLfcb, LfsReleaseLfsData, LfsRemoveClientFromList(), LfsRestartLogFile(), LfsZeroLsn, _LFS_CLIENT_RECORD::NextClient, NTSTATUS(), NULL, _LFCB::OldestLsn, _LFS_CLIENT_RECORD::OldestLsn, PAGED_CODE, PtrOffset, _LFCB::RecordHeaderLength, _LFCB::RestartArea, _LFS_CLIENT_RECORD::SeqNumber, _LFS_CLIENT_ID::SeqNumber, Status, _LFCB::Sync, _LCH::Sync, TRUE, _LFCB_SYNC::UserCount, and USHORT.

Referenced by LfsOpenLogFile().

    00379                    :
    00380
    00381     This routine is called when a client wishes to register with logging
    00382     service.  This can be a reregistration (i.e. restart after a crash)
    00383     or an initial registration.  There can be no other active clients
    00384     with the same name.  The Log Handle returned is then used for any
    00385     subsequent access by this client.
    00386
    00387     If an Lfs restart has not been done on the log file, it will be done
    00388     at this time.
    00389
    00390 Arguments:
    00391
    00392     LogFile - A file object for a file previously initialized for use
    00393               as a log file.
    00394
    00395     ClientName - This unicode string is used to uniquely identify clients
    00396                  of the logging service.  A case-sensitive comparison is
    00397                  used to check this name against active clients of the
    00398                  log file.
    00399
    00400     MaximumClients - The maximum number of clients if the log file has
    00401                      never been initialized.
    00402
    00403     LogPageSize - This is the recommeded size for the log page.
    00404
    00405     FileSize - This is the size of the log file.
    00406
    00407     LfsInfo - On entry, indicates the log file state the user may
    00408         know about.  On exit, indicates the log file state that Lfs
    00409         knows about.  This is a conduit for Lfs to communicate with its
    00410         clients.
    00411
    00412     LogHandle - The address to store the identifier the logging service
    00413                 will use to identify this client in all other Lfs calls.
    00414
    00415     WriteData - Pointer to WRITE_DATA in caller's data structure.
    00416
    00417 Return Value:
    00418
    00419     ULONG - Amount to add to reservation value for header for log record.
    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     //  Check that the client name length is a legal length.
    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     //  Protect this call with a try-except.
    00460     //
    00461
    00462     try {
    00463
    00464         //
    00465         //  Aqcuire the global data.
    00466         //
    00467
    00468         LfsAcquireLfsData();
    00469
    00470         //
    00471         //  Use a try-finally to facilitate cleanup.
    00472         //
    00473
    00474         try {
    00475
    00476             //
    00477             //  Walk through the list searching for this file object.
    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             //  If the log file doesn't exist, create an Lfcb and perform an
    00497             //  Lfs restart.
    00498             //
    00499
    00500             if (Link == &LfsData.LfcbLinks) {
    00501
    00502                 //
    00503                 //  Call the Cache Manager to disable read ahead and write behind;
    00504                 //  we flush the log file explicitly.
    00505                 //
    00506
    00507                 CcSetAdditionalCacheAttributes( LogFile, TRUE, TRUE );
    00508
    00509                 //
    00510                 //  Perform Lfs restart on this file object.
    00511                 //
    00512
    00513                 ThisLfcb = NewLfcb = LfsRestartLogFile( LogFile,
    00514                                                         MaximumClients,
    00515                                                         0,
    00516                                                         FileSize,
    00517                                                         LfsInfo,
    00518                                                         WriteData );
    00519
    00520                 //
    00521                 //  Insert this Lfcb into the global list.
    00522                 //
    00523
    00524                 InsertHeadList( &LfsData.LfcbLinks, &ThisLfcb->LfcbLinks );
    00525             }
    00526
    00527             //
    00528             //  At this point we have the log file control block for the file
    00529             //  object given us.  We first check whether the log file is fatally
    00530             //  corrupt.
    00531             //
    00532
    00533             if (FlagOn( ThisLfcb->Flags, LFCB_LOG_FILE_CORRUPT )) {
    00534
    00535                 //
    00536                 //  We leave the in-memory data alone and raise an error if
    00537                 //  anyone attempts to access this file.
    00538                 //
    00539
    00540                 DebugTrace( 0, Dbg, "The Lfcb is corrupt\n", 0 );
    00541                 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR );
    00542             }
    00543
    00544             //
    00545             //  Search through and look for a client match.
    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             //  Allocate an Lch structure and link it into the Lfcb.
    00568             //
    00569
    00570             LfsAllocateLch( &Lch );
    00571             InsertTailList( &ThisLfcb->LchLinks, &Lch->LchLinks );
    00572
    00573             //
    00574             //  Initialize the client handle with the data from the Lfcb.
    00575             //
    00576
    00577             Lch->Lfcb = ThisLfcb;
    00578             Lch->Sync = ThisLfcb->Sync;
    00579             Lch->Sync->UserCount += 1;
    00580
    00581             //
    00582             //  If a match isn't found, take a client block off the free list
    00583             //  if available.
    00584             //
    00585
    00586             if (ThisClient == LFS_NO_CLIENT) {
    00587
    00588                 //
    00589                 //  Raise an error status if out of client blocks.
    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                 //  Initialize the client block.
    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                 //  Add it to the in use list.
    00619                 //
    00620
    00621                 LfsAddClientToList( ThisLfcb->ClientArray,
    00622                                     ThisClient,
    00623                                     &ThisLfcb->RestartArea->ClientInUseList );
    00624             }
    00625
    00626             //
    00627             //  Update the client handle with the client block information.
    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             //  If the Lfcb has been acquired, we release it now.
    00644             //
    00645
    00646             if (ThisLfcb != NULL) {
    00647
    00648                 //
    00649                 //  Pass information back to our caller for the number
    00650                 //  of bytes to add to the reserved amount for a
    00651                 //  log header.
    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             //  If there is an error then deallocate the Lch and any new Lfcb.
    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             //  Always free the global.
    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 }

VOID LfsReadLogFileInformation | ( | IN LFS_LOG_HANDLE | LogHandle,
|  | IN PLOG_FILE_INFORMATION | Buffer,
|  | IN OUT PULONG | Length
| ) |

Definition at line 1141 of file lfs/registry.c.

References Buffer, _LCH::ClientUndoCommitment, _LOG_FILE_INFORMATION::ClientUndoCommitment, _LOG_FILE_INFORMATION::CurrentAvailable, _LFS_RESTART_AREA::CurrentLsn, Dbg, DebugTrace, DebugUnwind, _LFCB::LastFlushedLsn, _LOG_FILE_INFORMATION::LastFlushedLsn, _LOG_FILE_INFORMATION::LastLsn, _LCH::Lfcb, LfsAcquireLch, LfsCurrentAvailSpace(), LfsReadLogFileInformation(), LfsReleaseLch, LfsValidateClientId, LfsValidateLch, NULL, _LFCB::OldestLsn, _LOG_FILE_INFORMATION::OldestLsn, PAGED_CODE, _LFCB::RestartArea, _LFCB::TotalAvailable, _LOG_FILE_INFORMATION::TotalAvailable, _LFCB::TotalUndoCommitment, _LOG_FILE_INFORMATION::TotalUndoCommitment, and try_return.

Referenced by LfsReadLogFileInformation().

    01149                    :
    01150
    01151     This routine returns information about the current state of the log
    01152     file, primarily to aid the client perform its checkpoint processing.
    01153
    01154 Arguments:
    01155
    01156     LogHandle - Pointer to private Lfs structure used to identify this
    01157                 client.
    01158
    01159     Buffer - Pointer to buffer to return the log file information.
    01160
    01161     Length - On input this is the length of the user's buffer.  On output,
    01162              it is the amount of data stored by the Lfs in the buffer.
    01163
    01164 Return Value:
    01165
    01166     None
    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     //  Check that the structure is a valid log handle structure.
    01185     //
    01186
    01187     LfsValidateLch( Lch );
    01188
    01189     //
    01190     //  Use a try-finally to facilitate cleanup.
    01191     //
    01192
    01193     try {
    01194
    01195         //
    01196         //  Acquire the log file control block for this log file.
    01197         //
    01198
    01199         LfsAcquireLch( Lch );
    01200         Lfcb = Lch->Lfcb;
    01201
    01202         //
    01203         //  If the Log file has been closed then return immediately.
    01204         //
    01205
    01206         if (Lfcb == NULL) {
    01207
    01208             try_return( *Length = 0 );
    01209         }
    01210
    01211         //
    01212         //  Check that the client Id is valid.
    01213         //
    01214
    01215         LfsValidateClientId( Lfcb, Lch );
    01216
    01217         //
    01218         //  The buffer better be large enough.
    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             //  Cast a pointer to the buffer and fill in the
    01233             //  data.
    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         //  Release the log file control block if held.
    01261         //
    01262
    01263         LfsReleaseLch( Lch );
    01264
    01265         DebugTrace( -1, Dbg, "LfsReadLogFileInformation:  Exit\n", 0 );
    01266     }
    01267
    01268     return;
    01269 }

VOID LfsRemoveClientFromList | ( | PLFS_CLIENT_RECORD | ClientArray,
|  | PLFS_CLIENT_RECORD | ClientRecord,
|  | IN PUSHORT | ListHead
| ) |

Definition at line 4383 of file lfs/registry.c.

References Dbg, DebugTrace, LFS_NO_CLIENT, _LFS_CLIENT_RECORD::NextClient, PAGED_CODE, and _LFS_CLIENT_RECORD::PrevClient.

Referenced by LfsCloseLogFile(), and LfsOpenLogFile().

    04391                    :
    04392
    04393     This routine is called to remove a client record from a client record
    04394     list in an Lfs restart area.
    04395
    04396 Arguments:
    04397
    04398     ClientArray - Base of client records in restart area.
    04399
    04400     ClientRecord - A pointer to the record to add.
    04401
    04402     ListHead - A pointer to the beginning of the list.  This points to a
    04403                USHORT which is the value of the first element in the list.
    04404
    04405 Return Value:
    04406
    04407     None.
    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     //  If this is the first element in the list, then the head of the list
    04423     //  points to the element after this record.
    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     //  Otherwise the previous element points to the next element.
    04433     //
    04434
    04435     } else {
    04436
    04437         TempClientRecord = ClientArray + ClientRecord->PrevClient;
    04438         TempClientRecord->NextClient = ClientRecord->NextClient;
    04439     }
    04440
    04441     //
    04442     //  If this is not the last element in the list, the previous element
    04443     //  becomes the last element.
    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 }

VOID LfsRemoveClientFromList | ( | IN PLFS_CLIENT_RECORD | ClientArray,
|  | IN PLFS_CLIENT_RECORD | ClientRecord,
|  | IN PUSHORT | ListHead
| ) |

VOID LfsResetUndoTotal | ( | IN LFS_LOG_HANDLE | LogHandle,
|  | IN ULONG | NumberRecords,
|  | IN LONG | ResetTotal
| ) |

Definition at line 1361 of file lfs/registry.c.

References _LCH::ClientUndoCommitment, Dbg, DebugTrace, DebugUnwind, ExRaiseStatus(), FlagOn, _LFCB::Flags, _LCH::Lfcb, LFCB_PACK_LOG, LfsAcquireLch, LfsReleaseLch, LfsResetUndoTotal(), LfsValidateClientId, LfsValidateLch, NULL, PAGED_CODE, _LFCB::RecordHeaderLength, and _LFCB::TotalUndoCommitment.

Referenced by LfsResetUndoTotal().

    01369                    :
    01370
    01371     This routine is called to adjust the undo commitment for this client.
    01372     If the reset total is positive, then we absolutely set the
    01373     reserve value for the client using this as the basis.  If the value
    01374     is negative, we will adjust the current value for the client.
    01375
    01376     To adjust the values in the Lfcb, we first return the Undo commitment
    01377     in the handle and then adjust by the values passed in.
    01378
    01379     To adjust the value in the client handle, we simply set it if
    01380     the reset value is positive, adjust it if the value is negative.
    01381
    01382     For a packed log file we just reserve the space requested.  We
    01383     have already taken into account the loss of the tail of each page.
    01384     For an unpacked log file we double each value.
    01385
    01386 Arguments:
    01387
    01388     LogHandle - Pointer to private Lfs structure used to identify this
    01389                 client.
    01390
    01391     NumberRecords - This is the number of records we should assume the
    01392                     reset total covers.  We allow an Lfs header for
    01393                     each one.
    01394
    01395     ResetTotal - This is the amount to adjust (or set) the undo
    01396                  commitment.
    01397
    01398 Return Value:
    01399
    01400     None
    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     //  Check that the structure is a valid log handle structure.
    01423     //
    01424
    01425     LfsValidateLch( Lch );
    01426
    01427     //
    01428     //  Use a try-finally to facilitate cleanup.
    01429     //
    01430
    01431     try {
    01432
    01433         //
    01434         //  Acquire the log file control block for this log file.
    01435         //
    01436
    01437         LfsAcquireLch( Lch );
    01438         Lfcb = Lch->Lfcb;
    01439
    01440         //
    01441         //  If the Log file has been closed then refuse access.
    01442         //
    01443
    01444         if (Lfcb == NULL) {
    01445
    01446             ExRaiseStatus( STATUS_ACCESS_DENIED );
    01447         }
    01448
    01449         //
    01450         //  Check that the client Id is valid.
    01451         //
    01452
    01453         LfsValidateClientId( Lfcb, Lch );
    01454
    01455         //
    01456         //  Compute the adjusted reset total.  Start by computing the
    01457         //  bytes needed for the Lfs log headers.  Add (or subtract) this
    01458         //  from the reset total and multiply by 2 (only if not packing the
    01459         //  log).
    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         //  If the reset total is positive, add the header bytes.
    01472         //
    01473
    01474         if (ResetTotal > 0) {
    01475
    01476             //
    01477             //  Subtract the client's current value from the TotalUndo
    01478             //  commit if he is setting his value exactly.
    01479             //
    01480
    01481             Lfcb->TotalUndoCommitment = Lfcb->TotalUndoCommitment - Lch->ClientUndoCommitment;
    01482
    01483             //
    01484             //  We can clear the values in the user's handle at this
    01485             //  time.
    01486             //
    01487
    01488             Lch->ClientUndoCommitment = 0;
    01489
    01490
    01491             ResetTotal += LfsHeaderBytes;
    01492
    01493         //
    01494         //  Otherwise subtract the value for the header bytes.
    01495         //
    01496
    01497         } else {
    01498
    01499             ResetTotal -= LfsHeaderBytes;
    01500         }
    01501
    01502         //
    01503         //  Now we adjust the Lfcb and Lch values by the adjustment amount.
    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         //  Release the log file control block if held.
    01518         //
    01519
    01520         LfsReleaseLch( Lch );
    01521
    01522         DebugTrace( -1, Dbg, "LfsResetUndoTotal:  Exit\n", 0 );
    01523     }
    01524
    01525     return;
    01526 }

PLFCB LfsRestartLogFile | ( | IN PFILE_OBJECT | LogFile,
|  | IN USHORT | MaximumClients,
|  | IN ULONG LogPageSize | OPTIONAL,
|  | IN LONGLONG | FileSize,
|  | IN OUT PLFS_INFO | LfsInfo,
|  | OUT PLFS_WRITE_DATA | WriteData
| ) |

Definition at line 1534 of file lfs/registry.c.

References Add2Ptr, ASSERT, CcUnpinData(), ClearFlag, _LFCB::ClientArray, _LFS_RESTART_AREA::ClientArrayOffset, _LFCB::ClientArrayOffset, _LFS_RESTART_AREA::ClientInUseList, _LFCB::CurrentOpenLogCount, Dbg, DebugTrace, DebugUnwind, ExRaiseStatus(), FALSE, _LFCB::FileObject, _LFS_RESTART_AREA::FileSize, FlagOn, _LFS_RESTART_AREA::Flags, _LFCB::Flags, _LFCB::InitialRestartArea, KeQuerySystemTime(), LFCB_READ_FIRST_RESTART, LFCB_READ_SECOND_RESTART, LFS_DEFAULT_LOG_PAGE_SIZE, LFS_NO_CLIENT, LFS_SIGNATURE_MODIFIED_ULONG, LfsAcquireLfcb, LfsAllocateLfcb(), LfsAllocateRestartArea, LfsDeallocateLfcb(), LfsDeallocateRestartArea, LfsFindCurrentAvail(), LfsFindLastLsn(), LfsFixedPageSize, LfsInitializeLogFilePriv(), LfsLi0, LfsNormalizeBasicLogFile(), LfsPackLog, LfsPinOrMapData(), LfsReadRestart(), LfsReleaseLfcb, LfsRestartLogFile(), _LFS_WRITE_DATA::LfsStructureSize, LfsUpdateLfcbFromNoRestart(), LfsUpdateLfcbFromPgHeader(), LfsUpdateLfcbFromRestart(), LfsUpdateRestartAreaFromLfcb(), _LFS_RESTART_AREA::LogClientArray, _LFCB::LogClients, _LFS_RESTART_PAGE_HEADER::LogPageSize, LSN, _LFS_RESTART_PAGE_HEADER::MajorVersion, _LFS_RESTART_PAGE_HEADER::MinorVersion, NT_SUCCESS, NULL, PAGE_SIZE, PAGED_CODE, RESTART_SINGLE_PAGE_IO, _LFCB::RestartArea, _LFS_RESTART_AREA::RestartAreaLength, _LFCB::RestartAreaSize, _LFCB::RestartDataSize, _LFS_RESTART_PAGE_HEADER::RestartOffset, _LFS_RESTART_AREA::RestartOpenLogCount, SetFlag, SHORT, _LFS_RESTART_PAGE_HEADER::SystemPageSize, TRUE, _LFCB::UserWriteData, and USHORT.

Referenced by LfsOpenLogFile(), and LfsRestartLogFile().

    01545                    :
    01546
    01547     This routine is called to process an existing log file when it opened
    01548     for the first time on a running system.  We walk through the beginning
    01549     of the file looking for a valid restart area.  Once we have a restart
    01550     area, we can find the next restart area and determine which is the
    01551     most recent.  The data in the restart area will tell us if the system
    01552     has been gracefully shutdown and whether the log file in its current
    01553     state can run on the current system.
    01554
    01555     If the file is usable, we perform any necessary initialization on the
    01556     file to prepare it for operation.
    01557
    01558 Arguments:
    01559
    01560     LogFile - This is the file to use as a log file.
    01561
    01562     MaximumClients - This is the maximum number of clients that will be
    01563                      active in the log file at any one time.
    01564
    01565     LogPageSize - If specified (not 0), this is the recommended size of
    01566                   the log page.  Lfs will use this as a guide in
    01567                   determining the log page size.
    01568
    01569     FileSize - This is the available size of the log file.
    01570
    01571     LfsInfo - On entry, indicates the log file state the user may
    01572         know about.  On exit, indicates the log file state that Lfs
    01573         knows about.  This is a conduit for Lfs to communicate with its
    01574         clients.
    01575
    01576     WriteData - Pointer to WRITE_DATA in caller's data structure.
    01577
    01578 Return Value:
    01579
    01580     PLFCB - A pointer to an initialized Lfcb to use for
    01581                               this log file.
    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     //  Remember if we are to pack the log file.  Once a log file has
    01619     //  been packed we will attempt to keep it that way.
    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     //  Use a try-finally to facilitate cleanup.
    01633     //
    01634
    01635     try {
    01636
    01637         //
    01638         //  Normalize the values passed in with this call.
    01639         //
    01640
    01641         LfsNormalizeBasicLogFile( &FileSize,
    01642                                   &LogPageSize,
    01643                                   &MaximumClients,
    01644                                   UseDefaultLogPage );
    01645
    01646         //
    01647         //  Allocate an Lfcb to use for this file.
    01648         //
    01649
    01650         ThisLfcb = LfsAllocateLfcb();
    01651
    01652         //
    01653         //  Acquire the Lfcb and store it in the global queue.
    01654         //
    01655
    01656         LfsAcquireLfcb( ThisLfcb );
    01657
    01658         //
    01659         //  Remember this log file in the Lfcb.
    01660         //
    01661
    01662         ThisLfcb->FileObject = LogFile;
    01663
    01664         SetFlag( ThisLfcb->Flags,
    01665                  (LFCB_READ_FIRST_RESTART |
    01666                   LFCB_READ_SECOND_RESTART) );
    01667
    01668         //
    01669         //  Look for a restart area on the disk.
    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             //  If the restart offset above wasn't zero then we
    01695             //  won't look for a second restart.
    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             //  Determine which restart area to use.
    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                 //  In a very strange case we could have crashed on a system with
    01739                 //  a different page size and then run chkdsk on the new system.
    01740                 //  The second restart page may not have the chkdsk signature in
    01741                 //  that case but could have a higher final Lsn.
    01742                 //  We want to ignore the second restart area in that case.
    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             //  If the restart area is at offset 0, we want to write
    01781             //  the second restart area out first.
    01782             //
    01783
    01784             if (FirstRestartOffset != 0) {
    01785
    01786                 ThisLfcb->InitialRestartArea = TRUE;
    01787             }
    01788
    01789             //
    01790             //  If we have a valid page then grab a pointer to the restart area.
    01791             //
    01792
    01793             if (FirstValidPage) {
    01794
    01795                 DiskRestartArea = Add2Ptr( FirstRestartPage, FirstRestartPage->RestartOffset, PLFS_RESTART_AREA );
    01796             }
    01797
    01798             //
    01799             //  If checkdisk was run or there are no active clients,
    01800             //  then we will begin at the start of the log file.
    01801             //
    01802
    01803             if (FirstChkdskWasRun
    01804                 || DiskRestartArea->ClientInUseList == LFS_NO_CLIENT) {
    01805
    01806                 //
    01807                 //  Default version is 1.1.
    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                 //  Do some checks based on whether we have a valid log page.
    01825                 //
    01826
    01827                 if (FirstValidPage) {
    01828
    01829                     CurrentTime.LowPart = DiskRestartArea->RestartOpenLogCount;
    01830
    01831                     //
    01832                     //  If the restart page size isn't changing then we want to
    01833                     //  check how much work we need to do.
    01834                     //
    01835
    01836                     if (LogPageSize == FirstRestartPage->SystemPageSize) {
    01837
    01838                         //
    01839                         //  If the file size is changing we want to remember
    01840                         //  at which point we want to start clearing the file.
    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                             //  If the page is valid we don't need to clear the log
    01857                             //  file or force the data to disk.
    01858                             //
    01859
    01860                             ForceRestartToDisk = FALSE;
    01861                             ClearLogFile = FALSE;
    01862                         }
    01863                     }
    01864
    01865                 } else {
    01866
    01867                     KeQuerySystemTime( &CurrentTime );
    01868                 }
    01869
    01870                 //
    01871                 //  Initialize our Lfcb for the current log page values.
    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                 //  Unpin any pages pinned here.
    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                 //  Now update the caller's WRITE_DATA structure.
    01917                 //
    01918
    01919                 ThisLfcb->UserWriteData = WriteData;
    01920                 WriteData->LfsStructureSize = LogPageSize;
    01921                 WriteData->Lfcb = ThisLfcb;
    01922
    01923                 //
    01924                 //  Put the restart areas out and initialize the log file
    01925                 //  as required.
    01926                 //
    01927
    01928                 LfsInitializeLogFilePriv( ThisLfcb,
    01929                                           ForceRestartToDisk,
    01930                                           ThisLfcb->RestartDataSize,
    01931                                           StartOffsetForClear,
    01932                                           ClearLogFile );
    01933
    01934             //
    01935             //  If the log page or the system page sizes have changed,
    01936             //  we can't use the log file.  We must use the system
    01937             //  page size instead of the default size if there is not
    01938             //  a clean shutdown.
    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                 //  If the file size has shrunk then we won't mount it.
    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                 //  Otherwise we have a restart area to deal with.
    01969                 //
    01970
    01971                 } else {
    01972
    01973                     //
    01974                     //  We preserve the packed status from the disk.
    01975                     //
    01976
    01977                     PackLogFile = FirstLogPacked;
    01978
    01979                     //
    01980                     //  Update the Lfcb from the values in the restart area
    01981                     //  page header and the active restart page.
    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                     //  Now allocate a restart area.
    01997                     //
    01998
    01999                     LfsAllocateRestartArea( &RestartArea, ThisLfcb->RestartDataSize );
    02000
    02001                     //
    02002                     //  We may need to grow the restart area to allow room for the open
    02003                     //  log file count.
    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                         //  Copy the start of the restart area over.
    02016                         //
    02017
    02018                         RtlCopyMemory( RestartArea, DiskRestartArea, ThisLfcb->ClientArrayOffset );
    02019
    02020                         //
    02021                         //  Now copy over the client data to its new location.
    02022                         //
    02023
    02024                         RtlCopyMemory( RestartArea->LogClientArray,
    02025                                        Add2Ptr( DiskRestartArea, ThisLfcb->ClientArrayOffset, PVOID ),
    02026                                        DiskRestartArea->RestartAreaLength - ThisLfcb->ClientArrayOffset );
    02027
    02028                         //
    02029                         //  Update the system open count.
    02030                         //
    02031
    02032                         KeQuerySystemTime( &CurrentTime );
    02033
    02034                         ThisLfcb->CurrentOpenLogCount =
    02035                         RestartArea->RestartOpenLogCount = CurrentTime.LowPart;
    02036
    02037                         //
    02038                         //  Now update the numbers in the Lfcb and restart area.
    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                     //  Update the log file open count.
    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                     //  Unpin any pages pinned here.
    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                     //  Now update the caller's WRITE_DATA structure.
    02078                     //
    02079
    02080                     ThisLfcb->UserWriteData = WriteData;
    02081                     WriteData->LfsStructureSize = LogPageSize;
    02082                     WriteData->Lfcb = ThisLfcb;
    02083
    02084                     //
    02085                     //  Now we need to walk through looking for the last
    02086                     //  Lsn.
    02087                     //
    02088
    02089                     LfsFindLastLsn( ThisLfcb );
    02090
    02091                     //
    02092                     //  Recalculate the available pages in the Lfcb.
    02093                     //
    02094
    02095                     LfsFindCurrentAvail( ThisLfcb );
    02096
    02097                     //
    02098                     //  Remember which restart area to write out first.
    02099                     //
    02100
    02101                     if (FirstRestartOffset != 0) {
    02102
    02103                         ThisLfcb->InitialRestartArea = TRUE;
    02104                     }
    02105
    02106                     //
    02107                     //  Queue the restart areas.
    02108                     //
    02109
    02110                     LfsInitializeLogFilePriv( ThisLfcb,
    02111                                               FALSE,
    02112                                               ThisLfcb->RestartDataSize,
    02113                                               0,
    02114                                               FALSE );
    02115                 }
    02116             }
    02117
    02118         //
    02119         //  If the file is uninitialized, we will initialized it with new
    02120         //  restart areas.  We can move to version 1.0 where we use
    02121         //  update sequence array support but don't have to force the values
    02122         //  to disk.
    02123         //
    02124
    02125         } else if (UninitializedFile) {
    02126
    02127             //
    02128             //  We go to a packed system if possible.
    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             //  Now update the caller's WRITE_DATA structure.
    02159             //
    02160
    02161             ThisLfcb->UserWriteData = WriteData;
    02162             WriteData->LfsStructureSize = LogPageSize;
    02163             WriteData->Lfcb = ThisLfcb;
    02164
    02165             //
    02166             //  Put both restart areas in the queue to be flushed but don't
    02167             //  force them to disk.
    02168             //
    02169
    02170             LfsInitializeLogFilePriv( ThisLfcb,
    02171                                       FALSE,
    02172                                       ThisLfcb->RestartDataSize,
    02173                                       0,
    02174                                       FALSE );
    02175
    02176         //
    02177         //  We didn't find a restart area but the file is not initialized.
    02178         //  This is a corrupt disk.
    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         //  Free the Lfcb if allocated.
    02193         //
    02194
    02195         if (ThisLfcb != NULL) {
    02196
    02197             LfsReleaseLfcb( ThisLfcb );
    02198
    02199             //
    02200             //  Free the Lfcb and Restart areas in the event of an error.
    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     //  Indicate whether the log is packed.
    02229     //
    02230
    02231     if (PackLogFile
    02232         && *LfsInfo < LfsPackLog) {
    02233
    02234         *LfsInfo = LfsPackLog;
    02235     }
    02236
    02237     return ThisLfcb;
    02238 }

VOID LfsUpdateLfcbFromNoRestart | ( | IN PLFCB | Lfcb,
|  | IN LONGLONG | FileSize,
|  | IN LSN | LastLsn,
|  | IN ULONG | LogClients,
|  | IN ULONG | OpenLogCount,
|  | IN BOOLEAN | LogFileWrapped,
|  | IN BOOLEAN | UseMultiplePageIo
| ) |

Definition at line 2514 of file lfs/registry.c.

References Count, Dbg, DebugTrace, FlagOn, LFCB_LOG_WRAPPED, LFCB_MULTIPLE_PAGE_IO, LFCB_NO_LAST_LSN, LFCB_NO_OLDEST_LSN, LFCB_PACK_LOG, LFS_RECORD_HEADER_SIZE, LFS_RESTART_PAGE_HEADER_SIZE, LfsAllocateLbcb(), LfsFileOffsetToLsn, LfsLsnToSeqNumber, LSN, PAGED_CODE, QuadAlign, SetFlag, UPDATE_SEQUENCE_NUMBER, and USHORT.

Referenced by LfsInitializeLogFile(), and LfsRestartLogFile().

    02526                    :
    02527
    02528     This routine updates the values in the Lfcb in cases when we don't have a
    02529     restart area to use.
    02530
    02531 Arguments:
    02532
    02533     Lfcb - Log file control block to update.
    02534
    02535     FileSize - Log file size.  This is the usable size of the log file.  It has
    02536         already been adjusted to the log page size.
    02537
    02538     LastLsn - This is the last Lsn to use for the disk.
    02539
    02540     LogClients - This is the number of clients supported.
    02541
    02542     OpenLogCount - This is the current count of opens for this log file.
    02543
    02544     LogFileWrapped - Indicates if the log file has wrapped.
    02545
    02546     UseMultiplePageIo - Indicates if we should be using large i/o transfers.
    02547
    02548 Return Value:
    02549
    02550     None.
    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     //  We can compute the number of bits needed for the file size by shifting
    02565     //  until the size is 0.  We then can subtract 3 bits to account for
    02566     //  quadaligning all file offsets for log records.
    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     //  We get a starting sequence number from the given Lsn.
    02581     //  We add 2 to this for our starting sequence number.
    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     //  The oldest Lsn is contructed from the sequence number.
    02594     //
    02595
    02596     Lfcb->OldestLsn.QuadPart = LfsFileOffsetToLsn( Lfcb, 0, Lfcb->SeqNumber );
    02597     Lfcb->OldestLsnOffset = 0;
    02598
    02599     Lfcb->LastFlushedLsn = Lfcb->OldestLsn;
    02600
    02601     //
    02602     //  Set the correct flags for the I/O and indicate if we have wrapped.
    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     //  Compute the Log page values.
    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         //  Allocate the Lbcb for the tail of the packed log file.
    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         //  Remember the different page sizes for reservation.
    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     //  Compute the restart page values.
    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     //  The total available log file space is the number of log file pages times
    02668     //  the space available on each page.
    02669     //
    02670
    02671     Lfcb->TotalAvailInPages = Lfcb->FileSize - Lfcb->FirstLogPage;
    02672     Lfcb->TotalAvailable = Int64ShrlMod32(((ULONGLONG)(Lfcb->TotalAvailInPages)), Lfcb->LogPageShift);
    02673
    02674     //
    02675     //  If the log file is packed we assume that we can't use the end of the
    02676     //  page less than the file record size.  Then we won't need to reserve more
    02677     //  than the caller asks for.
    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 }

VOID LfsUpdateLfcbFromPgHeader | ( | IN PLFCB | Lfcb,
|  | IN ULONG | SystemPageSize,
|  | IN ULONG | LogPageSize,
|  | IN SHORT | MajorVersion,
|  | IN SHORT | MinorVersion,
|  | IN BOOLEAN | PackLog
| ) |

Definition at line 2390 of file lfs/registry.c.

References Dbg, DebugTrace, LFCB_PACK_LOG, LFS_PACKED_RECORD_PAGE_HEADER_SIZE, LFS_RESTART_PAGE_HEADER_SIZE, LFS_UNPACKED_RECORD_PAGE_HEADER_SIZE, PAGED_CODE, SetFlag, TRUE, UpdateSequenceArraySize, and USHORT.

Referenced by LfsInitializeLogFile(), and LfsRestartLogFile().

    02401                    :
    02402
    02403     This routine updates the values in the Lfcb which depend on values in the
    02404     restart page header.
    02405
    02406 Arguments:
    02407
    02408     Lfcb - Log file control block to update.
    02409
    02410     SystemPageSize - System page size to use.
    02411
    02412     LogPageSize - Log page size to use.
    02413
    02414     MajorVersion - Major version number for Lfs.
    02415
    02416     MinorVersion - Minor version number for Lfs.
    02417
    02418     PackLog - Indicates if we are packing the log file.
    02419
    02420 Return Value:
    02421
    02422     None.
    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     //  Compute the restart page values.
    02438     //
    02439
    02440     Lfcb->SystemPageSize = SystemPageSize;
    02441     Lfcb->SystemPageMask = SystemPageSize - 1;
    02442     Lfcb->SystemPageInverseMask = ~Lfcb->SystemPageMask;
    02443
    02444     //
    02445     //  Do the same for the log pages.
    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     //  If we are packing the log file then the first log page is page
    02468     //  4.  Otherwise it is page 2.  Use the PackLog value to determine the
    02469     //  Usa values.
    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     //  Remember the values for the version numbers.
    02489     //
    02490
    02491     Lfcb->MajorVersion = MajorVersion;
    02492     Lfcb->MinorVersion = MinorVersion;
    02493
    02494     //
    02495     //  Compute the offsets for the update sequence arrays.
    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 }

VOID LfsUpdateLfcbFromRestart | ( | IN OUT PLFCB | Lfcb,
|  | IN PLFS_RESTART_AREA | RestartArea,
|  | IN USHORT | RestartOffset
| ) |

Definition at line 2697 of file lfs/registry.c.

References Add2Ptr, Dbg, DebugTrace, FlagOn, LFCB_LOG_WRAPPED, LFCB_MULTIPLE_PAGE_IO, LFCB_NO_LAST_LSN, LFCB_NO_OLDEST_LSN, LFCB_PACK_LOG, LFCB_REUSE_TAIL, LFS_RECORD_HEADER_SIZE, LfsAllocateLbcb(), LfsFindCurrentAvail(), LfsFindOldestClientLsn(), LfsLsnFinalOffset(), LfsLsnToFileOffset, LfsLsnToSeqNumber, LfsNextLogPageOffset(), LfsTruncateOffsetToLogPage, LSN, PAGED_CODE, QuadAlign, RESTART_SINGLE_PAGE_IO, SetFlag, and UPDATE_SEQUENCE_NUMBER.

Referenced by LfsRestartLogFile().

    02705                    :
    02706
    02707     This routine updates the values in the Lfcb based on data in the
    02708     restart area.
    02709
    02710 Arguments:
    02711
    02712     Lfcb - Log file control block to update.
    02713
    02714     RestartArea - Restart area to use to update the Lfcb.
    02715
    02716     RestartOffset - This is the offset to the restart area in the restart page.
    02717
    02718 Return Value:
    02719
    02720     None.
    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     //  We get the sequence number bits from the restart area and compute the
    02737     //  file data bits.
    02738     //
    02739
    02740     Lfcb->SeqNumberBits = RestartArea->SeqNumberBits;
    02741     Lfcb->FileDataBits = (sizeof( LSN ) * 8) - Lfcb->SeqNumberBits;
    02742
    02743     //
    02744     //  We look at the last flushed Lsn to determine the current sequence count and
    02745     //  the next log page to examine.
    02746     //
    02747
    02748     Lfcb->LastFlushedLsn = RestartArea->CurrentLsn;
    02749
    02750     Lfcb->SeqNumber = LfsLsnToSeqNumber( Lfcb, Lfcb->LastFlushedLsn );
    02751     Lfcb->SeqNumberForWrap = Lfcb->SeqNumber + 1;
    02752
    02753     //
    02754     //  The restart area size depends on the number of clients and whether the
    02755     //  the file is packed.
    02756     //
    02757
    02758     Lfcb->LogClients = RestartArea->LogClients;
    02759
    02760     //
    02761     //  Compute the restart page values from the restart offset.
    02762     //
    02763
    02764     Lfcb->RestartDataOffset = RestartOffset;
    02765     Lfcb->RestartDataSize = (ULONG)Lfcb->SystemPageSize - RestartOffset;
    02766
    02767     //
    02768     //  For a packed log file we can find the following values in the restart
    02769     //  area.  Otherwise we compute them from the current structure sizes.
    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         //  For packed files we allocate the tail Lbcbs.
    02785         //
    02786
    02787         //
    02788         //  Allocate the Lbcb for the tail of the packed log file.
    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         //  Remember the different page sizes for reservation.
    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     //  If the current last flushed Lsn offset is before the first log page
    02821     //  then this is a pseudo Lsn.
    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     //  Otherwise look at the last Lsn to determine where it ends in the file.
    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         //  Find the end of this log record.
    02847         //
    02848
    02849         LfsLsnFinalOffset( Lfcb,
    02850                            Lfcb->LastFlushedLsn,
    02851                            DataLength,
    02852                            &LsnFinalOffset );
    02853
    02854         //
    02855         //  If we wrapped in the file then increment the sequence number.
    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         //  Now compute the next log page to use.  If we are packing the log file
    02867         //  we will attempt to use the same page.
    02868         //
    02869
    02870         LfsTruncateOffsetToLogPage( Lfcb, LsnFinalOffset, &LsnFileOffset );
    02871
    02872         RemainingPageBytes = (ULONG)Lfcb->LogPageSize
    02873                              - ((((ULONG)LsnFinalOffset) & Lfcb->LogPageMask) + 1);
    02874
    02875         //
    02876         //  If we are packing the log file and we can fit another log record on the
    02877         //  page, move back a page in the log file.
    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     //  Find the oldest client Lsn.  Use the last flushed Lsn as a starting point.
    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     //  If there is no oldest client Lsn, then update the flag in the Lfcb.
    02907     //
    02908
    02909     if ( Lfcb->OldestLsnOffset < Lfcb->FirstLogPage ) {
    02910
    02911         SetFlag( Lfcb->Flags, LFCB_NO_OLDEST_LSN );
    02912     }
    02913
    02914     //
    02915     //  We need to determine the flags for the Lfcb.  These flags let us know
    02916     //  if we wrapped in the file and if we are using multiple page I/O.
    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     //  Remember the current open log count from the disk.  We may be plucking random data out
    02926     //  of the client area if the restart area hasn't been grown yet but we will detect that
    02927     //  elsewhere.
    02928     //
    02929
    02930     Lfcb->CurrentOpenLogCount = RestartArea->RestartOpenLogCount;
    02931
    02932     //
    02933     //  The total available log file space is the number of log file pages times
    02934     //  the space available on each page.
    02935     //
    02936
    02937     Lfcb->TotalAvailInPages = Lfcb->FileSize - Lfcb->FirstLogPage;
    02938
    02939     Lfcb->TotalAvailable = Int64ShrlMod32(((ULONGLONG)(Lfcb->TotalAvailInPages)), Lfcb->LogPageShift);
    02940
    02941     //
    02942     //  If the log file is packed we assume that we can't use the end of the
    02943     //  page less than the file record size.  Then we won't need to reserve more
    02944     //  than the caller asks for.
    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 }

VOID LfsUpdateLfcbFromRestart | ( | IN PLFCB | Lfcb,
|  | IN PLFS_RESTART_AREA | RestartArea,
|  | IN USHORT | RestartOffset
| ) |

VOID LfsUpdateRestartAreaFromLfcb | ( | IN PLFCB | Lfcb,
|  | IN PLFS_RESTART_AREA | RestartArea
| ) |

Definition at line 2964 of file lfs/registry.c.

References Add2Ptr, Dbg, DebugTrace, FlagOn, LFCB_MULTIPLE_PAGE_IO, LFS_NO_CLIENT, PAGED_CODE, RESTART_SINGLE_PAGE_IO, SetFlag, and USHORT.

Referenced by LfsInitializeLogFile(), and LfsRestartLogFile().

    02971                    :
    02972
    02973     This routine is called to update a restart area from the values stored
    02974     in the Lfcb.  This is typically done in a case where we won't use
    02975     any of the current values in the restart area.
    02976
    02977 Arguments:
    02978
    02979     Lfcb - Log file control block.
    02980
    02981     RestartArea - Restart area to update.
    02982
    02983 Return Value:
    02984
    02985     None.
    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     //  We can copy most of the fields directly out of Lfcb.
    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     //  We set the in use list as empty and the free list as containing
    03023     //  all of the client entries.
    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     //  We're now at the last client.
    03043     //
    03044
    03045     Client->PrevClient = PrevClient;
    03046     Client->NextClient = LFS_NO_CLIENT;
    03047
    03048     //
    03049     //  Use the current value out of the Lfcb to stamp this usage of the log file.
    03050     //
    03051
    03052     RestartArea->RestartOpenLogCount = Lfcb->CurrentOpenLogCount + 1;
    03053
    03054     DebugTrace( -1, Dbg, "LfsUpdateRestartAreaFromLfcb:  Exit\n", 0 );
    03055
    03056     return;
    03057 }

BOOLEAN LfsVerifyLogFile | ( | IN LFS_LOG_HANDLE | LogHandle,
|  | IN PVOID | LogFileHeader,
|  | IN ULONG | Length
| ) |

Definition at line 1273 of file lfs/registry.c.

References Add2Ptr, _LFCB::CurrentOpenLogCount, FALSE, _LCH::Lfcb, LFS_NTC_LCH, LFS_NTC_LFCB, LFS_SIGNATURE_RESTART_PAGE_ULONG, LfsAcquireLch, LfsReleaseLch, LfsReleaseLfcb, _LFCB::NodeTypeCode, _LCH::NodeTypeCode, NULL, PAGED_CODE, _LFS_RESTART_PAGE_HEADER::RestartOffset, _LFCB::SystemPageSize, and TRUE.

    01281                    :
    01282
    01283     This routine is called by a client to verify that the volume has not been removed
    01284     from the system and then reattached.  We will verify the log file open count on
    01285     disk matches the value in the user's handle.
    01286
    01287 Arguments:
    01288
    01289     LogHandle - Pointer to private Lfs structure used to identify this
    01290                 client.
    01291
    01292     LogFileHeader - Pointer to start of log file.
    01293
    01294     Length - Number bytes returned with the read.
    01295
    01296 Return Value:
    01297
    01298     BOOLEAN - TRUE if the log file has not been altered externally, FALSE if we
    01299         fail for any reason.
    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     //  Check that the structure is a valid log handle structure.
    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     //  Acquire the log file control block for this log file.
    01328     //
    01329
    01330     LfsAcquireLch( Lch );
    01331     Lfcb = Lch->Lfcb;
    01332
    01333     //
    01334     //  If the Log file has been closed then return immediately.
    01335     //
    01336
    01337     if (Lfcb == NULL) {
    01338
    01339         LfsReleaseLch( Lch );
    01340         return FALSE;
    01341     }
    01342
    01343     //
    01344     //  Check that we have at least one page and that the page is valid.
    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 }