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 }


Generated on Sat May 15 19:45:28 2004 for test by doxygen 1.3.7