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

lfsprocs.h File Reference

#include <ntos.h>
#include <string.h>
#include <zwapi.h>
#include <lfs.h>
#include <fsrtl.h>
#include "nodetype.h"
#include "LfsDisk.h"
#include "LfsStruc.h"
#include "LfsData.h"

Go to the source code of this file.

Defines

#define FsRtlAllocatePool(a, b)   FsRtlAllocatePoolWithTag(a,b,' sfL')
#define FsRtlAllocatePoolWithQuota(a, b)   FsRtlAllocatePoolWithQuotaTag(a,b,' sfL')
#define LfsAllocatePoolNoRaise(a, b)   ExAllocatePoolWithTag((a),(b),MODULE_POOL_TAG)
#define LfsAllocatePool(a, b)   ExAllocatePoolWithTag(((a) | POOL_RAISE_IF_ALLOCATION_FAILURE),(b),MODULE_POOL_TAG)
#define LfsFreePool(pv)   ExFreePool(pv)
#define LfsPreparePinWriteData(L, FO, LEN, BUF, B)
#define LfsTruncateOffsetToLogPage(LFCB, LI, OUTLI)
#define LfsLogPageOffset(LFCB, INT)   (INT & (LFCB)->LogPageMask)
#define LfsFileOffsetToLsn(LFCB, FO, SN)
#define LfsIsLsnInFile(LFCB, LSN)
#define LfsComputeLsnFromLbcb(LFCB, LBCB)
#define LfsTruncateLsnToLogPage(LFCB, LSN, FO)
#define LfsLsnToFileOffset(LFCB, LSN)   /*xxShr*/( ((ULONGLONG)/*xxShl*/( (LSN).QuadPart << (LFCB)->SeqNumberBits )) >> ((LFCB)->SeqNumberBits - 3) )
#define LfsLsnToSeqNumber(LFCB, LSN)   /*xxShr*/Int64ShrlMod32( ((ULONGLONG)(LSN).QuadPart), (LFCB)->FileDataBits )
#define LfsLsnToPageOffset(LFCB, LSN)   LfsLogPageOffset( LFCB, (LSN).LowPart << 3 )
#define LfsInitializeLcb(LCB, ID, MODE)
#define LfsAllocateLch(NEW)
#define LfsDeallocateLch(LCH)   ExFreePool( LCH )
#define LfsAllocateRestartArea(RS, SIZE)
#define LfsDeallocateRestartArea(RS)   ExFreePool( RS )
#define LfsLbcbIsRestart(LBCB)   (FlagOn( (LBCB)->LbcbFlags, LBCB_RESTART_LBCB ))
#define LfsAcquireLfsData()   ExAcquireFastMutex( &LfsData.LfsDataLock )
#define LfsReleaseLfsData()   ExReleaseFastMutex( &LfsData.LfsDataLock )
#define LfsAcquireBufferLock()   ExAcquireFastMutex( &LfsData.BufferLock )
#define LfsReleaseBufferLock()   ExReleaseFastMutex( &LfsData.BufferLock )
#define LfsWaitForBufferNotification()
#define LfsNotifyBufferWaiters()   KeSetEvent( &LfsData.BufferNotification, 0, FALSE )
#define LfsBlockBufferWaiters()   KeClearEvent( &LfsData.BufferNotification )
#define LfsAcquireLfcb(LFCB)   ExAcquireResourceExclusive( &(LFCB)->Sync->Resource, TRUE )
#define LfsReleaseLfcb(LFCB)
#define LfsAcquireLch(LCH)   ExAcquireResourceExclusive( &(LCH)->Sync->Resource, TRUE )
#define LfsReleaseLch(LCH)
#define LfsValidateLch(LCH)
#define LfsValidateClientId(LFCB, LCH)
#define LfsVerifyClientLsnInRange(LFCB, CLIENT, LSN)
#define LfsClientIdMatch(CLIENT_A, CLIENT_B)
#define LfsValidateLcb(LCB, LCH)
#define FlagOn(F, SF)
#define BooleanFlagOn(F, SF)
#define SetFlag(Flags, SingleFlag)
#define ClearFlag(Flags, SingleFlag)
#define WordAlign(Ptr)
#define LongAlign(Ptr)
#define QuadAlign(Ptr)
#define LiQuadAlign(LI, OUT)
#define Add2Ptr(PTR, INC, CAST)   ((CAST)((PUCHAR)(PTR) + (INC)))
#define PtrOffset(BASE, OFFSET)   ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE)))
#define try_return(S)   { S; goto try_exit; }

Functions

NTSTATUS LfsPinOrMapData (IN PLFCB Lfcb, IN LONGLONG FileOffset, IN ULONG Length, IN BOOLEAN PinData, IN BOOLEAN AllowErrors, IN BOOLEAN IgnoreUsaErrors, OUT PBOOLEAN UsaError, OUT PVOID *Buffer, OUT PBCB *Bcb)
VOID LfsPinOrMapLogRecordHeader (IN PLFCB Lfcb, IN LSN Lsn, IN BOOLEAN PinData, IN BOOLEAN IgnoreUsaErrors, OUT PBOOLEAN UsaError, OUT PLFS_RECORD_HEADER *RecordHeader, OUT PBCB *Bcb)
VOID LfsCopyReadLogRecord (IN PLFCB Lfcb, IN PLFS_RECORD_HEADER RecordHeader, OUT PVOID Buffer)
VOID LfsFlushLfcb (IN PLFCB Lfcb, IN PLBCB Lbcb)
BOOLEAN LfsReadRestart (IN PLFCB Lfcb, IN LONGLONG FileSize, IN BOOLEAN FirstRestart, OUT PLONGLONG RestartPageOffset, OUT PLFS_RESTART_PAGE_HEADER *RestartPage, OUT PBCB *RestartPageBcb, OUT PBOOLEAN ChkdskWasRun, OUT PBOOLEAN ValidPage, OUT PBOOLEAN UninitializedFile, OUT PBOOLEAN LogPacked, OUT PLSN LastLsn)
VOID LfsFlushLbcb (IN PLFCB Lfcb, IN PLBCB Lbcb)
VOID LfsFlushToLsnPriv (IN PLFCB Lfcb, IN LSN Lsn)
PLBCB LfsGetLbcb (IN PLFCB Lfcb)
LONG LfsExceptionFilter (IN PEXCEPTION_POINTERS ExceptionPointer)
VOID LfsNextLogPageOffset (IN PLFCB Lfcb, IN LONGLONG CurrentLogPageOffset, OUT PLONGLONG NextLogPageOffset, OUT PBOOLEAN Wrapped)
PVOID LfsAllocateSpanningBuffer (IN PLFCB Lfcb, IN ULONG Length)
VOID LfsFreeSpanningBuffer (IN PVOID Buffer)
BOOLEAN LfsWriteLogRecordIntoLogPage (IN PLFCB Lfcb, IN PLCH Lch, IN ULONG NumberOfWriteEntries, IN PLFS_WRITE_ENTRY WriteEntries, IN LFS_RECORD_TYPE RecordType, IN TRANSACTION_ID *TransactionId OPTIONAL, IN LSN ClientUndoNextLsn OPTIONAL, IN LSN ClientPreviousLsn OPTIONAL, IN LONG UndoRequirement, IN BOOLEAN ForceToDisk, OUT PLSN Lsn)
VOID LfsLsnFinalOffset (IN PLFCB Lfcb, IN LSN Lsn, IN ULONG DataLength, OUT PLONGLONG FinalOffset)
BOOLEAN LfsFindNextLsn (IN PLFCB Lfcb, IN PLFS_RECORD_HEADER RecordHeader, OUT PLSN Lsn)
VOID LfsWriteLfsRestart (IN PLFCB Lfcb, IN ULONG ThisRestartSize, IN BOOLEAN WaitForIo)
VOID LfsFindOldestClientLsn (IN PLFS_RESTART_AREA RestartArea, IN PLFS_CLIENT_RECORD ClientArray, OUT PLSN OldestLsn)
PLFCB LfsAllocateLfcb ()
VOID LfsDeallocateLfcb (IN PLFCB Lfcb, IN BOOLEAN CompleteTeardown)
VOID LfsAllocateLbcb (IN PLFCB Lfcb, OUT PLBCB *Lbcb)
VOID LfsDeallocateLbcb (IN PLFCB Lfcb, IN PLBCB Lbcb)
VOID LfsAllocateLcb (IN PLFCB Lfcb, OUT PLCB *NewLcb)
VOID LfsDeallocateLcb (IN PLFCB Lfcb, IN PLCB Lcb)
VOID LfsCurrentAvailSpace (IN PLFCB Lfcb, OUT PLONGLONG CurrentAvailSpace, OUT PULONG CurrentPageBytes)
BOOLEAN LfsVerifyLogSpaceAvail (IN PLFCB Lfcb, IN PLCH Lch, IN ULONG RemainingLogBytes, IN LONG UndoRequirement, IN BOOLEAN ForceToDisk)
VOID LfsFindCurrentAvail (IN PLFCB Lfcb)


Define Documentation

#define Add2Ptr PTR,
INC,
CAST   )     ((CAST)((PUCHAR)(PTR) + (INC)))
 

Definition at line 721 of file lfsprocs.h.

#define BooleanFlagOn F,
SF   ) 
 

Value:

( \ (BOOLEAN)(((F) & (SF)) != 0) \ )

Definition at line 658 of file lfsprocs.h.

#define ClearFlag Flags,
SingleFlag   ) 
 

Value:

{ \ (Flags) &= ~(SingleFlag); \ }

Definition at line 666 of file lfsprocs.h.

#define FlagOn F,
SF   ) 
 

Value:

( \ (((F) & (SF))) \ )

Definition at line 654 of file lfsprocs.h.

#define FsRtlAllocatePool a,
 )     FsRtlAllocatePoolWithTag(a,b,' sfL')
 

Definition at line 43 of file lfsprocs.h.

#define FsRtlAllocatePoolWithQuota a,
 )     FsRtlAllocatePoolWithQuotaTag(a,b,' sfL')
 

Definition at line 44 of file lfsprocs.h.

 
#define LfsAcquireBufferLock  )     ExAcquireFastMutex( &LfsData.BufferLock )
 

Definition at line 490 of file lfsprocs.h.

Referenced by LfsAllocateSpanningBuffer(), and LfsFreeSpanningBuffer().

#define LfsAcquireLch LCH   )     ExAcquireResourceExclusive( &(LCH)->Sync->Resource, TRUE )
 

Definition at line 517 of file lfsprocs.h.

Referenced by LfsCloseLogFile(), LfsDeleteLogHandle(), LfsFlushToLsn(), LfsForceWrite(), LfsQueryLastLsn(), LfsReadLogFileInformation(), LfsReadLogRecord(), LfsReadNextLogRecord(), LfsReadRestartArea(), LfsResetUndoTotal(), LfsSetBaseLsn(), LfsTerminateLogQuery(), LfsVerifyLogFile(), LfsWrite(), and LfsWriteRestartArea().

#define LfsAcquireLfcb LFCB   )     ExAcquireResourceExclusive( &(LFCB)->Sync->Resource, TRUE )
 

Definition at line 509 of file lfsprocs.h.

Referenced by LfsAllocateSpanningBuffer(), LfsCloseLogFile(), LfsFlushLbcb(), LfsFlushLfcb(), LfsInitializeLogFile(), LfsRestartLogFile(), and LfsWriteLogRecordIntoLogPage().

 
#define LfsAcquireLfsData  )     ExAcquireFastMutex( &LfsData.LfsDataLock )
 

Definition at line 484 of file lfsprocs.h.

Referenced by LfsCloseLogFile(), LfsInitializeLogFile(), and LfsOpenLogFile().

#define LfsAllocateLch NEW   ) 
 

Value:

{ \ *(NEW) = FsRtlAllocatePool( PagedPool, sizeof( LCH )); \ RtlZeroMemory( (*NEW), sizeof( LCH )); \ (*(NEW))->NodeTypeCode = LFS_NTC_LCH; \ (*(NEW))->NodeByteSize = sizeof( LCH ); \ }

Definition at line 428 of file lfsprocs.h.

Referenced by LfsOpenLogFile().

#define LfsAllocatePool a,
 )     ExAllocatePoolWithTag(((a) | POOL_RAISE_IF_ALLOCATION_FAILURE),(b),MODULE_POOL_TAG)
 

Definition at line 47 of file lfsprocs.h.

#define LfsAllocatePoolNoRaise a,
 )     ExAllocatePoolWithTag((a),(b),MODULE_POOL_TAG)
 

Definition at line 46 of file lfsprocs.h.

Referenced by LfsAllocateSpanningBuffer(), and LfsInitializeLogFileService().

#define LfsAllocateRestartArea RS,
SIZE   ) 
 

Value:

*(RS) = FsRtlAllocatePool( PagedPool, (SIZE) ); \ RtlZeroMemory( *(RS), (SIZE) )

Definition at line 438 of file lfsprocs.h.

Referenced by LfsInitializeLogFile(), LfsRestartLogFile(), and LfsWriteLfsRestart().

 
#define LfsBlockBufferWaiters  )     KeClearEvent( &LfsData.BufferNotification )
 

Definition at line 506 of file lfsprocs.h.

Referenced by LfsAllocateSpanningBuffer().

#define LfsClientIdMatch CLIENT_A,
CLIENT_B   ) 
 

Value:

((BOOLEAN) ((CLIENT_A)->SeqNumber == (CLIENT_B)->SeqNumber \ && (CLIENT_A)->ClientIndex == (CLIENT_B)->ClientIndex))

Definition at line 607 of file lfsprocs.h.

Referenced by LfsSearchForwardByClient().

#define LfsComputeLsnFromLbcb LFCB,
LBCB   ) 
 

Value:

( \ LfsFileOffsetToLsn( LFCB, \ (LBCB)->FileOffset + (LBCB)->BufferOffset, \ (LBCB)->SeqNumber ) \ )

Definition at line 291 of file lfsprocs.h.

Referenced by LfsWriteLogRecordIntoLogPage().

#define LfsDeallocateLch LCH   )     ExFreePool( LCH )
 

Definition at line 435 of file lfsprocs.h.

Referenced by LfsDeleteLogHandle(), and LfsOpenLogFile().

#define LfsDeallocateRestartArea RS   )     ExFreePool( RS )
 

Definition at line 442 of file lfsprocs.h.

Referenced by LfsDeallocateLbcb(), LfsDeallocateLfcb(), LfsInitializeLogFile(), and LfsRestartLogFile().

#define LfsFileOffsetToLsn LFCB,
FO,
SN   ) 
 

Value:

( \ (((ULONGLONG)(FO)) >> 3) + Int64ShllMod32((SN), (LFCB)->FileDataBits) \ )

Definition at line 283 of file lfsprocs.h.

Referenced by LfsFindNextLsn(), and LfsUpdateLfcbFromNoRestart().

#define LfsFreePool pv   )     ExFreePool(pv)
 

Definition at line 48 of file lfsprocs.h.

Referenced by LfsFreeSpanningBuffer(), and LfsInitializeLogFileService().

#define LfsInitializeLcb LCB,
ID,
MODE   ) 
 

Value:

(LCB)->ClientId = ID; \ (LCB)->ContextMode = MODE

Definition at line 423 of file lfsprocs.h.

Referenced by LfsReadLogRecord().

#define LfsIsLsnInFile LFCB,
LSN   ) 
 

Value:

(/*xxGeq*/( (LSN).QuadPart >= ((LFCB)->OldestLsn).QuadPart ) \ && /*xxLeq*/( (LSN).QuadPart <= ((LFCB)->RestartArea->CurrentLsn).QuadPart ))

Definition at line 287 of file lfsprocs.h.

Referenced by LfsFindNextLsn().

#define LfsLbcbIsRestart LBCB   )     (FlagOn( (LBCB)->LbcbFlags, LBCB_RESTART_LBCB ))
 

Definition at line 445 of file lfsprocs.h.

Referenced by LfsCloseLogFile(), LfsFindFirstIo(), LfsFlushLbcb(), and LfsFlushToLsnPriv().

#define LfsLogPageOffset LFCB,
INT   )     (INT & (LFCB)->LogPageMask)
 

Definition at line 188 of file lfsprocs.h.

#define LfsLsnToFileOffset LFCB,
LSN   )     /*xxShr*/( ((ULONGLONG)/*xxShl*/( (LSN).QuadPart << (LFCB)->SeqNumberBits )) >> ((LFCB)->SeqNumberBits - 3) )
 

Definition at line 302 of file lfsprocs.h.

Referenced by LfsFindNextLsn(), LfsSetBaseLsnPriv(), and LfsUpdateLfcbFromRestart().

#define LfsLsnToPageOffset LFCB,
LSN   )     LfsLogPageOffset( LFCB, (LSN).LowPart << 3 )
 

Definition at line 308 of file lfsprocs.h.

Referenced by LfsCopyReadLogRecord(), LfsFindLogRecord(), LfsLsnFinalOffset(), and LfsPinOrMapLogRecordHeader().

#define LfsLsnToSeqNumber LFCB,
LSN   )     /*xxShr*/Int64ShrlMod32( ((ULONGLONG)(LSN).QuadPart), (LFCB)->FileDataBits )
 

Definition at line 305 of file lfsprocs.h.

Referenced by LfsCheckSubsequentLogPage(), LfsFindLastLsn(), LfsFindNextLsn(), LfsUpdateLfcbFromNoRestart(), and LfsUpdateLfcbFromRestart().

 
#define LfsNotifyBufferWaiters  )     KeSetEvent( &LfsData.BufferNotification, 0, FALSE )
 

Definition at line 503 of file lfsprocs.h.

Referenced by LfsFreeSpanningBuffer().

#define LfsPreparePinWriteData L,
FO,
LEN,
BUF,
 ) 
 

Value:

{ \ LONGLONG _LocalFileOffset = (FO); \ CcPreparePinWrite( (L)->FileObject, \ (PLARGE_INTEGER)&_LocalFileOffset, \ (LEN), \ FALSE, \ TRUE, \ (B), \ (BUF) ); \ }

Definition at line 80 of file lfsprocs.h.

Referenced by LfsFlushLfcb(), and LfsGetLbcb().

 
#define LfsReleaseBufferLock  )     ExReleaseFastMutex( &LfsData.BufferLock )
 

Definition at line 493 of file lfsprocs.h.

Referenced by LfsAllocateSpanningBuffer(), and LfsFreeSpanningBuffer().

#define LfsReleaseLch LCH   ) 
 

Value:

if ((LCH)->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) { \ ExReleaseResource( &(LCH)->Sync->Resource ); \ }

Definition at line 520 of file lfsprocs.h.

Referenced by LfsCloseLogFile(), LfsDeleteLogHandle(), LfsFlushToLsn(), LfsForceWrite(), LfsQueryLastLsn(), LfsReadLogFileInformation(), LfsReadLogRecord(), LfsReadNextLogRecord(), LfsReadRestartArea(), LfsResetUndoTotal(), LfsSetBaseLsn(), LfsTerminateLogQuery(), LfsVerifyLogFile(), LfsWrite(), and LfsWriteRestartArea().

#define LfsReleaseLfcb LFCB   ) 
 

Value:

if ((LFCB)->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) {\ ExReleaseResource( &(LFCB)->Sync->Resource ); \ }

Definition at line 512 of file lfsprocs.h.

Referenced by LfsAllocateSpanningBuffer(), LfsCloseLogFile(), LfsFlushLbcb(), LfsFlushLfcb(), LfsInitializeLogFile(), LfsOpenLogFile(), LfsReadNextLogRecord(), LfsReadRestartArea(), LfsRestartLogFile(), LfsVerifyLogFile(), and LfsWriteLogRecordIntoLogPage().

 
#define LfsReleaseLfsData  )     ExReleaseFastMutex( &LfsData.LfsDataLock )
 

Definition at line 487 of file lfsprocs.h.

Referenced by LfsCloseLogFile(), LfsInitializeLogFile(), and LfsOpenLogFile().

#define LfsTruncateLsnToLogPage LFCB,
LSN,
FO   ) 
 

Value:

{ \ *(FO) = LfsLsnToFileOffset( LFCB, LSN ); \ *((PULONG)(FO)) &= (LFCB)->LogPageInverseMask; \ }

Definition at line 297 of file lfsprocs.h.

Referenced by LfsCheckSubsequentLogPage(), LfsCopyReadLogRecord(), LfsLsnFinalOffset(), and LfsPinOrMapLogRecordHeader().

#define LfsTruncateOffsetToLogPage LFCB,
LI,
OUTLI   ) 
 

Value:

*(OUTLI) = LI; \ *((PULONG)(OUTLI)) &= (LFCB)->SystemPageInverseMask

Definition at line 184 of file lfsprocs.h.

Referenced by LfsFindCurrentAvail(), LfsFindNextLsn(), LfsNextLogPageOffset(), and LfsUpdateLfcbFromRestart().

#define LfsValidateClientId LFCB,
LCH   ) 
 

Value:

if ((LCH)->ClientId.ClientIndex >= (LFCB)->RestartArea->LogClients \ || (LCH)->ClientId.SeqNumber \ != Add2Ptr( Lfcb->ClientArray, \ (LCH)->ClientArrayByteOffset, \ PLFS_CLIENT_RECORD )->SeqNumber) { \ ExRaiseStatus( STATUS_ACCESS_DENIED ); \ }

Definition at line 593 of file lfsprocs.h.

Referenced by LfsCloseLogFile(), LfsFlushToLsn(), LfsForceWrite(), LfsQueryLastLsn(), LfsReadLogFileInformation(), LfsReadLogRecord(), LfsReadNextLogRecord(), LfsReadRestartArea(), LfsResetUndoTotal(), LfsSetBaseLsn(), LfsTerminateLogQuery(), LfsWrite(), and LfsWriteRestartArea().

#define LfsValidateLcb LCB,
LCH   ) 
 

Value:

if (LCB == NULL \ || (LCB)->NodeTypeCode != LFS_NTC_LCB \ || !LfsClientIdMatch( &(LCB)->ClientId, &(LCH)->ClientId )) { \ ExRaiseStatus( STATUS_ACCESS_DENIED ); \ }

Definition at line 611 of file lfsprocs.h.

Referenced by LfsReadNextLogRecord(), and LfsTerminateLogQuery().

#define LfsValidateLch LCH   ) 
 

Value:

if ((LCH) == NULL \ || (LCH)->NodeTypeCode != LFS_NTC_LCH \ || ((LCH)->Lfcb != NULL \ && (LCH)->Lfcb->NodeTypeCode != LFS_NTC_LFCB)) { \ \ ExRaiseStatus( STATUS_ACCESS_DENIED ); \ }

Definition at line 584 of file lfsprocs.h.

Referenced by LfsCloseLogFile(), LfsFlushToLsn(), LfsForceWrite(), LfsQueryLastLsn(), LfsReadLogFileInformation(), LfsReadLogRecord(), LfsReadNextLogRecord(), LfsReadRestartArea(), LfsResetUndoTotal(), LfsSetBaseLsn(), LfsTerminateLogQuery(), LfsWrite(), and LfsWriteRestartArea().

#define LfsVerifyClientLsnInRange LFCB,
CLIENT,
LSN   ) 
 

Value:

(/*xxGeq*/( (LSN).QuadPart >= ((CLIENT)->OldestLsn).QuadPart ) \ && /*xxLeq*/( (LSN).QuadPart <= ((LFCB)->RestartArea->CurrentLsn).QuadPart ) \ && /*xxNeqZero*/( (LSN).QuadPart != 0 ))

Definition at line 602 of file lfsprocs.h.

Referenced by LfsFindClientNextLsn(), and LfsReadLogRecord().

 
#define LfsWaitForBufferNotification  ) 
 

Value:

KeWaitForSingleObject( &LfsData.BufferNotification, \ Executive, \ KernelMode, \ FALSE, \ NULL )

Definition at line 496 of file lfsprocs.h.

Referenced by LfsAllocateSpanningBuffer().

#define LiQuadAlign LI,
OUT   ) 
 

Value:

{ \ *(OUT) = /*xxAdd*/( (LI) + 7 ); \ *((PULONG)(OUT)) &= 0xfffffff8; \ }

Definition at line 701 of file lfsprocs.h.

Referenced by LfsFindNextLsn().

#define LongAlign Ptr   ) 
 

Value:

( \ ((((ULONG)(Ptr)) + 3) & 0xfffffffc) \ )

Definition at line 684 of file lfsprocs.h.

#define PtrOffset BASE,
OFFSET   )     ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE)))
 

Definition at line 723 of file lfsprocs.h.

#define QuadAlign Ptr   ) 
 

Value:

( \ ((((ULONG)(Ptr)) + 7) & 0xfffffff8) \ )

Definition at line 693 of file lfsprocs.h.

#define SetFlag Flags,
SingleFlag   ) 
 

Value:

{ \ (Flags) |= (SingleFlag); \ }

Definition at line 662 of file lfsprocs.h.

#define try_return  )     { S; goto try_exit; }
 

Definition at line 754 of file lfsprocs.h.

#define WordAlign Ptr   ) 
 

Value:

( \ ((((ULONG)(Ptr)) + 1) & 0xfffffffe) \ )

Definition at line 675 of file lfsprocs.h.


Function Documentation

VOID LfsAllocateLbcb IN PLFCB  Lfcb,
OUT PLBCB Lbcb
 

Definition at line 315 of file lfs/strucsup.c.

References ExAllocatePoolWithTag, ExRaiseStatus(), LBCB, LFCB_RESERVE_LBCB_COUNT, LFS_NTC_LBCB, _LBCB::NodeByteSize, _LBCB::NodeTypeCode, NULL, PAGED_CODE, and PagedPool.

Referenced by LfsGetLbcb(), LfsUpdateLfcbFromNoRestart(), LfsUpdateLfcbFromRestart(), and LfsWriteLfsRestart().

00322 : 00323 00324 This routine will allocate the next Lbcb. If the pool allocation fails 00325 we will look at the private queue of Lbcb's. 00326 00327 Arguments: 00328 00329 Lfcb - Supplies a pointer to the log file control block. 00330 00331 Lbcb - Address to store the allocated Lbcb. 00332 00333 Return Value: 00334 00335 None 00336 00337 --*/ 00338 00339 { 00340 PLBCB NewLbcb = NULL; 00341 00342 PAGED_CODE(); 00343 00344 // 00345 // If there are enough entries on the look-aside list then get one from 00346 // there. 00347 // 00348 00349 if (Lfcb->SpareLbcbCount > LFCB_RESERVE_LBCB_COUNT) { 00350 00351 NewLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink; 00352 00353 Lfcb->SpareLbcbCount -= 1; 00354 RemoveHeadList( &Lfcb->SpareLbcbList ); 00355 00356 // 00357 // Otherwise try to allocate from pool. 00358 // 00359 00360 } else { 00361 00362 NewLbcb = ExAllocatePoolWithTag( PagedPool, sizeof( LBCB ), ' sfL' ); 00363 } 00364 00365 // 00366 // If we didn't get one then look at the look-aside list. 00367 // 00368 00369 if (NewLbcb == NULL) { 00370 00371 if (Lfcb->SpareLbcbCount != 0) { 00372 00373 NewLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink; 00374 00375 Lfcb->SpareLbcbCount -= 1; 00376 RemoveHeadList( &Lfcb->SpareLbcbList ); 00377 00378 } else { 00379 00380 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00381 } 00382 } 00383 00384 // 00385 // Initialize the structure. 00386 // 00387 00388 RtlZeroMemory( NewLbcb, sizeof( LBCB )); 00389 NewLbcb->NodeTypeCode = LFS_NTC_LBCB; 00390 NewLbcb->NodeByteSize = sizeof( LBCB ); 00391 00392 // 00393 // Return it to the user. 00394 // 00395 00396 *Lbcb = NewLbcb; 00397 return; 00398 }

VOID LfsAllocateLcb IN PLFCB  Lfcb,
OUT PLCB NewLcb
 

Definition at line 463 of file lfs/strucsup.c.

References ExAllocatePoolWithTag, ExRaiseStatus(), LCB, LFCB_RESERVE_LCB_COUNT, LFS_NTC_LCB, NULL, and PagedPool.

Referenced by LfsReadLogRecord().

00469 : 00470 00471 This routine will allocate an Lcb. If the pool fails we will fall back 00472 on our spare list. A failure then will result in an exception 00473 00474 Arguments: 00475 00476 Lfcb - Supplies a pointer to the log file control block. 00477 00478 Lcb - This will contain the new lcb 00479 00480 Return Value: 00481 00482 None 00483 00484 --*/ 00485 { 00486 00487 ExAcquireFastMutex( &(Lfcb->Sync->SpareListMutex) ); 00488 00489 try { 00490 00491 *NewLcb = NULL; 00492 if (Lfcb->SpareLcbCount < LFCB_RESERVE_LCB_COUNT) { 00493 (*NewLcb) = ExAllocatePoolWithTag( PagedPool, sizeof( LCB ), ' sfL' ); 00494 } 00495 00496 if ((*NewLcb) == NULL) { 00497 if (Lfcb->SpareLcbCount > 0) { 00498 *NewLcb = (PLCB) Lfcb->SpareLcbList.Flink; 00499 Lfcb->SpareLcbCount -= 1; 00500 RemoveHeadList( &Lfcb->SpareLcbList ); 00501 } else { 00502 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00503 } 00504 } 00505 00506 RtlZeroMemory( (*NewLcb), sizeof( LCB ) ); 00507 (*NewLcb)->NodeTypeCode = LFS_NTC_LCB; 00508 (*NewLcb)->NodeByteSize = sizeof( LCB ); 00509 00510 } finally { 00511 ExReleaseFastMutex( &(Lfcb->Sync->SpareListMutex) ); 00512 } 00513 }

PLFCB LfsAllocateLfcb  ) 
 

Definition at line 41 of file lfs/strucsup.c.

References Count, Dbg, DebugTrace, DebugUnwind, _LFCB_SYNC::Event, ExAllocatePoolWithTag, ExInitializeFastMutex, ExInitializeResource, FsRtlAllocatePool, KeInitializeEvent, _LFCB::LbcbActive, _LFCB::LbcbWorkque, _LFCB::LchLinks, LFCB, LFCB_RESERVE_LBCB_COUNT, LFCB_RESERVE_LCB_COUNT, LFS_NTC_LFCB, LfsDeallocateLfcb(), LfsLi1, _LFCB::NextRestartLsn, _LFCB::NodeByteSize, _LFCB::NodeTypeCode, NonPagedPool, NULL, PAGED_CODE, PagedPool, _LFCB_SYNC::Resource, _LFCB::SpareLbcbCount, _LFCB::SpareLbcbList, _LFCB::SpareLcbCount, _LFCB::SpareLcbList, _LFCB_SYNC::SpareListMutex, _LFCB::Sync, TRUE, and _LFCB_SYNC::UserCount.

Referenced by LfsInitializeLogFile(), and LfsRestartLogFile().

00046 : 00047 00048 This routine allocates and initializes a log file control block. 00049 00050 Arguments: 00051 00052 Return Value: 00053 00054 PLFCB - A pointer to the log file control block just 00055 allocated and initialized. 00056 00057 --*/ 00058 00059 { 00060 PLFCB Lfcb = NULL; 00061 ULONG Count; 00062 PLBCB NextLbcb; 00063 PLCB NextLcb; 00064 00065 PAGED_CODE(); 00066 00067 DebugTrace( +1, Dbg, "LfsAllocateLfcb: Entered\n", 0 ); 00068 00069 // 00070 // Use a try-finally to facilitate cleanup. 00071 // 00072 00073 try { 00074 00075 // 00076 // Allocate and zero the structure for the Lfcb. 00077 // 00078 00079 Lfcb = FsRtlAllocatePool( PagedPool, sizeof( LFCB )); 00080 00081 // 00082 // Zero out the structure initially. 00083 // 00084 00085 RtlZeroMemory( Lfcb, sizeof( LFCB )); 00086 00087 // 00088 // Initialize the log file control block. 00089 // 00090 00091 Lfcb->NodeTypeCode = LFS_NTC_LFCB; 00092 Lfcb->NodeByteSize = sizeof( LFCB ); 00093 00094 // 00095 // Initialize the client links. 00096 // 00097 00098 InitializeListHead( &Lfcb->LchLinks ); 00099 00100 // 00101 // Initialize the Lbcb links. 00102 // 00103 00104 InitializeListHead( &Lfcb->LbcbWorkque ); 00105 InitializeListHead( &Lfcb->LbcbActive ); 00106 00107 // 00108 // Initialize and allocate the spare Lbcb queue. 00109 // 00110 00111 InitializeListHead( &Lfcb->SpareLbcbList ); 00112 00113 for (Count = 0; Count < LFCB_RESERVE_LBCB_COUNT; Count++) { 00114 00115 NextLbcb = ExAllocatePoolWithTag( PagedPool, sizeof( LBCB ), ' sfL' ); 00116 00117 if (NextLbcb != NULL) { 00118 00119 InsertHeadList( &Lfcb->SpareLbcbList, (PLIST_ENTRY) NextLbcb ); 00120 Lfcb->SpareLbcbCount += 1; 00121 } 00122 } 00123 00124 // 00125 // Initialize and allocate the spare Lcb queue. 00126 // 00127 00128 InitializeListHead( &Lfcb->SpareLcbList ); 00129 00130 for (Count = 0; Count < LFCB_RESERVE_LCB_COUNT; Count++) { 00131 00132 NextLcb = ExAllocatePoolWithTag( PagedPool, sizeof( LCB ), ' sfL' ); 00133 00134 if (NextLcb != NULL) { 00135 00136 InsertHeadList( &Lfcb->SpareLcbList, (PLIST_ENTRY) NextLcb ); 00137 Lfcb->SpareLcbCount += 1; 00138 } 00139 } 00140 00141 // 00142 // Allocate the Lfcb synchronization event. 00143 // 00144 00145 Lfcb->Sync = FsRtlAllocatePool( NonPagedPool, sizeof( LFCB_SYNC )); 00146 00147 ExInitializeResource( &Lfcb->Sync->Resource ); 00148 00149 // 00150 // Initialize the pseudo Lsn for the restart Lbcb's 00151 // 00152 00153 Lfcb->NextRestartLsn = LfsLi1; 00154 00155 // 00156 // Initialize the event to the signalled state. 00157 // 00158 00159 KeInitializeEvent( &Lfcb->Sync->Event, NotificationEvent, TRUE ); 00160 00161 Lfcb->Sync->UserCount = 0; 00162 00163 // 00164 // Initialize the spare list mutex 00165 // 00166 00167 ExInitializeFastMutex( &(Lfcb->Sync->SpareListMutex) ); 00168 00169 } finally { 00170 00171 DebugUnwind( LfsAllocateFileControlBlock ); 00172 00173 if (AbnormalTermination() 00174 && Lfcb != NULL) { 00175 00176 LfsDeallocateLfcb( Lfcb, TRUE ); 00177 Lfcb = NULL; 00178 } 00179 00180 DebugTrace( -1, Dbg, "LfsAllocateLfcb: Exit -> %08lx\n", Lfcb ); 00181 } 00182 00183 return Lfcb; 00184 }

PVOID LfsAllocateSpanningBuffer IN PLFCB  Lfcb,
IN ULONG  Length
 

Definition at line 113 of file logpgsup.c.

References ASSERT, _LFS_DATA::Buffer1, _LFS_DATA::Buffer2, _LFS_DATA::BufferFlags, _LFS_DATA::BufferOwner, Dbg, DebugTrace, ERESOURCE_THREAD, ExGetCurrentResourceThread, ExRaiseStatus(), FALSE, FlagOn, LFS_BUFFER1_OWNED, LFS_BUFFER2_OWNED, LFS_BUFFER_SIZE, LfsAcquireBufferLock, LfsAcquireLfcb, LfsAllocatePoolNoRaise, LfsBlockBufferWaiters, LfsData, LfsReleaseBufferLock, LfsReleaseLfcb, LfsWaitForBufferNotification, NULL, PAGED_CODE, PagedPool, SetFlag, and TRUE.

Referenced by LfsFindLogRecord().

00120 : 00121 00122 This routine is called to allocate a spare buffer to read a file record 00123 which spans a log page. We will first try to allocate one. If that 00124 fails we will use one of the existing spare buffers. If that fails then 00125 we will raise. 00126 00127 Arguments: 00128 00129 Lfcb - This is the file control block for the log file. 00130 00131 Length - Length of the buffer required. 00132 00133 Return Value: 00134 00135 PVOID - Pointer to the buffer to use for reading the log record. 00136 May be either from pool or from the auxilary buffer pool. 00137 00138 --*/ 00139 00140 { 00141 PVOID NewBuffer = NULL; 00142 ERESOURCE_THREAD Thread; 00143 BOOLEAN Wait = FALSE; 00144 00145 PAGED_CODE(); 00146 00147 DebugTrace( +1, Dbg, "LfsAllocateSpanningBuffer: Entered\n", 0 ); 00148 00149 // 00150 // Loop while we don't have a buffer. First try to get our reserved buffer 00151 // without waiting. Then try to allocate a buffer. Finally wait for the reserved 00152 // buffer as the final alternative. 00153 // 00154 00155 do { 00156 00157 // 00158 // Skip the reserved buffer if the request is larger than we can read into it. 00159 // 00160 00161 if (Length <= LFS_BUFFER_SIZE) { 00162 00163 // 00164 // If this thread already owns one buffer it can get the second directly. 00165 // 00166 00167 Thread = ExGetCurrentResourceThread(); 00168 00169 if (Thread == LfsData.BufferOwner) { 00170 00171 if (!FlagOn( LfsData.BufferFlags, LFS_BUFFER1_OWNED )) { 00172 00173 SetFlag( LfsData.BufferFlags, LFS_BUFFER1_OWNED ); 00174 NewBuffer = LfsData.Buffer1; 00175 break; 00176 00177 } else if (!FlagOn( LfsData.BufferFlags, LFS_BUFFER2_OWNED )) { 00178 00179 SetFlag( LfsData.BufferFlags, LFS_BUFFER2_OWNED ); 00180 NewBuffer = LfsData.Buffer2; 00181 break; 00182 00183 } else if (Wait) { 00184 00185 // 00186 // This shouldn't happen but handle anyway. 00187 // 00188 00189 DebugTrace( -1, Dbg, "LfsAllocateSpanningBuffer: Exit\n", 0 ); 00190 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00191 } 00192 00193 // 00194 // Otherwise acquire the buffer lock and check the state of the buffers. 00195 // 00196 00197 } else { 00198 00199 BOOLEAN LfcbOwned = TRUE; 00200 00201 while (TRUE) { 00202 00203 LfsAcquireBufferLock(); 00204 00205 // 00206 // Check to see if the buffers are available. No 00207 // need to drop the Lfcb in the typical case. 00208 // 00209 00210 if (LfsData.BufferOwner == (ERESOURCE_THREAD) NULL) { 00211 00212 ASSERT( !FlagOn( LfsData.BufferFlags, LFS_BUFFER1_OWNED | LFS_BUFFER2_OWNED )); 00213 NewBuffer = LfsData.Buffer1; 00214 LfsData.BufferOwner = Thread; 00215 SetFlag( LfsData.BufferFlags, LFS_BUFFER1_OWNED ); 00216 LfsBlockBufferWaiters(); 00217 00218 // 00219 // Reacquire the Lfcb if needed. 00220 // 00221 00222 if (!LfcbOwned) { 00223 00224 LfsAcquireLfcb( Lfcb ); 00225 } 00226 00227 // 00228 // Break out. 00229 // 00230 00231 LfsReleaseBufferLock(); 00232 break; 00233 } 00234 00235 // 00236 // Release the Lfcb and wait on the notification for the buffers. 00237 // 00238 00239 if (Wait) { 00240 00241 if (LfcbOwned) { 00242 LfsReleaseLfcb( Lfcb ); 00243 LfcbOwned = FALSE; 00244 } 00245 00246 LfsReleaseBufferLock(); 00247 LfsWaitForBufferNotification(); 00248 00249 } else { 00250 00251 // 00252 // Go ahead and try to allocate a buffer from pool next. 00253 // 00254 00255 LfsReleaseBufferLock(); 00256 break; 00257 } 00258 } 00259 } 00260 00261 // 00262 // Raise if we already tried the allocate path. 00263 // 00264 00265 } else if (Wait) { 00266 00267 DebugTrace( -1, Dbg, "LfsAllocateSpanningBuffer: Exit\n", 0 ); 00268 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00269 } 00270 00271 // 00272 // Try pool if we didn't get a buffer above. 00273 // 00274 00275 if (NewBuffer == NULL) { 00276 00277 // 00278 // Try pool next but don't let this fail on pool allocation. 00279 // 00280 00281 NewBuffer = LfsAllocatePoolNoRaise( PagedPool, Length ); 00282 } 00283 00284 // 00285 // Wait on the next pass through the loop. 00286 // 00287 00288 Wait = TRUE; 00289 00290 } while (NewBuffer == NULL); 00291 00292 DebugTrace( -1, Dbg, "LfsAllocateSpanningBuffer: Exit\n", 0 ); 00293 return NewBuffer; 00294 }

VOID LfsCopyReadLogRecord IN PLFCB  Lfcb,
IN PLFS_RECORD_HEADER  RecordHeader,
OUT PVOID  Buffer
 

Definition at line 339 of file lfs/cachesup.c.

References Add2Ptr, Buffer, CcUnpinData(), Dbg, DebugTrace, ExRaiseStatus(), FALSE, FlagOn, LFCB_PACK_LOG, LfsLsnToPageOffset, LfsNextLogPageOffset(), LfsPinOrMapData(), LfsTruncateLsnToLogPage, LOG_PAGE_LOG_RECORD_END, NULL, PAGED_CODE, and TRUE.

Referenced by LfsFindLogRecord(), and LfsReadRestartArea().

00347 : 00348 00349 This routines copies a log record from the file to a buffer. The log 00350 record may span several log pages and may even wrap in the file. 00351 00352 Arguments: 00353 00354 Lfcb - A pointer to the control block for the log file. 00355 00356 RecordHeader - Pointer to the log record header for this log record. 00357 00358 Buffer - Pointer to the buffer to store the log record. 00359 00360 Return Value: 00361 00362 None. 00363 00364 --*/ 00365 00366 { 00367 PBCB Bcb = NULL; 00368 BOOLEAN UsaError; 00369 00370 PLFS_RECORD_PAGE_HEADER PageHeader; 00371 00372 LONGLONG LogPageFileOffset; 00373 ULONG LogPageOffset; 00374 00375 ULONG RemainingTransferBytes; 00376 00377 PAGED_CODE(); 00378 00379 DebugTrace( +1, Dbg, "LfsCopyReadLogRecord: Entered\n", 0 ); 00380 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00381 DebugTrace( 0, Dbg, "RecordHeader -> %08lx\n", RecordHeader ); 00382 DebugTrace( 0, Dbg, "Buffer -> %08lx\n", Buffer ); 00383 00384 // 00385 // We find the file offset of the log page containing the start of 00386 // this log record, the offset within the page to start the transfer from, 00387 // the number of bytes to transfer on this page and the starting 00388 // position in the buffer to begin the transfer to. 00389 // 00390 00391 LfsTruncateLsnToLogPage( Lfcb, RecordHeader->ThisLsn, &LogPageFileOffset ); 00392 LogPageOffset = LfsLsnToPageOffset( Lfcb, RecordHeader->ThisLsn ) + Lfcb->RecordHeaderLength; 00393 00394 RemainingTransferBytes = RecordHeader->ClientDataLength; 00395 00396 // 00397 // Use a try-finally to facilitate cleanup. 00398 // 00399 00400 try { 00401 00402 // 00403 // While there are more bytes to transfer, we continue to attempt to 00404 // perform the read. 00405 // 00406 00407 while (TRUE) { 00408 00409 ULONG RemainingPageBytes; 00410 00411 BOOLEAN Wrapped; 00412 00413 RemainingPageBytes = (ULONG)Lfcb->LogPageSize - LogPageOffset; 00414 00415 // 00416 // We compute the number of bytes to read from this log page and 00417 // call the cache package to perform the transfer. 00418 // 00419 00420 if (RemainingTransferBytes <= RemainingPageBytes) { 00421 00422 RemainingPageBytes = RemainingTransferBytes; 00423 } 00424 00425 RemainingTransferBytes -= RemainingPageBytes; 00426 00427 // 00428 // Unpin any previous buffer. 00429 // 00430 00431 if (Bcb != NULL) { 00432 00433 CcUnpinData( Bcb ); 00434 Bcb = NULL; 00435 } 00436 00437 LfsPinOrMapData( Lfcb, 00438 LogPageFileOffset, 00439 (ULONG)Lfcb->LogPageSize, 00440 FALSE, 00441 FALSE, 00442 TRUE, 00443 &UsaError, 00444 (PVOID *) &PageHeader, 00445 &Bcb ); 00446 00447 // 00448 // The last Lsn on this page better be greater or equal to the Lsn we 00449 // are copying. 00450 // 00451 00452 if ( PageHeader->Copy.LastLsn.QuadPart < RecordHeader->ThisLsn.QuadPart ) { 00453 00454 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00455 } 00456 00457 RtlCopyMemory( Buffer, 00458 Add2Ptr( PageHeader, LogPageOffset, PVOID ), 00459 RemainingPageBytes ); 00460 00461 // 00462 // If there are no more bytes to transfer, we exit the loop. 00463 // 00464 00465 if (RemainingTransferBytes == 0) { 00466 00467 // 00468 // Our log record better not span this page. 00469 // 00470 00471 if (!FlagOn( PageHeader->Flags, LOG_PAGE_LOG_RECORD_END ) 00472 00473 || (FlagOn( Lfcb->Flags, LFCB_PACK_LOG ) 00474 && ( RecordHeader->ThisLsn.QuadPart > PageHeader->Header.Packed.LastEndLsn.QuadPart ))) { 00475 00476 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00477 } 00478 00479 break; 00480 } 00481 00482 // 00483 // If the page header indicates that the log record ended on this page, 00484 // this is a disk corrupt condition. For a packed page it means 00485 // that the last Lsn and the last Ending Lsn are the same. 00486 // 00487 00488 if (FlagOn( Lfcb->Flags, LFCB_PACK_LOG )) { 00489 00490 // 00491 // If there is no spanning log record this is an error. 00492 // 00493 00494 if (( PageHeader->Copy.LastLsn.QuadPart == PageHeader->Header.Packed.LastEndLsn.QuadPart ) 00495 00496 || ( RecordHeader->ThisLsn.QuadPart > PageHeader->Copy.LastLsn.QuadPart )) { 00497 00498 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00499 } 00500 00501 // 00502 // For an unpacked page it simply means that the page 00503 // contains the end of a log record. 00504 // 00505 00506 } else if (FlagOn( PageHeader->Flags, LOG_PAGE_LOG_RECORD_END )) { 00507 00508 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00509 } 00510 00511 // 00512 // We find the start of the next log page and the offset within 00513 // that page to start transferring bytes. 00514 // 00515 00516 LfsNextLogPageOffset( Lfcb, 00517 LogPageFileOffset, 00518 &LogPageFileOffset, 00519 &Wrapped ); 00520 00521 LogPageOffset = (ULONG)Lfcb->LogPageDataOffset; 00522 00523 // 00524 // We also adjust our pointer in the user's buffer to transfer 00525 // the next block to. 00526 // 00527 00528 Buffer = Add2Ptr( Buffer, RemainingPageBytes, PVOID ); 00529 } 00530 00531 } finally { 00532 00533 // 00534 // Unpin any previous buffer. 00535 // 00536 00537 if (Bcb != NULL) { 00538 00539 CcUnpinData( Bcb ); 00540 Bcb = NULL; 00541 } 00542 00543 DebugTrace( -1, Dbg, "LfsCopyReadLogRecord: Exit\n", 0 ); 00544 } 00545 00546 return; 00547 }

VOID LfsCurrentAvailSpace IN PLFCB  Lfcb,
OUT PLONGLONG  CurrentAvailSpace,
OUT PULONG  CurrentPageBytes
 

Definition at line 36 of file lfs/verfysup.c.

References _LBCB::BufferOffset, Dbg, DebugTrace, FlagOn, LBCB_FLUSH_COPY, LBCB_NOT_EMPTY, _LBCB::LbcbFlags, and PAGED_CODE.

Referenced by LfsFlushToLsnPriv(), LfsReadLogFileInformation(), and LfsVerifyLogSpaceAvail().

00044 : 00045 00046 This routine is called to determine the available log space in the log file. 00047 It returns the total number of free bytes and the number available on the 00048 active page if present. The total free bytes will reflect all of the empty 00049 pages as well as the number in the active page. 00050 00051 Arguments: 00052 00053 Lfcb - Lfcb for this log file. 00054 00055 CurrentAvailSpace - This is the number of bytes available for log 00056 records. 00057 00058 CurrentPageBytes - This is the number of bytes remaining on the 00059 current log page. 00060 00061 Return Value: 00062 00063 None. 00064 00065 --*/ 00066 00067 { 00068 *CurrentPageBytes = 0; 00069 00070 PAGED_CODE(); 00071 00072 DebugTrace( +1, Dbg, "LfsCurrentAvailSpace: Entered\n", 0 ); 00073 00074 // 00075 // Get the total number from the Lfcb. 00076 // 00077 00078 *CurrentAvailSpace = Lfcb->CurrentAvailable; 00079 00080 // 00081 // We now look to see if there are any bytes available on the Lbcb in 00082 // the active queue. We can add this to the bytes available in the 00083 // log pages and also give this back to the caller. 00084 // 00085 00086 if (!IsListEmpty( &Lfcb->LbcbActive )) { 00087 00088 PLBCB ThisLbcb; 00089 00090 ThisLbcb = CONTAINING_RECORD( Lfcb->LbcbActive.Flink, 00091 LBCB, 00092 ActiveLinks ); 00093 00094 // 00095 // If the page is not empty or the page is empty but this is a 00096 // restart page then add the remaining bytes on this page. 00097 // 00098 00099 if (FlagOn( ThisLbcb->LbcbFlags, LBCB_NOT_EMPTY | LBCB_FLUSH_COPY )) { 00100 00101 *CurrentPageBytes = (ULONG)Lfcb->LogPageSize - (ULONG)ThisLbcb->BufferOffset; 00102 00103 *CurrentAvailSpace = *CurrentAvailSpace + *CurrentPageBytes; //**** xxAdd( *CurrentAvailSpace, xxFromUlong( *CurrentPageBytes )); 00104 } 00105 } 00106 00107 DebugTrace( +1, Dbg, "LfsCurrentAvailSpace: Exit\n", 0 ); 00108 00109 return; 00110 }

VOID LfsDeallocateLbcb IN PLFCB  Lfcb,
IN PLBCB  Lbcb
 

Definition at line 402 of file lfs/strucsup.c.

References ExFreePool(), FlagOn, LBCB_RESTART_LBCB, LFCB_MAX_LBCB_COUNT, LfsDeallocateRestartArea, NULL, and PAGED_CODE.

Referenced by LfsCloseLogFile(), LfsDeallocateLfcb(), LfsFlushLfcb(), and LfsGetLbcb().

00409 : 00410 00411 This routine will deallocate the Lbcb. If we need one for the look-aside 00412 list we will put it there. 00413 00414 Arguments: 00415 00416 Lfcb - Supplies a pointer to the log file control block. 00417 00418 Lbcb - This is the Lbcb to deallocate. 00419 00420 Return Value: 00421 00422 None 00423 00424 --*/ 00425 00426 { 00427 PAGED_CODE(); 00428 00429 // 00430 // Deallocate any restart area attached to this Lbcb. 00431 // 00432 00433 if (FlagOn( Lbcb->LbcbFlags, LBCB_RESTART_LBCB ) && 00434 (Lbcb->PageHeader != NULL)) { 00435 00436 LfsDeallocateRestartArea( Lbcb->PageHeader ); 00437 } 00438 00439 // 00440 // Put this in the Lbcb queue if it is short. 00441 // 00442 00443 if (Lfcb->SpareLbcbCount < LFCB_MAX_LBCB_COUNT) { 00444 00445 InsertHeadList( &Lfcb->SpareLbcbList, (PLIST_ENTRY) Lbcb ); 00446 Lfcb->SpareLbcbCount += 1; 00447 00448 // 00449 // Otherwise just free the pool block. 00450 // 00451 00452 } else { 00453 00454 ExFreePool( Lbcb ); 00455 } 00456 00457 return; 00458 }

VOID LfsDeallocateLcb IN PLFCB  Lfcb,
IN PLCB  Lcb
 

Definition at line 518 of file lfs/strucsup.c.

References CcUnpinData(), ExFreePool(), LFCB_MAX_LCB_COUNT, LfsFreeSpanningBuffer(), and NULL.

Referenced by LfsReadLogRecord(), and LfsTerminateLogQuery().

00524 : 00525 00526 This routine will deallocate an Lcb. We'll cache the old lcb if there 00527 aren't too many already on the spare list 00528 00529 Arguments: 00530 00531 Lfcb - Supplies a pointer to the log file control block. 00532 00533 Lcb - This will contain the lcb to release 00534 00535 Return Value: 00536 00537 None 00538 00539 --*/ 00540 00541 { 00542 if (Lcb->RecordHeaderBcb != NULL) { 00543 CcUnpinData( Lcb->RecordHeaderBcb ); 00544 } 00545 if ((Lcb->CurrentLogRecord != NULL) && Lcb->AuxilaryBuffer) { 00546 LfsFreeSpanningBuffer( Lcb->CurrentLogRecord ); 00547 } 00548 00549 ExAcquireFastMutex( &(Lfcb->Sync->SpareListMutex) ); 00550 00551 try { 00552 if (Lfcb->SpareLcbCount < LFCB_MAX_LCB_COUNT) { 00553 InsertHeadList( &Lfcb->SpareLcbList, (PLIST_ENTRY) Lcb ); 00554 Lfcb->SpareLcbCount += 1; 00555 } else { 00556 ExFreePool( Lcb ); 00557 } 00558 } finally { 00559 ExReleaseFastMutex( &(Lfcb->Sync->SpareListMutex) ); 00560 } 00561 }

VOID LfsDeallocateLfcb IN PLFCB  Lfcb,
IN BOOLEAN  CompleteTeardown
 

Definition at line 188 of file lfs/strucsup.c.

References ASSERT, Dbg, DebugTrace, ExDeleteResource, ExFreePool(), LfsDeallocateLbcb(), LfsDeallocateRestartArea, NULL, and PAGED_CODE.

Referenced by LfsAllocateLfcb(), LfsCloseLogFile(), LfsInitializeLogFile(), LfsOpenLogFile(), and LfsRestartLogFile().

00195 : 00196 00197 This routine releases the resources associated with a log file control 00198 block. 00199 00200 Arguments: 00201 00202 Lfcb - Supplies a pointer to the log file control block. 00203 00204 CompleteTeardown - Indicates if we are to completely remove this Lfcb. 00205 00206 Return Value: 00207 00208 None 00209 00210 --*/ 00211 00212 { 00213 PLBCB NextLbcb; 00214 PLCB NextLcb; 00215 00216 PAGED_CODE(); 00217 00218 DebugTrace( +1, Dbg, "LfsDeallocateLfcb: Entered\n", 0 ); 00219 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00220 00221 // 00222 // Check that there are no buffer blocks. 00223 // 00224 00225 ASSERT( IsListEmpty( &Lfcb->LbcbActive )); 00226 ASSERT( IsListEmpty( &Lfcb->LbcbWorkque )); 00227 00228 // 00229 // Check that we have no clients. 00230 // 00231 00232 ASSERT( IsListEmpty( &Lfcb->LchLinks )); 00233 00234 // 00235 // If there is a restart area we deallocate it. 00236 // 00237 00238 if (Lfcb->RestartArea != NULL) { 00239 00240 LfsDeallocateRestartArea( Lfcb->RestartArea ); 00241 } 00242 00243 // 00244 // If there are any of the tail Lbcb's, deallocate them now. 00245 // 00246 00247 if (Lfcb->ActiveTail != NULL) { 00248 00249 LfsDeallocateLbcb( Lfcb, Lfcb->ActiveTail ); 00250 Lfcb->ActiveTail = NULL; 00251 } 00252 00253 if (Lfcb->PrevTail != NULL) { 00254 00255 LfsDeallocateLbcb( Lfcb, Lfcb->PrevTail ); 00256 Lfcb->PrevTail = NULL; 00257 } 00258 00259 // 00260 // Only do the following if we are to remove the Lfcb completely. 00261 // 00262 00263 if (CompleteTeardown) { 00264 00265 // 00266 // If there is a resource structure we deallocate it. 00267 // 00268 00269 if (Lfcb->Sync != NULL) { 00270 00271 ExDeleteResource( &Lfcb->Sync->Resource ); 00272 00273 ExFreePool( Lfcb->Sync ); 00274 } 00275 } 00276 00277 // 00278 // Deallocate all of the spare Lbcb's. 00279 // 00280 00281 while (!IsListEmpty( &Lfcb->SpareLbcbList )) { 00282 00283 NextLbcb = (PLBCB) Lfcb->SpareLbcbList.Flink; 00284 00285 RemoveHeadList( &Lfcb->SpareLbcbList ); 00286 00287 ExFreePool( NextLbcb ); 00288 } 00289 00290 // 00291 // Deallocate all of the spare Lcb's. 00292 // 00293 00294 while (!IsListEmpty( &Lfcb->SpareLcbList )) { 00295 00296 NextLcb = (PLCB) Lfcb->SpareLcbList.Flink; 00297 00298 RemoveHeadList( &Lfcb->SpareLcbList ); 00299 00300 ExFreePool( NextLcb ); 00301 } 00302 00303 // 00304 // Discard the Lfcb structure. 00305 // 00306 00307 ExFreePool( Lfcb ); 00308 00309 DebugTrace( -1, Dbg, "LfsDeallocateLfcb: Exit\n", 0 ); 00310 return; 00311 }

LONG LfsExceptionFilter IN PEXCEPTION_POINTERS  ExceptionPointer  ) 
 

Definition at line 58 of file lfsdata.c.

References ASSERT, EXCEPTION_CONTINUE_SEARCH, EXCEPTION_EXECUTE_HANDLER, FsRtlIsNtstatusExpected(), and NTSTATUS().

Referenced by LfsCloseLogFile(), LfsDeleteLogHandle(), LfsFlushToLsn(), LfsForceWrite(), LfsInitializeLogFile(), LfsOpenLogFile(), LfsPinOrMapData(), LfsReadLogRecord(), LfsReadNextLogRecord(), LfsReadRestartArea(), LfsSetBaseLsn(), LfsWrite(), and LfsWriteRestartArea().

00064 : 00065 00066 This routine is used to decide if we should or should not handle 00067 an exception status that is being raised. It indicates that we should handle 00068 the exception or bug check the system. 00069 00070 Arguments: 00071 00072 ExceptionCode - Supplies the exception code to being checked. 00073 00074 Return Value: 00075 00076 ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks 00077 00078 --*/ 00079 00080 { 00081 NTSTATUS ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode; 00082 00083 #ifdef NTFS_RESTART 00084 ASSERT( (ExceptionCode != STATUS_DISK_CORRUPT_ERROR) && 00085 (ExceptionCode != STATUS_FILE_CORRUPT_ERROR) ); 00086 #endif 00087 00088 //if (ExceptionCode != STATUS_LOG_FILE_FULL) { 00089 // 00090 // DbgPrint("Status not LOGFILE FULL, ExceptionPointers = %08lx\n", ExceptionPointer); 00091 // DbgBreakPoint(); 00092 //} 00093 00094 if (!FsRtlIsNtstatusExpected( ExceptionCode )) { 00095 00096 return EXCEPTION_CONTINUE_SEARCH; 00097 00098 } else { 00099 00100 return EXCEPTION_EXECUTE_HANDLER; 00101 } 00102 } }

VOID LfsFindCurrentAvail IN PLFCB  Lfcb  ) 
 

Definition at line 412 of file lfs/verfysup.c.

References Dbg, DebugTrace, FlagOn, LFCB_NO_LAST_LSN, LFCB_NO_OLDEST_LSN, LFCB_REUSE_TAIL, LfsTruncateOffsetToLogPage, and PAGED_CODE.

Referenced by LfsRestartLogFile(), LfsSetBaseLsnPriv(), and LfsUpdateLfcbFromRestart().

00418 : 00419 00420 This routine is called to calculate the number of bytes available for log 00421 records which are in completely empty log record pages. It ignores any 00422 partial pages in the active work queue and ignores any page which is 00423 going to be reused. 00424 00425 Arguments: 00426 00427 Lfcb - Lfcb for this log file. 00428 00429 Return Value: 00430 00431 None. 00432 00433 --*/ 00434 00435 { 00436 LONGLONG OldestPageOffset; 00437 LONGLONG NextFreePageOffset; 00438 LONGLONG FreeBytes; 00439 00440 PAGED_CODE(); 00441 00442 DebugTrace( +1, Dbg, "LfsFindCurrentAvail: Entered\n", 0 ); 00443 DebugTrace( 0, Dbg, "Lfcb -> %08x\n", Lfcb ); 00444 00445 // 00446 // If there is a last lsn in the restart area then we know 00447 // that we will have to compute the free range. 00448 // 00449 00450 if (!FlagOn( Lfcb->Flags, LFCB_NO_LAST_LSN )) { 00451 00452 // 00453 // If there is no oldest Lsn then start at the 00454 // first page of the file. 00455 // 00456 00457 if (FlagOn( Lfcb->Flags, LFCB_NO_OLDEST_LSN )) { 00458 00459 OldestPageOffset = Lfcb->FirstLogPage; 00460 00461 } else { 00462 00463 LfsTruncateOffsetToLogPage( Lfcb, 00464 Lfcb->OldestLsnOffset, 00465 &OldestPageOffset ); 00466 } 00467 00468 // 00469 // We will use the next log page offset to compute the 00470 // next free page. If we are going to reuse this page 00471 // go to the next page, if we are at the first page then 00472 // use the end of the file. 00473 // 00474 00475 if (FlagOn( Lfcb->Flags, LFCB_REUSE_TAIL )) { 00476 00477 NextFreePageOffset = Lfcb->NextLogPage + Lfcb->LogPageSize; //**** xxAdd( Lfcb->NextLogPage, Lfcb->LogPageSize ); 00478 00479 } else if ( Lfcb->NextLogPage == Lfcb->FirstLogPage ) { //**** xxEql( Lfcb->NextLogPage, Lfcb->FirstLogPage ) 00480 00481 NextFreePageOffset = Lfcb->FileSize; 00482 00483 } else { 00484 00485 NextFreePageOffset = Lfcb->NextLogPage; 00486 } 00487 00488 // 00489 // If the two offsets are the same then there is no available space. 00490 // 00491 00492 if ( OldestPageOffset == NextFreePageOffset ) { //**** xxEql( OldestPageOffset, NextFreePageOffset ) 00493 00494 Lfcb->CurrentAvailable = 0; 00495 00496 } else { 00497 00498 // 00499 // If the free offset follows the oldest offset then subtract 00500 // this range from the total available pages. 00501 // 00502 00503 if ( OldestPageOffset < NextFreePageOffset ) { //**** xxLtr( OldestPageOffset, NextFreePageOffset ) 00504 00505 FreeBytes = Lfcb->TotalAvailInPages - ( NextFreePageOffset - OldestPageOffset ); //**** xxSub( Lfcb->TotalAvailInPages, xxSub( NextFreePageOffset, OldestPageOffset )); 00506 00507 } else { 00508 00509 FreeBytes = OldestPageOffset - NextFreePageOffset; //**** xxSub( OldestPageOffset, NextFreePageOffset ); 00510 } 00511 00512 // 00513 // We now have the total bytes in the pages available. We 00514 // now have to subtract the size of the page header to get 00515 // the total available bytes. 00516 // 00517 // We will convert the bytes to pages and then multiple 00518 // by the data size of each page. 00519 // 00520 00521 FreeBytes = Int64ShrlMod32(((ULONGLONG)(FreeBytes)), Lfcb->LogPageShift); 00522 00523 Lfcb->CurrentAvailable = FreeBytes * (ULONG)Lfcb->ReservedLogPageSize; //**** xxXMul( FreeBytes, Lfcb->ReservedLogPageSize.LowPart ); 00524 } 00525 00526 // 00527 // Otherwise the entire file is available. 00528 // 00529 00530 } else { 00531 00532 Lfcb->CurrentAvailable = Lfcb->MaxCurrentAvail; 00533 } 00534 00535 DebugTrace( -1, Dbg, "LfsFindCurrentAvail: Exit\n", 0 ); 00536 00537 return; 00538 } }

BOOLEAN LfsFindNextLsn IN PLFCB  Lfcb,
IN PLFS_RECORD_HEADER  RecordHeader,
OUT PLSN  Lsn
 

Definition at line 148 of file lsnsup.c.

References CcUnpinData(), Dbg, DebugTrace, DebugUnwind, FALSE, LfsFileOffsetToLsn, LfsFindNextLsn(), LfsIsLsnInFile, LfsLsnFinalOffset(), LfsLsnToFileOffset, LfsLsnToSeqNumber, LfsNextLogPageOffset(), LfsPinOrMapData(), LfsTruncateOffsetToLogPage, LiQuadAlign, NULL, PAGED_CODE, and TRUE.

Referenced by LfsFindNextLsn(), and LfsSearchForwardByClient().

00156 : 00157 00158 This routine takes as a starting point the log record header of an 00159 Lsn in the log file. It searches for the next Lsn in the file and 00160 returns that value in the 'Lsn' argument. The boolean return value 00161 indicates whether there is another Lsn in the file. 00162 00163 Arguments: 00164 00165 Lfcb - This is the file control block for the log file. 00166 00167 RecordHeader - This is the log record for the Lsn starting point. 00168 00169 Lsn - This supplies the address to store the next Lsn, if found. 00170 00171 Return Value: 00172 00173 BOOLEAN - Indicates whether the next Lsn was found. 00174 00175 --*/ 00176 00177 { 00178 BOOLEAN FoundNextLsn; 00179 00180 LONGLONG LsnOffset; 00181 LONGLONG EndOfLogRecord; 00182 LONGLONG LogHeaderOffset; 00183 00184 LONGLONG SequenceNumber; 00185 00186 PLFS_RECORD_PAGE_HEADER LogRecordPage; 00187 PBCB LogRecordPageBcb; 00188 BOOLEAN UsaError; 00189 00190 PAGED_CODE(); 00191 00192 DebugTrace( +1, Dbg, "LfsFindNextLsn: Entered\n", 0 ); 00193 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00194 DebugTrace( 0, Dbg, "Record Header -> %08lx\n", RecordHeader ); 00195 00196 LogRecordPageBcb = NULL; 00197 FoundNextLsn = FALSE; 00198 00199 // 00200 // Use a try-finally to facilitate cleanup. 00201 // 00202 00203 try { 00204 00205 // 00206 // Find the file offset of the log page which contains the end 00207 // of the log record for this Lsn. 00208 // 00209 00210 LsnOffset = LfsLsnToFileOffset( Lfcb, RecordHeader->ThisLsn ); 00211 00212 LfsLsnFinalOffset( Lfcb, 00213 RecordHeader->ThisLsn, 00214 RecordHeader->ClientDataLength, 00215 &EndOfLogRecord ); 00216 00217 LfsTruncateOffsetToLogPage( Lfcb, EndOfLogRecord, &LogHeaderOffset ); 00218 00219 // 00220 // Remember the sequence number for this page. 00221 // 00222 00223 SequenceNumber = LfsLsnToSeqNumber( Lfcb, RecordHeader->ThisLsn ); 00224 00225 // 00226 // Remember if we wrapped. 00227 // 00228 00229 if ( EndOfLogRecord <= LsnOffset ) { //**** xxLeq( EndOfLogRecord, LsnOffset ) 00230 00231 SequenceNumber = SequenceNumber + 1; //**** xxAdd( SequenceNumber, LfsLi1 ); 00232 } 00233 00234 // 00235 // Pin the log page header for this page. 00236 // 00237 00238 LfsPinOrMapData( Lfcb, 00239 LogHeaderOffset, 00240 (ULONG)Lfcb->LogPageSize, 00241 FALSE, 00242 FALSE, 00243 FALSE, 00244 &UsaError, 00245 (PVOID *)&LogRecordPage, 00246 &LogRecordPageBcb ); 00247 00248 // 00249 // If the Lsn we were given was not the last Lsn on this page, then 00250 // the starting offset for the next Lsn is on a quad word boundary 00251 // following the last file offset for the current Lsn. Otherwise 00252 // the file offset is the start of the data on the next page. 00253 // 00254 00255 if ( RecordHeader->ThisLsn.QuadPart == LogRecordPage->Copy.LastLsn.QuadPart ) { //**** xxEql( RecordHeader->ThisLsn, LogRecordPage->Copy.LastLsn ) 00256 00257 BOOLEAN Wrapped; 00258 00259 LfsNextLogPageOffset( Lfcb, 00260 LogHeaderOffset, 00261 &LogHeaderOffset, 00262 &Wrapped ); 00263 00264 LsnOffset = LogHeaderOffset + Lfcb->LogPageDataOffset; //**** xxAdd( LogHeaderOffset, Lfcb->LogPageDataOffset ); 00265 00266 // 00267 // If we wrapped, we need to increment the sequence number. 00268 // 00269 00270 if (Wrapped) { 00271 00272 SequenceNumber = SequenceNumber + 1; //**** xxAdd( SequenceNumber, LfsLi1 ); 00273 } 00274 00275 } else { 00276 00277 LiQuadAlign( EndOfLogRecord, &LsnOffset ); 00278 } 00279 00280 // 00281 // Compute the Lsn based on the file offset and the sequence count. 00282 // 00283 00284 Lsn->QuadPart = LfsFileOffsetToLsn( Lfcb, LsnOffset, SequenceNumber ); 00285 00286 // 00287 // If this Lsn is within the legal range for the file, we return TRUE. 00288 // Otherwise FALSE indicates that there are no more Lsn's. 00289 // 00290 00291 if (LfsIsLsnInFile( Lfcb, *Lsn )) { 00292 00293 FoundNextLsn = TRUE; 00294 } 00295 00296 } finally { 00297 00298 DebugUnwind( LfsFindNextLsn ); 00299 00300 // 00301 // Unpin the log page header if held. 00302 // 00303 00304 if (LogRecordPageBcb != NULL) { 00305 00306 CcUnpinData( LogRecordPageBcb ); 00307 } 00308 00309 DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn->LowPart ); 00310 DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn->HighPart ); 00311 DebugTrace( -1, Dbg, "LfsFindNextLsn: Exit -> %08x\n", FoundNextLsn ); 00312 } 00313 00314 return FoundNextLsn; 00315 }

VOID LfsFindOldestClientLsn IN PLFS_RESTART_AREA  RestartArea,
IN PLFS_CLIENT_RECORD  ClientArray,
OUT PLSN  OldestLsn
 

Definition at line 189 of file rstrtsup.c.

References Dbg, DebugTrace, LFS_NO_CLIENT, _LFS_CLIENT_RECORD::NextClient, _LFS_CLIENT_RECORD::OldestLsn, PAGED_CODE, and USHORT.

Referenced by LfsSetBaseLsnPriv(), and LfsUpdateLfcbFromRestart().

00197 : 00198 00199 This routine walks through the active clients to determine the oldest 00200 Lsn the system must maintain. 00201 00202 Arguments: 00203 00204 RestartArea - This is the Restart Area to examine. 00205 00206 ClientArray - This is the start of the client data array. 00207 00208 OldestLsn - We store the oldest Lsn we find in this value. It is 00209 initialized with a starting value, we won't return a more recent 00210 Lsn. 00211 00212 Return Value: 00213 00214 None. 00215 00216 --*/ 00217 00218 { 00219 USHORT NextClient; 00220 00221 PLFS_CLIENT_RECORD ClientBlock; 00222 00223 PAGED_CODE(); 00224 00225 DebugTrace( +1, Dbg, "LfsFindOldestClientLsn: Entered\n", 0 ); 00226 DebugTrace( 0, Dbg, "RestartArea -> %08lx\n", RestartArea ); 00227 DebugTrace( 0, Dbg, "Base Lsn (Low) -> %08lx\n", BaseLsn.LowPart ); 00228 DebugTrace( 0, Dbg, "Base Lsn (High) -> %08lx\n", BaseLsn.HighPart ); 00229 00230 // 00231 // Take the first client off the in use list. 00232 // 00233 00234 NextClient = RestartArea->ClientInUseList; 00235 00236 // 00237 // While there are more clients, compare their oldest Lsn with the 00238 // current oldest. 00239 // 00240 00241 while (NextClient != LFS_NO_CLIENT) { 00242 00243 ClientBlock = ClientArray + NextClient; 00244 00245 // 00246 // We ignore this block if it's oldest Lsn is 0. 00247 // 00248 00249 if (( ClientBlock->OldestLsn.QuadPart != 0 ) 00250 && ( ClientBlock->OldestLsn.QuadPart < OldestLsn->QuadPart )) { 00251 00252 *OldestLsn = ClientBlock->OldestLsn; 00253 } 00254 00255 // 00256 // Try the next client block. 00257 // 00258 00259 NextClient = ClientBlock->NextClient; 00260 } 00261 00262 DebugTrace( 0, Dbg, "OldestLsn (Low) -> %08lx\n", BaseLsn.LowPart ); 00263 DebugTrace( 0, Dbg, "OldestLsn (High) -> %08lx\n", BaseLsn.HighPart ); 00264 DebugTrace( -1, Dbg, "LfsFindOldestClientLsn: Exit\n", 0 ); 00265 00266 return; 00267 }

VOID LfsFlushLbcb IN PLFCB  Lfcb,
IN PLBCB  Lbcb
 

Definition at line 37 of file lbcbsup.c.

References Dbg, DebugTrace, Executive, FALSE, KernelMode, KeWaitForSingleObject(), LfsAcquireLfcb, LfsFlushLfcb(), LfsLbcbIsRestart, LfsNoIoInProgress, LfsReleaseLfcb, LSN, NULL, PAGED_CODE, and PLSN.

Referenced by LfsFlushToLsnPriv(), and LfsWriteLfsRestart().

00044 : 00045 00046 This routine is called to make sure the data within an Lbcb makes it out 00047 to disk. The Lbcb must either already be in the workque or it must be 00048 a restart Lbcb. 00049 00050 Arguments: 00051 00052 Lfcb - This is the file control block for the log file. 00053 00054 Lbcb - This is the Lbcb to flush. 00055 00056 Return Value: 00057 00058 None. 00059 00060 --*/ 00061 00062 { 00063 LSN LastLsn; 00064 PLSN FlushedLsn; 00065 00066 PAGED_CODE(); 00067 00068 DebugTrace( +1, Dbg, "LfsFlushLbcb: Entered\n", 0 ); 00069 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00070 DebugTrace( 0, Dbg, "Lbcb -> %08lx\n", Lbcb ); 00071 00072 LastLsn = Lbcb->LastEndLsn; 00073 00074 // 00075 // If this is a restart area we use the restart counter in the 00076 // Lfcb. Otherwise we can use the LastFlushedLsn value in the 00077 // Lfcb. This way we can determine that the Lbcb that interests 00078 // us has made it out to disk. 00079 // 00080 00081 if (LfsLbcbIsRestart( Lbcb )) { 00082 00083 FlushedLsn = &Lfcb->LastFlushedRestartLsn; 00084 00085 } else { 00086 00087 FlushedLsn = &Lfcb->LastFlushedLsn; 00088 } 00089 00090 // 00091 // We loop here until the desired Lsn has made it to disk. 00092 // If we are able to do the I/O, we will perform it. 00093 // 00094 00095 do { 00096 00097 // 00098 // 00099 // If we can do the Io, call down to flush the Lfcb. 00100 // 00101 00102 if (Lfcb->LfsIoState == LfsNoIoInProgress) { 00103 00104 LfsFlushLfcb( Lfcb, Lbcb ); 00105 00106 break; 00107 } 00108 00109 // 00110 // Otherwise we release the Lfcb and immediately wait on the event. 00111 // 00112 00113 Lfcb->Waiters += 1; 00114 00115 LfsReleaseLfcb( Lfcb ); 00116 00117 KeWaitForSingleObject( &Lfcb->Sync->Event, 00118 Executive, 00119 KernelMode, 00120 FALSE, 00121 NULL ); 00122 00123 LfsAcquireLfcb( Lfcb ); 00124 Lfcb->Waiters -= 1; 00125 00126 } while ( LastLsn.QuadPart > FlushedLsn->QuadPart ); 00127 00128 DebugTrace( -1, Dbg, "LfsFlushLbcb: Exit\n", 0 ); 00129 return; 00130 }

VOID LfsFlushLfcb IN PLFCB  Lfcb,
IN PLBCB  Lbcb
 

Definition at line 551 of file lfs/cachesup.c.

References Add2Ptr, ASSERT, CcFlushCache(), CcMapData(), CcSetDirtyPinnedData(), CcUnpinData(), CcUnpinDataForThread(), _LFS_RESTART_PAGE_HEADER::ChkDskLsn, ClearFlag, _LFS_RECORD_PAGE_HEADER::Copy, Count, Dbg, DebugTrace, DebugUnwind, ExGetCurrentResourceThread, ExRaiseStatus(), FALSE, _LBCB::FileOffset, FlagOn, _LBCB::Flags, KeClearEvent, KeSetEvent(), _LBCB::LastEndLsn, _LBCB::LastLsn, LBCB, _LBCB::Length, LFCB_FINAL_SHUTDOWN, LFCB_LOG_WRAPPED, LFCB_MULTIPLE_PAGE_IO, LFCB_READ_FIRST_RESTART, LFCB_READ_SECOND_RESTART, LFS_SIGNATURE_RECORD_PAGE_ULONG, LFS_SIGNATURE_RESTART_PAGE_ULONG, LfsAcquireLfcb, LfsClientThreadIo, LfsDeallocateLbcb(), LfsFindFirstIo(), LfsFlushLfcb(), LfsLi0, LfsNoIoInProgress, LfsPinOrMapData(), LfsPreparePinWriteData, LfsReleaseLfcb, LfsUsaSeqNumber, LOG_PAGE_LOG_RECORD_END, _LBCB::LogPageBcb, _LFS_RESTART_PAGE_HEADER::LogPageSize, LSN, _LFS_RESTART_PAGE_HEADER::MajorVersion, _LFS_RESTART_PAGE_HEADER::MinorVersion, _LFS_RECORD_PAGE_HEADER::MultiSectorHeader, _LFS_RESTART_PAGE_HEADER::MultiSectorHeader, NT_SUCCESS, NTSTATUS(), NULL, PAGE_SIZE, _LFS_RECORD_PAGE_HEADER::PageCount, PAGED_CODE, _LBCB::PageHeader, _LFS_RECORD_PAGE_HEADER::PagePosition, PLFS_RESTART_AREA, PUSHORT, _LBCB::ResourceThread, RESTART_SINGLE_PAGE_IO, _LFS_RESTART_PAGE_HEADER::RestartOffset, SetFlag, _MULTI_SECTOR_HEADER::Signature, Status, _LFS_RESTART_PAGE_HEADER::SystemPageSize, TRUE, try_return, _MULTI_SECTOR_HEADER::UpdateSequenceArrayOffset, _MULTI_SECTOR_HEADER::UpdateSequenceArraySize, USHORT, and _LBCB::WorkqueLinks.

Referenced by LfsFlushLbcb(), and LfsFlushLfcb().

00558 : 00559 00560 This routine is called to flush the current Lbcbs in on the Lfcb 00561 work queue. It will flush up to the I/O which contains the desired 00562 Lbcb. 00563 00564 Arguments: 00565 00566 Lfcb - This is the file control block for the log file. 00567 00568 Lbcb - This is the block which is needed to be flushed to disk. 00569 00570 Return Value: 00571 00572 None. 00573 00574 --*/ 00575 00576 { 00577 PLBCB FirstLbcb; 00578 PLBCB ThisLbcb; 00579 PLBCB NextLbcb; 00580 00581 PLBCB TargetLbcb; 00582 PULONG Signature; 00583 00584 LONGLONG FileOffset; 00585 ULONG Length; 00586 00587 BOOLEAN RaiseCorrupt = FALSE; 00588 BOOLEAN ValidLastLsn = FALSE; 00589 00590 BOOLEAN ContainsLastEntry = FALSE; 00591 BOOLEAN LfsRestart; 00592 BOOLEAN UseTailCopy; 00593 00594 ULONG IoBlocks; 00595 ULONG NewLfcbFlags = 0; 00596 00597 PBCB MapPageBcb = NULL; 00598 PVOID MapPage; 00599 00600 LSN LastLsn; 00601 00602 IO_STATUS_BLOCK Iosb; 00603 00604 PBCB PageBcb = NULL; 00605 00606 PAGED_CODE(); 00607 00608 DebugTrace( +1, Dbg, "LfsFlushLfcb: Entered\n", 0 ); 00609 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00610 00611 // 00612 // Use a try-finally to facilitate cleanup. 00613 // 00614 00615 try { 00616 00617 // 00618 // If there are no elements on the list, we are done. 00619 // 00620 00621 if (IsListEmpty( &Lfcb->LbcbWorkque )) { 00622 00623 try_return( NOTHING ); 00624 } 00625 00626 // 00627 // Mark the Lfcb as Io in progress. 00628 // 00629 00630 Lfcb->LfsIoState = LfsClientThreadIo; 00631 #ifdef BRIANDBG 00632 Lfcb->LfsIoThread = ExGetCurrentResourceThread(); 00633 #endif 00634 00635 // 00636 // Remember the first Lbcb in the list. 00637 // 00638 00639 FirstLbcb = CONTAINING_RECORD( Lfcb->LbcbWorkque.Flink, 00640 LBCB, 00641 WorkqueLinks ); 00642 00643 // 00644 // We continue looping and performing I/o for as long as possible. 00645 // 00646 00647 while (!ContainsLastEntry) { 00648 00649 ASSERT( Lfcb->PageToDirty == NULL ); 00650 00651 // 00652 // Reset the notify event for all of the waiting threads. 00653 // 00654 00655 KeClearEvent( &Lfcb->Sync->Event ); 00656 00657 // 00658 // Find the block of Lbcb's that make up the first I/O, remembering 00659 // how many there are. Also remember if this I/O contains the 00660 // last element on the list when we were called. 00661 // 00662 00663 LfsFindFirstIo( Lfcb, 00664 Lbcb, 00665 FirstLbcb, 00666 &NextLbcb, 00667 &FileOffset, 00668 &ContainsLastEntry, 00669 &LfsRestart, 00670 &UseTailCopy, 00671 &IoBlocks ); 00672 00673 Length = IoBlocks * (ULONG) Lfcb->LogPageSize; 00674 if (UseTailCopy) { 00675 00676 TargetLbcb = Lfcb->ActiveTail; 00677 Lfcb->ActiveTail = Lfcb->PrevTail; 00678 Lfcb->PrevTail = TargetLbcb; 00679 00680 FileOffset = TargetLbcb->FileOffset; 00681 00682 } else { 00683 00684 TargetLbcb = FirstLbcb; 00685 } 00686 00687 // 00688 // Give up the Lfcb unless we are looking at an active page. 00689 // 00690 00691 if (!UseTailCopy) { 00692 00693 LfsReleaseLfcb( Lfcb ); 00694 } 00695 00696 // 00697 // If this I/O involves the Lfs restart area, write it to the 00698 // cache pages. 00699 // 00700 00701 if (LfsRestart) { 00702 00703 PLFS_RESTART_PAGE_HEADER RestartPage; 00704 BOOLEAN UsaError; 00705 NTSTATUS Status; 00706 00707 // 00708 // If there was some error in initially reading the restart page then 00709 // it is OK to settle for a page of zeroes. 00710 // 00711 00712 if (FlagOn( Lfcb->Flags, LFCB_READ_FIRST_RESTART | LFCB_READ_SECOND_RESTART ) && 00713 ((FileOffset == 0) ? 00714 FlagOn( Lfcb->Flags, LFCB_READ_FIRST_RESTART ) : 00715 FlagOn( Lfcb->Flags, LFCB_READ_SECOND_RESTART ))) { 00716 00717 LfsPreparePinWriteData( Lfcb, 00718 FileOffset, 00719 (ULONG) Lfcb->SystemPageSize, 00720 &RestartPage, 00721 &PageBcb ); 00722 00723 Status = STATUS_SUCCESS; 00724 00725 if (FileOffset == 0) { 00726 00727 SetFlag( NewLfcbFlags, LFCB_READ_FIRST_RESTART ); 00728 00729 } else { 00730 00731 SetFlag( NewLfcbFlags, LFCB_READ_SECOND_RESTART ); 00732 } 00733 00734 } else { 00735 00736 Status = LfsPinOrMapData( Lfcb, 00737 FileOffset, 00738 (ULONG)Lfcb->SystemPageSize, 00739 TRUE, 00740 TRUE, 00741 TRUE, 00742 &UsaError, 00743 &RestartPage, 00744 &PageBcb ); 00745 } 00746 00747 if (NT_SUCCESS( Status )) { 00748 00749 // 00750 // Initialize the restart page header. 00751 // 00752 00753 Signature = (PULONG) &RestartPage->MultiSectorHeader.Signature; 00754 00755 *Signature = LFS_SIGNATURE_RESTART_PAGE_ULONG; 00756 RestartPage->ChkDskLsn = LfsLi0; 00757 00758 RestartPage->MultiSectorHeader.UpdateSequenceArrayOffset 00759 = Lfcb->RestartUsaOffset; 00760 00761 RestartPage->MultiSectorHeader.UpdateSequenceArraySize 00762 = Lfcb->RestartUsaArraySize; 00763 00764 RestartPage->SystemPageSize = (ULONG)Lfcb->SystemPageSize; 00765 RestartPage->LogPageSize = (ULONG)Lfcb->LogPageSize; 00766 00767 RestartPage->RestartOffset = (USHORT) Lfcb->RestartDataOffset; 00768 RestartPage->MajorVersion = Lfcb->MajorVersion; 00769 RestartPage->MinorVersion = Lfcb->MinorVersion; 00770 00771 // 00772 // If the Lfcb indicates that the file has wrapped, then clear the 00773 // first pass flag in the restart area. 00774 // 00775 00776 if (FlagOn( Lfcb->Flags, LFCB_LOG_WRAPPED )) { 00777 00778 ClearFlag( ((PLFS_RESTART_AREA) FirstLbcb->PageHeader)->Flags, RESTART_SINGLE_PAGE_IO ); 00779 SetFlag( Lfcb->Flags, LFCB_MULTIPLE_PAGE_IO ); 00780 } 00781 00782 // 00783 // Write the page header into the page and mark the page dirty. 00784 // 00785 00786 RtlCopyMemory( Add2Ptr( RestartPage, Lfcb->RestartDataOffset, PVOID ), 00787 FirstLbcb->PageHeader, 00788 (ULONG)FirstLbcb->Length ); 00789 00790 // 00791 // Make sure the modified bit gets set in the pfn database. The 00792 // cache manager should do this even for files we told him not to 00793 // lazy write. 00794 // 00795 00796 CcSetDirtyPinnedData( PageBcb, NULL ); 00797 00798 // 00799 // We unpin any buffers pinned on this page. 00800 // 00801 00802 CcUnpinData( PageBcb ); 00803 PageBcb = NULL; 00804 00805 LastLsn = FirstLbcb->LastLsn; 00806 ValidLastLsn = TRUE; 00807 00808 // 00809 // Use a system page size as the length we need to flush. 00810 // 00811 00812 Length = (ULONG)Lfcb->SystemPageSize; 00813 00814 } else { 00815 00816 RaiseCorrupt = TRUE; 00817 } 00818 00819 // 00820 // Otherwise these are log record pages 00821 // 00822 00823 } else { 00824 00825 PLFS_RECORD_PAGE_HEADER RecordPageHeader; 00826 00827 ULONG Count; 00828 00829 // 00830 // Mark the last Lsn fields for the page headers and each 00831 // page's position in the transfer. Also unpin all of the 00832 // log pages. 00833 // 00834 00835 Count = 1; 00836 00837 ThisLbcb = FirstLbcb; 00838 00839 while (TRUE) { 00840 00841 // 00842 // If we have to use the tail copy, then pin a page to use. 00843 // 00844 00845 if (UseTailCopy) { 00846 00847 BOOLEAN UsaError; 00848 00849 if (!NT_SUCCESS( LfsPinOrMapData( Lfcb, 00850 TargetLbcb->FileOffset, 00851 (ULONG)Lfcb->LogPageSize, 00852 TRUE, 00853 TRUE, 00854 TRUE, 00855 &UsaError, 00856 &RecordPageHeader, 00857 &PageBcb ))) { 00858 00859 RaiseCorrupt = TRUE; 00860 break; 00861 } 00862 00863 } else { 00864 00865 PUSHORT SeqNumber; 00866 00867 RecordPageHeader = (PLFS_RECORD_PAGE_HEADER) ThisLbcb->PageHeader; 00868 00869 // 00870 // If the sequence number is zero then this is probably a 00871 // page of zeroes produced by the cache manager. In order 00872 // to insure that we don't have the same sequence number 00873 // on each page we will seed the sequence number. 00874 // 00875 00876 SeqNumber = Add2Ptr( RecordPageHeader, 00877 Lfcb->LogRecordUsaOffset, 00878 PUSHORT ); 00879 00880 if (*SeqNumber == 0) { 00881 00882 *SeqNumber = LfsUsaSeqNumber; 00883 LfsUsaSeqNumber += 1; 00884 } 00885 } 00886 00887 // 00888 // Make sure the modified bit gets set in the pfn database. The 00889 // cache manager should do this even for files we told him not to 00890 // lazy write. 00891 // 00892 00893 if (UseTailCopy) { 00894 00895 // 00896 // Store the file offset of the real page in the header. 00897 // Also set the flag indicating the page is a tail copy. 00898 // 00899 00900 RtlCopyMemory( RecordPageHeader, 00901 ThisLbcb->PageHeader, 00902 (ULONG)Lfcb->LogPageSize ); 00903 00904 RecordPageHeader->Copy.FileOffset = ThisLbcb->FileOffset; 00905 } 00906 00907 // 00908 // We update all of fields as yet not updated. 00909 // 00910 00911 RecordPageHeader->PagePosition = (USHORT) Count; 00912 RecordPageHeader->PageCount = (USHORT) IoBlocks; 00913 00914 // 00915 // We set up the update sequence array for this structure. 00916 // 00917 00918 Signature = (PULONG) &RecordPageHeader->MultiSectorHeader.Signature; 00919 *Signature = LFS_SIGNATURE_RECORD_PAGE_ULONG; 00920 00921 RecordPageHeader->MultiSectorHeader.UpdateSequenceArrayOffset 00922 = Lfcb->LogRecordUsaOffset; 00923 00924 RecordPageHeader->MultiSectorHeader.UpdateSequenceArraySize 00925 = Lfcb->LogRecordUsaArraySize; 00926 00927 // 00928 // Make sure the modified bit gets set in the pfn database. The 00929 // cache manager should do this even for files we told him not to 00930 // lazy write. 00931 // 00932 00933 if (UseTailCopy) { 00934 00935 CcSetDirtyPinnedData( PageBcb, NULL ); 00936 00937 CcUnpinData( PageBcb ); 00938 PageBcb = NULL; 00939 00940 } else { 00941 00942 CcSetDirtyPinnedData( ThisLbcb->LogPageBcb, NULL ); 00943 00944 // 00945 // We unpin any buffers pinned on this page. 00946 // 00947 00948 CcUnpinDataForThread( ThisLbcb->LogPageBcb, ThisLbcb->ResourceThread ); 00949 } 00950 00951 // 00952 // Remember the last lsn and its length if this is the final 00953 // page of an Lsn. 00954 // 00955 00956 if (FlagOn( ThisLbcb->Flags, LOG_PAGE_LOG_RECORD_END )) { 00957 00958 LastLsn = ThisLbcb->LastEndLsn; 00959 ValidLastLsn = TRUE; 00960 } 00961 00962 // 00963 // Exit the loop if this is the last block. 00964 // 00965 00966 if (Count == IoBlocks) { 00967 00968 break; 00969 } 00970 00971 // 00972 // Otherwise move to the next entry. 00973 // 00974 00975 ThisLbcb = CONTAINING_RECORD( ThisLbcb->WorkqueLinks.Flink, 00976 LBCB, 00977 WorkqueLinks ); 00978 00979 Count += 1; 00980 } 00981 } 00982 00983 // 00984 // Remember the range we are flushing and find the second half of a page 00985 // if necessary. 00986 // 00987 00988 Lfcb->UserWriteData->FileOffset = FileOffset; 00989 Lfcb->UserWriteData->Length = Length; 00990 00991 if (!UseTailCopy && !LfsRestart) { 00992 00993 PLBCB TailLbcb; 00994 PLIST_ENTRY Links; 00995 LONGLONG NextOffset; 00996 00997 // 00998 // We are flushing log records. If the current request does not end on 00999 // a system page boundary then check if there is another page in 01000 // memory that we are concerned with. 01001 // 01002 01003 if (FlagOn( (ULONG)(FileOffset + Length), (PAGE_SIZE - 1) )) { 01004 01005 NextOffset = FileOffset + Length; 01006 01007 LfsAcquireLfcb( Lfcb ); 01008 01009 // 01010 // Start by looking through the Lbcbs on the active queue. 01011 // 01012 01013 Links = Lfcb->LbcbActive.Flink; 01014 01015 while (Links != &Lfcb->LbcbActive) { 01016 01017 TailLbcb = CONTAINING_RECORD( Links, 01018 LBCB, 01019 ActiveLinks ); 01020 01021 if (TailLbcb->FileOffset == NextOffset) { 01022 01023 Lfcb->PageToDirty = TailLbcb; 01024 break; 01025 } 01026 01027 Links = Links->Flink; 01028 } 01029 01030 // 01031 // If we didn't find it then scan to the end of the workque. 01032 // 01033 01034 if (Lfcb->PageToDirty == NULL) { 01035 01036 Links = Lfcb->LbcbWorkque.Flink; 01037 01038 while (Links != &Lfcb->LbcbWorkque) { 01039 01040 TailLbcb = CONTAINING_RECORD( Links, 01041 LBCB, 01042 WorkqueLinks ); 01043 01044 if (TailLbcb->FileOffset == NextOffset) { 01045 01046 Lfcb->PageToDirty = TailLbcb; 01047 break; 01048 } 01049 01050 Links = Links->Flink; 01051 } 01052 } 01053 01054 // 01055 // If we found an Lbcb then unpin the page temporarily. 01056 // Other users will have to detect this is not pinned. 01057 // 01058 01059 if (Lfcb->PageToDirty != NULL) { 01060 01061 // 01062 // Go ahead and map this page to keep the virtual address 01063 // valid. 01064 // 01065 01066 CcMapData( Lfcb->FileObject, 01067 (PLARGE_INTEGER) &Lfcb->PageToDirty->FileOffset, 01068 (ULONG) Lfcb->LogPageSize, 01069 TRUE, 01070 &MapPageBcb, 01071 &MapPage ); 01072 01073 CcUnpinDataForThread( Lfcb->PageToDirty->LogPageBcb, 01074 Lfcb->PageToDirty->ResourceThread ); 01075 01076 Lfcb->PageToDirty->LogPageBcb = NULL; 01077 } 01078 01079 LfsReleaseLfcb( Lfcb ); 01080 } 01081 } 01082 01083 // 01084 // We are ready to do the I/O. Flush the pages to the log file. 01085 // 01086 01087 CcFlushCache( Lfcb->FileObject->SectionObjectPointer, 01088 (PLARGE_INTEGER)&FileOffset, 01089 Length, 01090 &Iosb ); 01091 01092 // 01093 // Recover the state of any partial page first. 01094 // 01095 01096 if (Lfcb->PageToDirty != NULL) { 01097 01098 LfsPreparePinWriteData( Lfcb, 01099 Lfcb->PageToDirty->FileOffset, 01100 (ULONG) Lfcb->LogPageSize, 01101 &Lfcb->PageToDirty->PageHeader, 01102 &Lfcb->PageToDirty->LogPageBcb ); 01103 01104 Lfcb->PageToDirty->ResourceThread = ExGetCurrentResourceThread(); 01105 Lfcb->PageToDirty = NULL; 01106 01107 CcUnpinData( MapPageBcb ); 01108 MapPageBcb = NULL; 01109 } 01110 01111 if (!NT_SUCCESS( Iosb.Status )) { 01112 01113 LONG BytesRemaining = (LONG) Length; 01114 01115 // 01116 // If we get an error then try each individual page. 01117 // 01118 01119 while (BytesRemaining > 0) { 01120 01121 // 01122 // Remember the range we are flushing and find the second half of a page 01123 // if necessary. 01124 // 01125 01126 Lfcb->UserWriteData->FileOffset = FileOffset; 01127 Lfcb->UserWriteData->Length = Length; 01128 01129 if (!UseTailCopy && !LfsRestart) { 01130 01131 PLBCB TailLbcb; 01132 PLIST_ENTRY Links; 01133 LONGLONG NextOffset; 01134 01135 // 01136 // We are flushing log records. If the current request does not end on 01137 // a system page boundary then check if there is another page in 01138 // memory that we are concerned with. 01139 // 01140 01141 if (FlagOn( (ULONG)(FileOffset + Length), (PAGE_SIZE - 1) )) { 01142 01143 NextOffset = FileOffset + Length; 01144 01145 LfsAcquireLfcb( Lfcb ); 01146 01147 // 01148 // Start by looking through the Lbcbs on the active queue. 01149 // 01150 01151 Links = Lfcb->LbcbActive.Flink; 01152 01153 while (Links != &Lfcb->LbcbActive) { 01154 01155 TailLbcb = CONTAINING_RECORD( Links, 01156 LBCB, 01157 ActiveLinks ); 01158 01159 if (TailLbcb->FileOffset == NextOffset) { 01160 01161 Lfcb->PageToDirty = TailLbcb; 01162 break; 01163 } 01164 01165 Links = Links->Flink; 01166 } 01167 01168 // 01169 // If we didn't find it then scan to the end of the workque. 01170 // 01171 01172 if (Lfcb->PageToDirty == NULL) { 01173 01174 Links = Lfcb->LbcbWorkque.Flink; 01175 01176 while (Links != &Lfcb->LbcbWorkque) { 01177 01178 TailLbcb = CONTAINING_RECORD( Links, 01179 LBCB, 01180 WorkqueLinks ); 01181 01182 if (TailLbcb->FileOffset == NextOffset) { 01183 01184 Lfcb->PageToDirty = TailLbcb; 01185 break; 01186 } 01187 01188 Links = Links->Flink; 01189 } 01190 } 01191 01192 // 01193 // If we found an Lbcb then unpin the page temporarily. 01194 // Other users will have to detect this is not pinned. 01195 // 01196 01197 if (Lfcb->PageToDirty != NULL) { 01198 01199 CcMapData( Lfcb->FileObject, 01200 (PLARGE_INTEGER) &Lfcb->PageToDirty->FileOffset, 01201 (ULONG) Lfcb->PageToDirty->Length, 01202 TRUE, 01203 &MapPageBcb, 01204 &MapPage ); 01205 01206 CcUnpinDataForThread( Lfcb->PageToDirty->LogPageBcb, 01207 Lfcb->PageToDirty->ResourceThread ); 01208 01209 Lfcb->PageToDirty->LogPageBcb = NULL; 01210 } 01211 } 01212 LfsReleaseLfcb( Lfcb ); 01213 } 01214 01215 CcFlushCache( Lfcb->FileObject->SectionObjectPointer, 01216 (PLARGE_INTEGER)&FileOffset, 01217 (ULONG)Lfcb->SystemPageSize, 01218 &Iosb ); 01219 01220 // 01221 // Recover the state of any partial page first. 01222 // 01223 01224 if (Lfcb->PageToDirty != NULL) { 01225 01226 LfsPreparePinWriteData( Lfcb, 01227 Lfcb->PageToDirty->FileOffset, 01228 (ULONG) Lfcb->PageToDirty->Length, 01229 &Lfcb->PageToDirty->PageHeader, 01230 &Lfcb->PageToDirty->LogPageBcb ); 01231 01232 Lfcb->PageToDirty->ResourceThread = ExGetCurrentResourceThread(); 01233 Lfcb->PageToDirty = NULL; 01234 01235 CcUnpinData( MapPageBcb ); 01236 MapPageBcb = NULL; 01237 } 01238 01239 if (!NT_SUCCESS( Iosb.Status )) { 01240 01241 #ifdef NTFS_RESTART 01242 ASSERT( FALSE ); 01243 #endif 01244 RaiseCorrupt = TRUE; 01245 } 01246 01247 BytesRemaining -= (LONG)Lfcb->SystemPageSize; 01248 FileOffset = FileOffset + Lfcb->SystemPageSize; 01249 } 01250 } 01251 01252 // 01253 // Reacquire the Lfcb, remembering that we have it. 01254 // 01255 01256 if (!UseTailCopy) { 01257 01258 LfsAcquireLfcb( Lfcb ); 01259 } 01260 01261 // 01262 // Update the last flushed Lsn value if this isn't a 01263 // restart write. 01264 // 01265 01266 if (!LfsRestart) { 01267 01268 if (ValidLastLsn) { 01269 01270 Lfcb->LastFlushedLsn = LastLsn; 01271 } 01272 01273 // 01274 // Remember the Lsn we assigned to this restart area. 01275 // 01276 01277 } else { 01278 01279 Lfcb->LastFlushedRestartLsn = LastLsn; 01280 01281 // 01282 // Clear any neccessary flags on a successful operation. 01283 // 01284 01285 if (!RaiseCorrupt) { 01286 01287 ClearFlag( Lfcb->Flags, NewLfcbFlags ); 01288 NewLfcbFlags = 0; 01289 } 01290 01291 // 01292 // If this is the first write of a restart area and we have 01293 // updated the LogOpenCount then update the field in the Lfcb. 01294 // 01295 01296 if (NT_SUCCESS( Iosb.Status ) && 01297 (Lfcb->CurrentOpenLogCount != ((PLFS_RESTART_AREA) FirstLbcb->PageHeader)->RestartOpenLogCount)) { 01298 01299 Lfcb->CurrentOpenLogCount = ((PLFS_RESTART_AREA) FirstLbcb->PageHeader)->RestartOpenLogCount; 01300 } 01301 } 01302 01303 // 01304 // Walk through all the Lbcb's we flushed, deallocating the Lbcbs. 01305 // 01306 01307 if (!UseTailCopy) { 01308 01309 PLBCB TempLbcb; 01310 01311 ThisLbcb = FirstLbcb; 01312 01313 while (TRUE) { 01314 01315 // 01316 // Remember the next entry on the list. 01317 // 01318 01319 TempLbcb = CONTAINING_RECORD( ThisLbcb->WorkqueLinks.Flink, 01320 LBCB, 01321 WorkqueLinks ); 01322 01323 // 01324 // Remove it from the LbcbWorkque queue. 01325 // 01326 01327 RemoveEntryList( &ThisLbcb->WorkqueLinks ); 01328 01329 // 01330 // Deallocate the structure. 01331 // 01332 01333 LfsDeallocateLbcb( Lfcb, ThisLbcb ); 01334 01335 if (IoBlocks-- == 1) { 01336 01337 break; 01338 } 01339 01340 ThisLbcb = TempLbcb; 01341 } 01342 } 01343 01344 // 01345 // If we flushed the Lbcb we were interested in, we are done. 01346 // We will signal all waiting threads regardless 01347 // 01348 01349 KeSetEvent( &Lfcb->Sync->Event, 0, FALSE ); 01350 01351 // 01352 // Remember the starting Lbcb for the next I/O. 01353 // 01354 01355 FirstLbcb = NextLbcb; 01356 } 01357 01358 try_exit: NOTHING; 01359 } finally { 01360 01361 DebugUnwind( LfsFlushLfcb ); 01362 01363 ASSERT( Lfcb->PageToDirty == NULL ); 01364 01365 // 01366 // Show that there is no Io in progress. 01367 // 01368 01369 Lfcb->LfsIoState = LfsNoIoInProgress; 01370 #ifdef BRIANDBG 01371 Lfcb->LfsIoThread = 0; 01372 #endif 01373 01374 // 01375 // Make sure we didn't leave any pages pinned. 01376 // 01377 01378 if (PageBcb != NULL) { 01379 01380 CcUnpinData( PageBcb ); 01381 } 01382 01383 DebugTrace( -1, Dbg, "LfsFlushLfcb: Exit\n", 0 ); 01384 } 01385 01386 // 01387 // If the Io failed at some point, we raise a corrupt disk error. 01388 // The only exception is if this is the final flush of the log file. 01389 // In this case the client may not be able to cleanup after this error. 01390 // 01391 01392 if (RaiseCorrupt && (!FlagOn( Lfcb->Flags, LFCB_FINAL_SHUTDOWN ))) { 01393 01394 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 01395 } 01396 01397 return; 01398 }

VOID LfsFlushToLsnPriv IN PLFCB  Lfcb,
IN LSN  Lsn
 

Definition at line 134 of file lbcbsup.c.

References _LBCB::ActiveLinks, ClearFlag, Dbg, DebugTrace, ExRaiseStatus(), FALSE, FlagOn, _LBCB::Flags, LBCB_ON_ACTIVE_QUEUE, _LBCB::LbcbFlags, LFCB_PACK_LOG, LfsCurrentAvailSpace(), LfsFlushLbcb(), LfsLbcbIsRestart, LOG_PAGE_LOG_RECORD_END, NULL, PAGED_CODE, and TRUE.

Referenced by LfsFlushToLsn(), and LfsForceWrite().

00141 : 00142 00143 This routine is the worker routine which performs the work of flushing 00144 a particular Lsn to disk. This routine is always called with the 00145 Lfcb acquired. This routines makes no guarantee about whether the Lfcb 00146 is acquired on exit. 00147 00148 Arguments: 00149 00150 Lfcb - This is the file control block for the log file. 00151 00152 Lsn - This is the Lsn to flush to disk. 00153 00154 Return Value: 00155 00156 None. 00157 00158 --*/ 00159 00160 { 00161 BOOLEAN UseLastRecordLbcb = FALSE; 00162 PLBCB LastRecordLbcb = NULL; 00163 00164 PAGED_CODE(); 00165 00166 DebugTrace( +1, Dbg, "LfsFlushToLsnPriv: Entered\n", 0 ); 00167 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00168 DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn.LowPart ); 00169 DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn.HighPart ); 00170 00171 // 00172 // We check if the Lsn is in the valid range. Raising an 00173 // exception if not. 00174 // 00175 00176 if (Lsn.QuadPart > Lfcb->RestartArea->CurrentLsn.QuadPart) { 00177 00178 UseLastRecordLbcb = TRUE; 00179 } 00180 00181 // 00182 // If the Lsn has already been flushed we are done. 00183 // Otherwise we need to look through the workqueues and the 00184 // active queue. 00185 // 00186 00187 if (Lsn.QuadPart > Lfcb->LastFlushedLsn.QuadPart) { 00188 00189 PLIST_ENTRY ThisEntry; 00190 PLBCB ThisLbcb; 00191 00192 // 00193 // Check the workqueue first. We are looking for the last 00194 // buffer block of a log page block which contains this 00195 // Lsn. 00196 // 00197 00198 ThisEntry = Lfcb->LbcbWorkque.Flink; 00199 00200 // 00201 // We keep looping. 00202 // 00203 00204 while (TRUE) { 00205 00206 ThisLbcb = CONTAINING_RECORD( ThisEntry, 00207 LBCB, 00208 WorkqueLinks ); 00209 00210 // 00211 // We pass over any restart areas. We also skip any 00212 // Lbcb's which do not contain the end of a log record. 00213 // 00214 00215 if (!LfsLbcbIsRestart( ThisLbcb ) 00216 && FlagOn( ThisLbcb->Flags, LOG_PAGE_LOG_RECORD_END )) { 00217 00218 LastRecordLbcb = ThisLbcb; 00219 00220 // 00221 // If the last complete Lsn in this Lbcb is greater or equal 00222 // to the desired Lsn, we exit the loop. 00223 // 00224 00225 if (ThisLbcb->LastEndLsn.QuadPart >= Lsn.QuadPart) { 00226 00227 break; 00228 } 00229 } 00230 00231 // 00232 // Otherwise move to the next Lbcb. 00233 // 00234 00235 ThisEntry = ThisEntry->Flink; 00236 00237 // 00238 // If we have reached the end of the list then break out. We 00239 // were given an Lsn which is larger than any flushed Lsn so 00240 // we will just flush to the end of the log file. 00241 // 00242 00243 if (ThisEntry == &Lfcb->LbcbWorkque) { 00244 00245 if (UseLastRecordLbcb) { 00246 00247 ThisLbcb = LastRecordLbcb; 00248 } 00249 00250 break; 00251 } 00252 } 00253 00254 if (ThisLbcb != NULL) { 00255 00256 // 00257 // If we are not supporting a packed log file and this Lbcb is from 00258 // the active queue, we need to check that losing the tail of the 00259 // will not swallow up any of our reserved space. 00260 // 00261 00262 if (!FlagOn( Lfcb->Flags, LFCB_PACK_LOG ) 00263 && FlagOn( ThisLbcb->LbcbFlags, LBCB_ON_ACTIVE_QUEUE )) { 00264 00265 LONGLONG CurrentAvail; 00266 LONGLONG UnusedBytes; 00267 00268 // 00269 // Find the unused bytes. 00270 // 00271 00272 UnusedBytes = 0; 00273 00274 LfsCurrentAvailSpace( Lfcb, 00275 &CurrentAvail, 00276 (PULONG)&UnusedBytes ); 00277 00278 CurrentAvail = CurrentAvail - Lfcb->TotalUndoCommitment; 00279 00280 if (UnusedBytes > CurrentAvail) { 00281 00282 DebugTrace( -1, Dbg, "Have to preserve these bytes for possible aborts\n", 0 ); 00283 00284 ExRaiseStatus( STATUS_LOG_FILE_FULL ); 00285 } 00286 00287 // 00288 // We want to make sure we don't write any more data into this 00289 // page. Remove this from the active queue. 00290 // 00291 00292 RemoveEntryList( &ThisLbcb->ActiveLinks ); 00293 ClearFlag( ThisLbcb->LbcbFlags, LBCB_ON_ACTIVE_QUEUE ); 00294 } 00295 00296 // 00297 // We now have the Lbcb we want to flush to disk. 00298 // 00299 00300 LfsFlushLbcb( Lfcb, ThisLbcb ); 00301 } 00302 } 00303 00304 DebugTrace( -1, Dbg, "LfsFlushToLsnPriv: Exit\n", 0 ); 00305 00306 return; 00307 }

VOID LfsFreeSpanningBuffer IN PVOID  Buffer  ) 
 

Definition at line 297 of file logpgsup.c.

References ASSERT, Buffer, _LFS_DATA::Buffer1, _LFS_DATA::BufferFlags, _LFS_DATA::BufferOwner, ClearFlag, Dbg, DebugTrace, ERESOURCE_THREAD, ExGetCurrentResourceThread, FlagOn, LFS_BUFFER1_OWNED, LFS_BUFFER2_OWNED, LfsAcquireBufferLock, LfsData, LfsFreePool, LfsNotifyBufferWaiters, LfsReleaseBufferLock, NULL, and PAGED_CODE.

Referenced by LfsDeallocateLcb(), LfsFindLogRecord(), and LfsReadNextLogRecord().

00303 : 00304 00305 This routine is called to free a buffer used to read a log record 00306 which spans pages. We will check if it is one of our special buffers 00307 and deal with synchronization in that case. 00308 00309 Arguments: 00310 00311 Buffer - Buffer to free. 00312 00313 Return Value: 00314 00315 None. 00316 00317 --*/ 00318 00319 { 00320 ERESOURCE_THREAD Thread; 00321 00322 PAGED_CODE(); 00323 00324 DebugTrace( +1, Dbg, "LfsFreeSpanningBuffer: Entered\n", 0 ); 00325 00326 // 00327 // Do an unsafe test of the buffer flags. If we own a buffer then they must be non-zero. 00328 // Otherwise do the correct check of the resource thread. 00329 // 00330 00331 if (!FlagOn( LfsData.BufferFlags, LFS_BUFFER1_OWNED | LFS_BUFFER2_OWNED ) || 00332 (LfsData.BufferOwner != ExGetCurrentResourceThread())) { 00333 00334 LfsFreePool( Buffer ); 00335 00336 } else { 00337 00338 // 00339 // Acquire the lock for synchronization. 00340 // 00341 00342 LfsAcquireBufferLock(); 00343 00344 // 00345 // Check which buffer it is. 00346 // 00347 00348 if (Buffer == LfsData.Buffer1) { 00349 00350 ClearFlag( LfsData.BufferFlags, LFS_BUFFER1_OWNED ); 00351 00352 } else { 00353 00354 // 00355 // It better be buffer2 00356 // 00357 00358 ASSERT( FlagOn( LfsData.BufferFlags, LFS_BUFFER2_OWNED )); 00359 ClearFlag( LfsData.BufferFlags, LFS_BUFFER2_OWNED ); 00360 } 00361 00362 // 00363 // If no buffers owned then signal the waiters. 00364 // 00365 00366 if (!FlagOn( LfsData.BufferFlags, LFS_BUFFER1_OWNED | LFS_BUFFER2_OWNED )) { 00367 00368 LfsData.BufferOwner = (ERESOURCE_THREAD) NULL; 00369 LfsNotifyBufferWaiters(); 00370 } 00371 00372 LfsReleaseBufferLock(); 00373 } 00374 00375 DebugTrace( -1, Dbg, "LfsFreeSpanningBuffer: Exit\n", 0 ); 00376 00377 return; 00378 }

PLBCB LfsGetLbcb IN PLFCB  Lfcb  ) 
 

Definition at line 311 of file lbcbsup.c.

References _LBCB::ActiveLinks, _LBCB::BufferOffset, CcSetBcbOwnerPointer(), CcUnpinData(), ClearFlag, Dbg, DebugTrace, DebugUnwind, ERESOURCE_THREAD, ExGetCurrentResourceThread, _LBCB::FileOffset, FlagOn, _LBCB::Flags, KeBugCheck(), _LBCB::LastEndLsn, _LBCB::LastLsn, LBCB_FLUSH_COPY, LBCB_LOG_WRAPPED, LBCB_ON_ACTIVE_QUEUE, _LBCB::LbcbFlags, _LBCB::Length, LFCB_LOG_WRAPPED, LFCB_NO_LAST_LSN, LFCB_REUSE_TAIL, LFS_SIGNATURE_RECORD_PAGE_ULONG, LfsAllocateLbcb(), LfsDeallocateLbcb(), LfsGetLbcb(), LfsNextLogPageOffset(), LfsPreparePinWriteData, _LBCB::LogPageBcb, NULL, PAGED_CODE, _LBCB::PageHeader, _LBCB::ResourceThread, _LBCB::SeqNumber, and SetFlag.

Referenced by LfsGetLbcb(), and LfsPrepareLfcbForLogRecord().

00317 : 00318 00319 This routine is called to add a Lbcb to the active queue. 00320 00321 Arguments: 00322 00323 Lfcb - This is the file control block for the log file. 00324 00325 Return Value: 00326 00327 PLBCB - Pointer to the Lbcb allocated. 00328 00329 --*/ 00330 00331 { 00332 PLBCB Lbcb = NULL; 00333 PVOID PageHeader; 00334 PBCB PageHeaderBcb = NULL; 00335 00336 BOOLEAN WrappedOrUsaError; 00337 00338 PAGED_CODE(); 00339 00340 DebugTrace( +1, Dbg, "LfsGetLbcb: Entered\n", 0 ); 00341 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00342 00343 // 00344 // Use a try-finally to facilitate cleanup. 00345 // 00346 00347 try { 00348 00349 // 00350 // Pin the desired record page. 00351 // 00352 00353 LfsPreparePinWriteData( Lfcb, 00354 Lfcb->NextLogPage, 00355 (ULONG)Lfcb->LogPageSize, 00356 &PageHeader, 00357 &PageHeaderBcb ); 00358 00359 // 00360 // Put our signature into the page so we won't fail if we 00361 // see a previous 'BAAD' signature. 00362 // 00363 00364 *((PULONG) PageHeader) = LFS_SIGNATURE_RECORD_PAGE_ULONG; 00365 00366 // 00367 // Now allocate an Lbcb. 00368 // 00369 00370 LfsAllocateLbcb( Lfcb, &Lbcb ); 00371 00372 // 00373 // If we are at the beginning of the file we test that the 00374 // sequence number won't wrap to 0. 00375 // 00376 00377 if (!FlagOn( Lfcb->Flags, LFCB_NO_LAST_LSN | LFCB_REUSE_TAIL ) 00378 && ( Lfcb->NextLogPage == Lfcb->FirstLogPage )) { 00379 00380 Lfcb->SeqNumber = Lfcb->SeqNumber + 1; 00381 00382 // 00383 // If the sequence number is going from 0 to 1, then 00384 // this is the first time the log file has wrapped. We want 00385 // to remember this because it means that we can now do 00386 // large spiral writes. 00387 // 00388 00389 if (Int64ShllMod32( Lfcb->SeqNumber, Lfcb->FileDataBits ) == 0) { 00390 00391 DebugTrace( 0, Dbg, "Log sequence number about to wrap: Lfcb -> %08lx\n", Lfcb ); 00392 KeBugCheck( FILE_SYSTEM ); 00393 } 00394 00395 // 00396 // If this number is greater or equal to the wrap sequence number in 00397 // the Lfcb, set the wrap flag in the Lbcb. 00398 // 00399 00400 if (!FlagOn( Lfcb->Flags, LFCB_LOG_WRAPPED ) 00401 && ( Lfcb->SeqNumber >= Lfcb->SeqNumberForWrap )) { 00402 00403 SetFlag( Lbcb->LbcbFlags, LBCB_LOG_WRAPPED ); 00404 SetFlag( Lfcb->Flags, LFCB_LOG_WRAPPED ); 00405 } 00406 } 00407 00408 // 00409 // Now initialize the rest of the Lbcb fields. 00410 // 00411 00412 Lbcb->FileOffset = Lfcb->NextLogPage; 00413 Lbcb->SeqNumber = Lfcb->SeqNumber; 00414 Lbcb->BufferOffset = Lfcb->LogPageDataOffset; 00415 00416 // 00417 // Store the next page in the Lfcb. 00418 // 00419 00420 LfsNextLogPageOffset( Lfcb, 00421 Lfcb->NextLogPage, 00422 &Lfcb->NextLogPage, 00423 &WrappedOrUsaError ); 00424 00425 Lbcb->Length = Lfcb->LogPageSize; 00426 Lbcb->PageHeader = PageHeader; 00427 Lbcb->LogPageBcb = PageHeaderBcb; 00428 00429 Lbcb->ResourceThread = ExGetCurrentResourceThread(); 00430 Lbcb->ResourceThread = (ERESOURCE_THREAD) ((ULONG) Lbcb->ResourceThread | 3); 00431 00432 // 00433 // If we are reusing a previous page then set a flag in 00434 // the Lbcb to indicate that we should flush a copy 00435 // first. 00436 // 00437 00438 if (FlagOn( Lfcb->Flags, LFCB_REUSE_TAIL )) { 00439 00440 SetFlag( Lbcb->LbcbFlags, LBCB_FLUSH_COPY ); 00441 ClearFlag( Lfcb->Flags, LFCB_REUSE_TAIL ); 00442 00443 (ULONG)Lbcb->BufferOffset = Lfcb->ReusePageOffset; 00444 00445 Lbcb->Flags = ((PLFS_RECORD_PAGE_HEADER) PageHeader)->Flags; 00446 Lbcb->LastLsn = ((PLFS_RECORD_PAGE_HEADER) PageHeader)->Copy.LastLsn; 00447 Lbcb->LastEndLsn = ((PLFS_RECORD_PAGE_HEADER) PageHeader)->Header.Packed.LastEndLsn; 00448 } 00449 00450 // 00451 // Put the Lbcb on the active queue 00452 // 00453 00454 InsertTailList( &Lfcb->LbcbActive, &Lbcb->ActiveLinks ); 00455 00456 SetFlag( Lbcb->LbcbFlags, LBCB_ON_ACTIVE_QUEUE ); 00457 00458 // 00459 // Now that we have succeeded, set the owner thread to Thread + 1 so the resource 00460 // package will know not to peek in this thread. It may be deallocated before 00461 // we release the Bcb during flush. 00462 // 00463 00464 CcSetBcbOwnerPointer( Lbcb->LogPageBcb, (PVOID) Lbcb->ResourceThread ); 00465 00466 } finally { 00467 00468 DebugUnwind( LfsGetLbcb ); 00469 00470 // 00471 // If an error occurred, we need to clean up any blocks which 00472 // have not been added to the active queue. 00473 // 00474 00475 if (AbnormalTermination()) { 00476 00477 if (Lbcb != NULL) { 00478 00479 LfsDeallocateLbcb( Lfcb, Lbcb ); 00480 Lbcb = NULL; 00481 } 00482 00483 // 00484 // Unpin the system page if pinned. 00485 // 00486 00487 if (PageHeaderBcb != NULL) { 00488 00489 CcUnpinData( PageHeaderBcb ); 00490 } 00491 } 00492 00493 DebugTrace( -1, Dbg, "LfsGetLbcb: Exit\n", 0 ); 00494 } 00495 00496 return Lbcb; 00497 } }

VOID LfsLsnFinalOffset IN PLFCB  Lfcb,
IN LSN  Lsn,
IN ULONG  DataLength,
OUT PLONGLONG  FinalOffset
 

Definition at line 36 of file lsnsup.c.

References Dbg, DebugTrace, LfsLsnToPageOffset, LfsNextLogPageOffset(), LfsTruncateLsnToLogPage, PAGED_CODE, and TRUE.

Referenced by LfsFindNextLsn(), and LfsUpdateLfcbFromRestart().

00045 : 00046 00047 This routine will compute the final offset of the last byte of the log 00048 record. It does this by computing how many bytes are on the current 00049 page and then computing how many more pages will be needed. 00050 00051 Arguments: 00052 00053 Lfcb - This is the file control block for the log file. 00054 00055 Lsn - This is the log record being considered. 00056 00057 DataLength - This is the length of the data for this log record. We will add the 00058 header length here. 00059 00060 FinalOffset - Address to store the result. 00061 00062 Return Value: 00063 00064 None. 00065 00066 --*/ 00067 00068 { 00069 ULONG RemainingPageBytes; 00070 ULONG PageOffset; 00071 00072 PAGED_CODE(); 00073 00074 DebugTrace( +1, Dbg, "LfsLsnFinalOffset: Entered\n", 0 ); 00075 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00076 DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn.LowPart ); 00077 DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn.HighPart ); 00078 DebugTrace( 0, Dbg, "DataLength -> %08lx\n", DataLength ); 00079 00080 // 00081 // We compute the starting log page file offset, the number of bytes 00082 // remaining in the current log page and the position on this page 00083 // before any data bytes. 00084 // 00085 00086 LfsTruncateLsnToLogPage( Lfcb, Lsn, FinalOffset ); 00087 00088 PageOffset = LfsLsnToPageOffset( Lfcb, Lsn ); 00089 00090 RemainingPageBytes = (ULONG)Lfcb->LogPageSize - PageOffset; 00091 00092 PageOffset -= 1; 00093 00094 // 00095 // Add the length of the header. 00096 // 00097 00098 DataLength += Lfcb->RecordHeaderLength; 00099 00100 // 00101 // If this Lsn is contained in this log page we are done. 00102 // Otherwise we need to walk through several log pages. 00103 // 00104 00105 if (DataLength > RemainingPageBytes) { 00106 00107 DataLength -= RemainingPageBytes; 00108 00109 RemainingPageBytes = (ULONG)Lfcb->LogPageDataSize; 00110 00111 PageOffset = (ULONG)Lfcb->LogPageDataOffset - 1; 00112 00113 while (TRUE) { 00114 00115 BOOLEAN Wrapped; 00116 00117 LfsNextLogPageOffset( Lfcb, *FinalOffset, FinalOffset, &Wrapped ); 00118 00119 // 00120 // We are done if the remaining bytes fit on this page. 00121 // 00122 00123 if (DataLength <= RemainingPageBytes) { 00124 00125 break; 00126 } 00127 00128 DataLength -= RemainingPageBytes; 00129 } 00130 } 00131 00132 // 00133 // We add the remaining bytes to our starting position on this page 00134 // and then add that value to the file offset of this log page. 00135 // 00136 00137 *(PULONG)FinalOffset += (DataLength + PageOffset); 00138 00139 DebugTrace( 0, Dbg, "FinalOffset (Low) -> %08lx\n", LogPageFileOffset.LowPart ); 00140 DebugTrace( 0, Dbg, "FinalOffset (High) -> %08lx\n", LogPageFileOffset.HighPart ); 00141 DebugTrace( -1, Dbg, "LfsLsnFinalOffset: Exit\n", 0 ); 00142 00143 return; 00144 }

VOID LfsNextLogPageOffset IN PLFCB  Lfcb,
IN LONGLONG  CurrentLogPageOffset,
OUT PLONGLONG  NextLogPageOffset,
OUT PBOOLEAN  Wrapped
 

Definition at line 40 of file logpgsup.c.

References Dbg, DebugTrace, FALSE, LfsTruncateOffsetToLogPage, PAGED_CODE, and TRUE.

Referenced by LfsCopyReadLogRecord(), LfsFindLastLsn(), LfsFindNextLsn(), LfsGetLbcb(), LfsLsnFinalOffset(), and LfsUpdateLfcbFromRestart().

00049 : 00050 00051 This routine will compute the offset in the log file of the next log 00052 page. 00053 00054 Arguments: 00055 00056 Lfcb - This is the file control block for the log file. 00057 00058 CurrentLogPageOffset - This is the file offset of the current log page. 00059 00060 NextLogPageOffset - Address to store the next log page to use. 00061 00062 Wrapped - This is a pointer to a boolean variable that, if present, 00063 we use to indicate whether we wrapped in the log file. 00064 00065 Return Value: 00066 00067 None. 00068 00069 --*/ 00070 00071 { 00072 PAGED_CODE(); 00073 00074 DebugTrace( +1, Dbg, "LfsNextLogPageOffset: Entered\n", 0 ); 00075 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00076 DebugTrace( 0, Dbg, "CurrentLogPageOffset (Low) -> %08lx\n", CurrentLogPageOffset.LowPart ); 00077 DebugTrace( 0, Dbg, "CurrentLogPageOffset (High) -> %08lx\n", CurrentLogPageOffset.HighPart ); 00078 DebugTrace( 0, Dbg, "Wrapped -> %08lx\n", Wrapped ); 00079 00080 // 00081 // We add the log page size to the current log offset. 00082 // 00083 00084 LfsTruncateOffsetToLogPage( Lfcb, CurrentLogPageOffset, &CurrentLogPageOffset ); 00085 *NextLogPageOffset = CurrentLogPageOffset + Lfcb->LogPageSize; //**** xxAdd( CurrentLogPageOffset, Lfcb->LogPageSize ); 00086 00087 // 00088 // If the result is larger than the file, we use the first page offset 00089 // in the file. 00090 // 00091 00092 if ( *NextLogPageOffset >= Lfcb->FileSize ) { //**** xxGeq( *NextLogPageOffset, Lfcb->FileSize ) 00093 00094 *NextLogPageOffset = Lfcb->FirstLogPage; 00095 00096 *Wrapped = TRUE; 00097 00098 } else { 00099 00100 *Wrapped = FALSE; 00101 } 00102 00103 DebugTrace( 0, Dbg, "NextLogPageOffset (Low) -> %08lx\n", NextLogPageOffset->LowPart ); 00104 DebugTrace( 0, Dbg, "NextLogPageOffset (High) -> %08lx\n", NextLogPageOffset->HighPart ); 00105 DebugTrace( 0, Dbg, "Wrapped -> %08x\n", *Wrapped ); 00106 DebugTrace( -1, Dbg, "LfsNextLogPageOffset: Exit\n", 0 ); 00107 00108 return; 00109 }

NTSTATUS LfsPinOrMapData IN PLFCB  Lfcb,
IN LONGLONG  FileOffset,
IN ULONG  Length,
IN BOOLEAN  PinData,
IN BOOLEAN  AllowErrors,
IN BOOLEAN  IgnoreUsaErrors,
OUT PBOOLEAN  UsaError,
OUT PVOID *  Buffer,
OUT PBCB Bcb
 

Definition at line 84 of file lfs/cachesup.c.

References Buffer, CcMapData(), CcPinRead(), CcUnpinData(), Dbg, DebugTrace, DebugUnwind, ExRaiseStatus(), FALSE, LFS_SIGNATURE_BAD_USA_ULONG, LfsExceptionFilter(), LfsPinOrMapData(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Status, and TRUE.

Referenced by LfsCopyReadLogRecord(), LfsFindLastLsn(), LfsFindNextLsn(), LfsFlushLfcb(), LfsInitializeLogFilePriv(), LfsPinOrMapData(), LfsPinOrMapLogRecordHeader(), LfsReadRestart(), and LfsRestartLogFile().

00098 : 00099 00100 This routine will pin or map a portion of the log file. 00101 00102 Arguments: 00103 00104 Lfcb - This is the file control block for the log file. 00105 00106 FileOffset - This is the offset of the log page to pin. 00107 00108 Length - This is the length of the data to access. 00109 00110 PinData - Boolean indicating if we are to pin or map this data. 00111 00112 AllowErrors - This boolean indicates whether we should raise on an 00113 I/O error or return on an I/O error. 00114 00115 IgnoreUsaErrors - Boolean indicating whether we will raise on Usa 00116 errors. 00117 00118 UsaError - Address to store whether the Usa had an error. 00119 00120 Buffer - This is the address to store the address of the data. 00121 00122 Bcb - This is the Bcb for this operation. 00123 00124 Return Value: 00125 00126 NTSTATUS - The result of the I/O. 00127 00128 --*/ 00129 00130 { 00131 volatile NTSTATUS Status; 00132 ULONG Signature; 00133 BOOLEAN Result = FALSE; 00134 00135 Status = STATUS_SUCCESS; 00136 00137 PAGED_CODE(); 00138 00139 DebugTrace( +1, Dbg, "LfsPinReadLogPage: Entered\n", 0 ); 00140 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00141 DebugTrace( 0, Dbg, "FileOffset (Low) -> %08lx\n", FileOffset.HighPart ); 00142 DebugTrace( 0, Dbg, "FileOffset (High) -> %08lx\n", FileOffset.LowPart ); 00143 DebugTrace( 0, Dbg, "Length -> %08lx\n", Length ); 00144 DebugTrace( 0, Dbg, "PinData -> %04x\n", PinData ); 00145 DebugTrace( 0, Dbg, "AllowErrors -> %08x\n", AllowErrors ); 00146 DebugTrace( 0, Dbg, "IgnoreUsaErrors -> %04x\n", IgnoreUsaErrors ); 00147 00148 // 00149 // Use a try-finally to facilitate cleanup. 00150 // 00151 00152 try { 00153 00154 // 00155 // Use a try-except to catch cache manager errors. 00156 // 00157 00158 try { 00159 00160 // 00161 // We call the cache to perform the work. 00162 // 00163 00164 if (PinData) { 00165 00166 Result = CcPinRead( Lfcb->FileObject, 00167 (PLARGE_INTEGER)&FileOffset, 00168 Length, 00169 TRUE, 00170 Bcb, 00171 Buffer ); 00172 00173 } else { 00174 00175 Result = CcMapData( Lfcb->FileObject, 00176 (PLARGE_INTEGER)&FileOffset, 00177 Length, 00178 TRUE, 00179 Bcb, 00180 Buffer ); 00181 } 00182 00183 // 00184 // Capture the signature now while we are within the 00185 // exception filter. 00186 // 00187 00188 Signature = *((PULONG) *Buffer); 00189 00190 } except( LfsExceptionFilter( GetExceptionInformation() )) { 00191 00192 Status = GetExceptionCode(); 00193 if (Result) { 00194 CcUnpinData( *Bcb ); 00195 *Bcb = NULL; 00196 } 00197 } 00198 00199 *UsaError = FALSE; 00200 00201 // 00202 // If an error occurred, we raise the status. 00203 // 00204 00205 if (!NT_SUCCESS( Status )) { 00206 00207 if (!AllowErrors) { 00208 00209 DebugTrace( 0, Dbg, "Read on log page failed -> %08lx\n", Status ); 00210 ExRaiseStatus( Status ); 00211 } 00212 00213 // 00214 // Check that the update sequence array for this 00215 // page is valid. 00216 // 00217 00218 } else if (Signature == LFS_SIGNATURE_BAD_USA_ULONG) { 00219 00220 // 00221 // If we don't allow errors, raise an error status. 00222 // 00223 00224 if (!IgnoreUsaErrors) { 00225 00226 DebugTrace( 0, Dbg, "Usa error on log page\n", 0 ); 00227 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00228 } 00229 00230 *UsaError = TRUE; 00231 } 00232 00233 } finally { 00234 00235 DebugUnwind( LfsPinOrMapData ); 00236 00237 DebugTrace( 0, Dbg, "Buffer -> %08lx\n", *Buffer ); 00238 DebugTrace( 0, Dbg, "Bcb -> %08lx\n", *Bcb ); 00239 00240 DebugTrace( -1, Dbg, "LfsPinOrMapData: Exit -> %08lx\n", Status ); 00241 } 00242 00243 return Status; 00244 }

VOID LfsPinOrMapLogRecordHeader IN PLFCB  Lfcb,
IN LSN  Lsn,
IN BOOLEAN  PinData,
IN BOOLEAN  IgnoreUsaErrors,
OUT PBOOLEAN  UsaError,
OUT PLFS_RECORD_HEADER RecordHeader,
OUT PBCB Bcb
 

Definition at line 248 of file lfs/cachesup.c.

References Add2Ptr, Dbg, DebugTrace, FALSE, LfsLsnToPageOffset, LfsPinOrMapData(), LfsTruncateLsnToLogPage, PAGED_CODE, PLFS_RECORD_HEADER, and PLFS_RECORD_PAGE_HEADER.

Referenced by LfsFindClientNextLsn(), LfsFindLogRecord(), LfsReadRestartArea(), and LfsSearchForwardByClient().

00260 : 00261 00262 This routine will pin or map a log record for read access. 00263 00264 Arguments: 00265 00266 Lfcb - This is the file control block for the log file. 00267 00268 Lsn - This is the Lsn whose header should be pinned. 00269 00270 PinData - Boolean indicating if we are to pin or map this data. 00271 00272 IgnoreUsaErrors - Boolean indicating whether we will raise on Usa 00273 errors. 00274 00275 UsaError - Address to store whether the Usa had an error. 00276 00277 RecordHeader - This is the address to store the address of the pinned data. 00278 00279 Bcb - This is the Bcb for this pin operation. 00280 00281 Return Value: 00282 00283 None. 00284 00285 --*/ 00286 00287 { 00288 PLFS_RECORD_PAGE_HEADER LogPageHeader; 00289 LONGLONG LogPage; 00290 ULONG PageOffset; 00291 00292 PAGED_CODE(); 00293 00294 DebugTrace( +1, Dbg, "LfsPinOrMapLogRecordHeader: Entered\n", 0 ); 00295 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00296 DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn.HighPart ); 00297 DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn.LowPart ); 00298 DebugTrace( 0, Dbg, "PinData -> %04x\n", PinData ); 00299 DebugTrace( 0, Dbg, "IgnoreUsaErrors -> %04x\n", IgnoreUsaErrors ); 00300 00301 // 00302 // Compute the log page and the offset of the log record header 00303 // in the log page. 00304 // 00305 00306 LfsTruncateLsnToLogPage( Lfcb, Lsn, &LogPage ); 00307 PageOffset = LfsLsnToPageOffset( Lfcb, Lsn ); 00308 00309 // 00310 // Call the cache manager to pin the page. 00311 // 00312 00313 LfsPinOrMapData( Lfcb, 00314 LogPage, 00315 (ULONG)Lfcb->LogPageSize, 00316 PinData, 00317 FALSE, 00318 IgnoreUsaErrors, 00319 UsaError, 00320 (PVOID *) &LogPageHeader, 00321 Bcb ); 00322 00323 // 00324 // The actual offset we need is at PageOffset from the start of the page. 00325 // 00326 00327 *RecordHeader = Add2Ptr( LogPageHeader, PageOffset, PLFS_RECORD_HEADER ); 00328 00329 DebugTrace( 0, Dbg, "Record Header -> %08lx\n", *RecordHeader ); 00330 DebugTrace( 0, Dbg, "Bcb -> %08lx\n", *Bcb ); 00331 00332 DebugTrace( -1, Dbg, "LfsPinOrMapLogRecordHeader: Exit\n", 0 ); 00333 00334 return; 00335 }

BOOLEAN LfsReadRestart IN PLFCB  Lfcb,
IN LONGLONG  FileSize,
IN BOOLEAN  FirstRestart,
OUT PLONGLONG  RestartPageOffset,
OUT PLFS_RESTART_PAGE_HEADER RestartPage,
OUT PBCB RestartPageBcb,
OUT PBOOLEAN  ChkdskWasRun,
OUT PBOOLEAN  ValidPage,
OUT PBOOLEAN  UninitializedFile,
OUT PBOOLEAN  LogPacked,
OUT PLSN  LastLsn
 

Definition at line 1402 of file lfs/cachesup.c.

References Add2Ptr, CcUnpinData(), _LFS_RESTART_AREA::ClientInUseList, _LFS_RESTART_AREA::CurrentLsn, Dbg, DebugTrace, DebugUnwind, FALSE, LFS_NO_CLIENT, LFS_SIGNATURE_MODIFIED_ULONG, LFS_SIGNATURE_RECORD_PAGE_ULONG, LFS_SIGNATURE_RESTART_PAGE_ULONG, LFS_SIGNATURE_UNINITIALIZED_ULONG, LfsIsClientAreaValid(), LfsIsRestartAreaValid(), LfsIsRestartPageHeaderValid(), LfsPinOrMapData(), LfsReadRestart(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PLSN, SEQUENCE_NUMBER_STRIDE, Status, and TRUE.

Referenced by LfsReadRestart(), and LfsRestartLogFile().

01418 : 01419 01420 This routine will walk through 512 blocks of the file looking for a 01421 valid restart page header. It will stop the first time we find 01422 a valid page header. 01423 01424 Arguments: 01425 01426 Lfcb - This is the Lfcb for the log file. 01427 01428 FileSize - Size in bytes for the log file. 01429 01430 FirstRestart - Indicates if we are looking for the first valid 01431 restart area. 01432 01433 RestartPageOffset - This is the location to store the offset in the 01434 file where the log page was found. 01435 01436 RestartPage - This is the location to store the address of the 01437 pinned restart page. 01438 01439 RestartPageBcb - This is the location to store the Bcb for this 01440 cache pin operation. 01441 01442 ChkdskWasRun - Address to store whether checkdisk was run on this volume. 01443 01444 ValidPage - Address to store whether there was valid data on this page. 01445 01446 UninitializedFile - Address to store whether this is an uninitialized 01447 log file. Return value only valid if for the first restart area. 01448 01449 LogPacked - Address to store whether the log file is packed. 01450 01451 LastLsn - Address to store the last Lsn for this restart page. It will be the 01452 chkdsk value if checkdisk was run. Otherwise it is the LastFlushedLsn 01453 for this restart page. 01454 01455 Return Value: 01456 01457 BOOLEAN - TRUE if a restart area was found, FALSE otherwise. 01458 01459 --*/ 01460 01461 { 01462 ULONG FileOffsetIncrement; 01463 LONGLONG FileOffset; 01464 01465 PLFS_RESTART_AREA RestartArea; 01466 01467 NTSTATUS Status; 01468 01469 PLFS_RESTART_PAGE_HEADER ThisPage; 01470 PBCB ThisPageBcb = NULL; 01471 01472 BOOLEAN FoundRestart = FALSE; 01473 01474 PAGED_CODE(); 01475 01476 DebugTrace( +1, Dbg, "LfsReadRestart: Entered\n", 0 ); 01477 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 01478 01479 // 01480 // Use a try-finally to facilitate cleanup. 01481 // 01482 01483 *UninitializedFile = TRUE; 01484 *ValidPage = FALSE; 01485 *ChkdskWasRun = FALSE; 01486 *LogPacked = FALSE; 01487 01488 try { 01489 01490 // 01491 // Determine which restart area we are looking for. 01492 // 01493 01494 if (FirstRestart) { 01495 01496 FileOffset = 0; 01497 FileOffsetIncrement = SEQUENCE_NUMBER_STRIDE; 01498 01499 } else { 01500 01501 FileOffset = SEQUENCE_NUMBER_STRIDE; 01502 FileOffsetIncrement = 0; 01503 } 01504 01505 // 01506 // We loop continuously until we succeed, pin a log record page 01507 // or exhaust the number of possible tries. 01508 // 01509 01510 while ( FileOffset < FileSize ) { 01511 01512 ULONG Signature; 01513 BOOLEAN UsaError; 01514 01515 if (ThisPageBcb != NULL) { 01516 01517 CcUnpinData( ThisPageBcb ); 01518 ThisPageBcb = NULL; 01519 } 01520 01521 // 01522 // Attempt to pin a page header at the current offset. 01523 // 01524 01525 Status = LfsPinOrMapData( Lfcb, 01526 FileOffset, 01527 SEQUENCE_NUMBER_STRIDE, 01528 TRUE, 01529 TRUE, 01530 TRUE, 01531 &UsaError, 01532 (PVOID *)&ThisPage, 01533 &ThisPageBcb ); 01534 01535 // 01536 // 01537 // If we succeeded, we look at the 4 byte signature. 01538 // 01539 01540 if (NT_SUCCESS( Status )) { 01541 01542 Signature = *((PULONG) &ThisPage->MultiSectorHeader.Signature); 01543 01544 // 01545 // If the signature is a log record page, we will exit. 01546 // 01547 01548 if (Signature == LFS_SIGNATURE_RECORD_PAGE_ULONG) { 01549 01550 *UninitializedFile = FALSE; 01551 break; 01552 } 01553 01554 // 01555 // Continue analyzing the page if the signature is chkdsk or 01556 // a restart page. 01557 // 01558 01559 if (Signature == LFS_SIGNATURE_MODIFIED_ULONG 01560 || Signature == LFS_SIGNATURE_RESTART_PAGE_ULONG) { 01561 01562 *UninitializedFile = FALSE; 01563 01564 // 01565 // Remember where we found this page. 01566 // 01567 01568 *RestartPageOffset = FileOffset; 01569 01570 // 01571 // Let's check the restart area if this is a valid page. 01572 // 01573 01574 if (LfsIsRestartPageHeaderValid( FileOffset, 01575 ThisPage, 01576 LogPacked ) 01577 01578 && LfsIsRestartAreaValid( ThisPage, *LogPacked )) { 01579 01580 // 01581 // We have a valid restart page header and restart area. 01582 // If chkdsk was run or we have no clients then 01583 // we have no more checking to do. 01584 // 01585 01586 RestartArea = Add2Ptr( ThisPage, 01587 ThisPage->RestartOffset, 01588 PLFS_RESTART_AREA ); 01589 01590 if (Signature == LFS_SIGNATURE_RESTART_PAGE_ULONG 01591 && RestartArea->ClientInUseList != LFS_NO_CLIENT) { 01592 01593 // 01594 // Pin the entire restart area if we didn't have an earlier 01595 // 01596 01597 CcUnpinData( ThisPageBcb ); 01598 ThisPageBcb = NULL; 01599 01600 Status = LfsPinOrMapData( Lfcb, 01601 FileOffset, 01602 ThisPage->SystemPageSize, 01603 TRUE, 01604 TRUE, 01605 TRUE, 01606 &UsaError, 01607 (PVOID *)&ThisPage, 01608 &ThisPageBcb ); 01609 01610 if (NT_SUCCESS( Status ) 01611 && LfsIsClientAreaValid( ThisPage, *LogPacked, UsaError )) { 01612 01613 *ValidPage = TRUE; 01614 01615 RestartArea = Add2Ptr( ThisPage, 01616 ThisPage->RestartOffset, 01617 PLFS_RESTART_AREA ); 01618 } 01619 01620 } else { 01621 01622 *ValidPage = TRUE; 01623 } 01624 } 01625 01626 // 01627 // If chkdsk was run then update the caller's values and return. 01628 // 01629 01630 if (Signature == LFS_SIGNATURE_MODIFIED_ULONG) { 01631 01632 *ChkdskWasRun = TRUE; 01633 01634 *LastLsn = ThisPage->ChkDskLsn; 01635 01636 FoundRestart = TRUE; 01637 01638 *RestartPageBcb = ThisPageBcb; 01639 *RestartPage = ThisPage; 01640 01641 ThisPageBcb = NULL; 01642 break; 01643 } 01644 01645 // 01646 // If we have a valid page then copy the values we need from it. 01647 // 01648 01649 if (*ValidPage) { 01650 01651 *LastLsn = RestartArea->CurrentLsn; 01652 01653 FoundRestart = TRUE; 01654 01655 *RestartPageBcb = ThisPageBcb; 01656 *RestartPage = ThisPage; 01657 01658 ThisPageBcb = NULL; 01659 break; 01660 } 01661 01662 // 01663 // Remember if the signature does not indicate uninitialized file. 01664 // 01665 01666 } else if (Signature != LFS_SIGNATURE_UNINITIALIZED_ULONG) { 01667 01668 *UninitializedFile = FALSE; 01669 } 01670 } 01671 01672 // 01673 // Move to the next possible log page. 01674 // 01675 01676 FileOffset = FileOffset << 1; 01677 01678 (ULONG)FileOffset += FileOffsetIncrement; 01679 01680 FileOffsetIncrement = 0; 01681 } 01682 01683 } finally { 01684 01685 DebugUnwind( LfsReadRestart ); 01686 01687 // 01688 // Unpin the log pages if pinned. 01689 // 01690 01691 if (ThisPageBcb != NULL) { 01692 01693 CcUnpinData( ThisPageBcb ); 01694 } 01695 01696 DebugTrace( 0, Dbg, "RestartPageAddress (Low) -> %08lx\n", RestartPageAddress->LowPart ); 01697 DebugTrace( 0, Dbg, "RestartPageAddress (High) -> %08lx\n", RestartPageAddress->HighPart ); 01698 DebugTrace( 0, Dbg, "FirstRestartPage -> %08lx\n", *FirstRestartPage ); 01699 DebugTrace( -1, Dbg, "LfsReadRestart: Exit\n", 0 ); 01700 } 01701 01702 return FoundRestart; 01703 }

BOOLEAN LfsVerifyLogSpaceAvail IN PLFCB  Lfcb,
IN PLCH  Lch,
IN ULONG  RemainingLogBytes,
IN LONG  UndoRequirement,
IN BOOLEAN  ForceToDisk
 

Definition at line 114 of file lfs/verfysup.c.

References Dbg, DebugTrace, ExRaiseStatus(), FALSE, FlagOn, LFCB_PACK_LOG, LfsCurrentAvailSpace(), PAGED_CODE, and TRUE.

Referenced by LfsWriteLogRecordIntoLogPage().

00124 : 00125 00126 This routine is called to verify that we may write this log record into the 00127 log file. We want to always leave room for each transaction to abort. 00128 00129 We determine how much space the current log record will take and the 00130 worst case for its undo operation. If this space is available we 00131 update the corresponding values in the Lfcb and Lch for bookkeeping. 00132 Otherwise we raise a status indicating that the log file is full. 00133 00134 The disk usage is different for the packed and unpacked cases. Make the 00135 following adjustments after finding the total available and amount still 00136 remaining on the last active page, 00137 00138 Packed Case: 00139 00140 Size needed for log record is data size plus header size. 00141 00142 Undo requirement is the undo data size plus the header size. 00143 We have already taken into account the end of the pages 00144 except for the current page. 00145 00146 Add the log record size to the undo requirement to get the 00147 log file usage. Compare this number with the actual available 00148 space (Available - CommittedUndo). If the space is not 00149 available, then raise LOG_FILE_FULL. Must take into account 00150 any unused bytes at the end of the current page. 00151 00152 Unpacked Case: 00153 00154 Size needed is initially header size plus data size. 00155 00156 If the log record can't begin on the current page then 00157 add the bytes being thrown away to the log record size. 00158 00159 If the page is being forced to disk then add any remaining 00160 bytes on the last page. To the bytes being used. 00161 00162 Undo requirement is twice the sum of the header size and 00163 undo size. We double the requested size since the log 00164 record will always fit on a page. This can be a 00165 positive or negative number. 00166 00167 Add the log record usage to the undo usage to get the log file 00168 usage. Compare this number with the actual available 00169 space (Available - CommittedUndo). If the space is not 00170 available, then raise LOG_FILE_FULL. 00171 00172 Arguments: 00173 00174 Lfcb - Lfcb for this log file. 00175 00176 Lch - Client handle 00177 00178 RemainingLogBytes - Number of bytes for the current log record 00179 00180 UndoRequirement - User's requirement for the undo record. 00181 00182 ForceToDisk - Indicates if this log record will be flushed to disk. 00183 00184 Return Value: 00185 00186 BOOLEAN - Advisory, indicates that there is less than 1/4 of the log file available. 00187 00188 --*/ 00189 00190 { 00191 ULONG CurrentLogRecordSize; 00192 ULONG LogRecordStart; 00193 ULONG TailBytes; 00194 00195 LONGLONG CurrentAvailSpace; 00196 ULONG CurrentPageBytes; 00197 00198 LONGLONG LogFileUsage; 00199 00200 PAGED_CODE(); 00201 00202 DebugTrace( +1, Dbg, "LfsVerifyLogSpaceAvail: Entered\n", 0 ); 00203 DebugTrace( 0, Dbg, "Lfcb -> %08x\n", Lfcb ); 00204 DebugTrace( 0, Dbg, "Lch -> %08lx\n", Lch ); 00205 DebugTrace( 0, Dbg, "RemainingLogBytes -> %08lx\n", RemainingLogBytes ); 00206 DebugTrace( 0, Dbg, "UndoRequirement -> %08lx\n", UndoRequirement ); 00207 DebugTrace( 0, Dbg, "ForceToDisk -> %04x\n", ForceToDisk ); 00208 00209 // 00210 // Start by collecting the current data on the file. 00211 // 00212 00213 LfsCurrentAvailSpace( Lfcb, 00214 &CurrentAvailSpace, 00215 &CurrentPageBytes ); 00216 00217 // 00218 // We compute the amount of space needed for the current log record by 00219 // adding up the following: 00220 // 00221 // Space at end of current log page which won't be used. 00222 // Size of header for log record. 00223 // Size of client data in log record. 00224 // Size of wasted portion of log page if this is forced to disk. 00225 // 00226 00227 // 00228 // Start with the size of the header and the client data. 00229 // 00230 00231 CurrentLogRecordSize = RemainingLogBytes + Lfcb->RecordHeaderLength; 00232 00233 // 00234 // If the log is packed and there are bytes on the current page we need 00235 // to take into account any bytes at the end of the page which won't 00236 // be used. This will happen if the log record spills into the end of 00237 // the log page but doesn't use up the page. If the remaining bytes are 00238 // less than a record header size we must throw them away. 00239 // 00240 00241 if (FlagOn( Lfcb->Flags, LFCB_PACK_LOG )) { 00242 00243 if (CurrentPageBytes != 0 00244 && CurrentLogRecordSize < CurrentPageBytes 00245 && (CurrentPageBytes - CurrentLogRecordSize) < Lfcb->RecordHeaderLength) { 00246 00247 CurrentLogRecordSize += (CurrentPageBytes - CurrentLogRecordSize); 00248 } 00249 00250 // 00251 // If this is the unpacked case we need to check for bytes being thrown away 00252 // on the current page or the last page. 00253 // 00254 00255 } else { 00256 00257 // 00258 // If there is an active Lbcb, we need to add any bytes that 00259 // would be thrown away at the end. 00260 // 00261 00262 if (CurrentPageBytes != 0) { 00263 00264 // 00265 // We won't use this log page unless the new log record will fit or 00266 // unless this is the first log record in the page. 00267 // 00268 00269 if ((CurrentPageBytes != (ULONG)Lfcb->LogPageDataSize) 00270 && (CurrentLogRecordSize > CurrentPageBytes)) { 00271 00272 CurrentLogRecordSize += CurrentPageBytes; 00273 00274 // 00275 // Remember that we will start this log record at the first 00276 // byte in the data portion of a page. 00277 // 00278 00279 LogRecordStart = 0; 00280 00281 // 00282 // Otherwise this will start at the current offset into the 00283 // data portion of the log page. 00284 // 00285 00286 } else { 00287 00288 LogRecordStart = (ULONG)Lfcb->LogPageDataSize - CurrentPageBytes; 00289 } 00290 00291 // 00292 // If there was no Lbcb, then we know that we will start at the first 00293 // byte of the data portion. 00294 // 00295 00296 } else { 00297 00298 LogRecordStart = 0; 00299 } 00300 00301 // 00302 // We always assume that we will use up the rest of the bytes on the last page 00303 // in computing whether the log record will fit in the available space. We 00304 // only subtract that space from the available space if this is a force write. 00305 // 00306 00307 if (ForceToDisk) { 00308 00309 // 00310 // We take into account where we start on a log page and continue 00311 // to subtract log pages until we know the amount on the last 00312 // page. 00313 // 00314 00315 TailBytes = RemainingLogBytes + Lfcb->RecordHeaderLength + LogRecordStart; 00316 00317 while (TailBytes > (ULONG)Lfcb->LogPageDataSize) { 00318 00319 TailBytes -= (ULONG)Lfcb->LogPageDataSize; 00320 } 00321 00322 TailBytes = (ULONG)Lfcb->LogPageDataSize - TailBytes; 00323 00324 CurrentLogRecordSize += TailBytes; 00325 } 00326 } 00327 00328 // 00329 // We now know the number of bytes needed for the current log page. 00330 // Next we compute the number of bytes being reserved by UndoRequirement. 00331 // If the UndoRequirement is positive, we will add to the amount reserved 00332 // in the log file. If it is negative, we will subtract from the amount 00333 // reserved in the log file. 00334 // 00335 00336 // 00337 // When we have an actual reserve amount, we convert it to positive 00338 // and then reserve twice the space required to hold the data and 00339 // its header (up to the maximum of a single page. 00340 // 00341 00342 if (UndoRequirement != 0) { 00343 00344 if (!FlagOn( Lfcb->Flags, LFCB_PACK_LOG )) { 00345 00346 UndoRequirement *= 2; 00347 } 00348 00349 if (UndoRequirement < 0) { 00350 00351 UndoRequirement -= (2 * Lfcb->RecordHeaderLength); 00352 } else { 00353 00354 UndoRequirement += (2 * Lfcb->RecordHeaderLength); 00355 } 00356 } 00357 00358 // 00359 // Now compute the net log file usage. The result may be positive or 00360 // negative. 00361 // 00362 00363 LogFileUsage = ((LONG) CurrentLogRecordSize) + UndoRequirement; //**** xxFromLong( ((LONG) CurrentLogRecordSize) + UndoRequirement ); 00364 00365 // 00366 // The actual available space is the CurrentAvail minus the reserved 00367 // undo value in the Lfcb. 00368 // 00369 00370 CurrentAvailSpace = CurrentAvailSpace - Lfcb->TotalUndoCommitment; //**** xxSub( CurrentAvailSpace, Lfcb->TotalUndoCommitment ); 00371 00372 // 00373 // If this log file usage is greater than the available log file space 00374 // then we raise a status code. 00375 // 00376 00377 #ifdef LFS_RAISE 00378 if (LfsRaiseFull) { 00379 00380 LfsRaiseFull = FALSE; 00381 DebugTrace( -1, Dbg, "LfsVerifyLogSpaceAvail: About to raise\n", 0 ); 00382 ExRaiseStatus( STATUS_LOG_FILE_FULL ); 00383 } 00384 #endif 00385 00386 if (LogFileUsage > CurrentAvailSpace) { 00387 00388 DebugTrace( -1, Dbg, "LfsVerifyLogSpaceAvail: About to raise\n", 0 ); 00389 ExRaiseStatus( STATUS_LOG_FILE_FULL ); 00390 } 00391 00392 Lfcb->TotalUndoCommitment = Lfcb->TotalUndoCommitment + UndoRequirement; //**** xxAdd( Lfcb->TotalUndoCommitment, xxFromLong( UndoRequirement )); 00393 00394 Lch->ClientUndoCommitment = Lch->ClientUndoCommitment + UndoRequirement; //**** xxAdd( Lch->ClientUndoCommitment, xxFromLong( UndoRequirement )); 00395 00396 DebugTrace( -1, Dbg, "LfsVerifyLogSpaceAvail: Exit\n", 0 ); 00397 00398 // 00399 // Now check if the log file is almost used up. 00400 // 00401 00402 if ((CurrentAvailSpace - LogFileUsage) < (Lfcb->TotalAvailable >> 2)) { 00403 00404 return TRUE; 00405 } 00406 00407 return FALSE; 00408 }

VOID LfsWriteLfsRestart IN PLFCB  Lfcb,
IN ULONG  ThisRestartSize,
IN BOOLEAN  WaitForIo
 

Definition at line 36 of file rstrtsup.c.

References _LBCB::ActiveLinks, Add2Ptr, ClearFlag, _LFS_RESTART_AREA::ClientArrayOffset, Dbg, DebugTrace, DebugUnwind, ExFreePool(), _LBCB::FileOffset, FlagOn, _LBCB::LastEndLsn, _LBCB::LastLsn, LBCB_NOT_EMPTY, LBCB_ON_ACTIVE_QUEUE, LBCB_RESTART_LBCB, _LBCB::LbcbFlags, _LBCB::Length, LFCB_PACK_LOG, LfsAllocateLbcb(), LfsAllocateRestartArea, LfsFlushLbcb(), LfsWriteLfsRestart(), NULL, PAGED_CODE, _LBCB::PageHeader, SetFlag, and _LBCB::WorkqueLinks.

Referenced by LfsCloseLogFile(), LfsInitializeLogFilePriv(), LfsSetBaseLsn(), LfsWriteLfsRestart(), and LfsWriteRestartArea().

00044 : 00045 00046 This routine puts the Lfs restart area on the queue of operations to 00047 write to the file. We do this by allocating a second restart area 00048 and attaching it to the Lfcb. We also allocate a buffer control 00049 block to use for this write. We look at the WaitForIo boolean to 00050 determine whether this thread can perform the I/O. This also indicates 00051 whether this thread gives up the Lfcb. 00052 00053 Arguments: 00054 00055 Lfcb - A pointer to the log file control block for this operation. 00056 00057 ThisRestartSize - This is the size to use for the restart area. 00058 00059 WaitForIo - Indicates if this thread is to perform the work. 00060 00061 Return Value: 00062 00063 None. 00064 00065 --*/ 00066 00067 { 00068 PLBCB NewLbcb = NULL; 00069 PLFS_RESTART_AREA NewRestart = NULL; 00070 00071 PAGED_CODE(); 00072 00073 DebugTrace( +1, Dbg, "LfsWriteLfsRestart: Entered\n", 0 ); 00074 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00075 DebugTrace( 0, Dbg, "Write Chkdsk -> %04x\n", WriteChkdsk ); 00076 DebugTrace( 0, Dbg, "Restart Size -> %08lx\n", ThisRestartSize ); 00077 DebugTrace( 0, Dbg, "WaitForIo -> %08lx\n", WaitForIo ); 00078 00079 // 00080 // Use a try-finally to facilitate cleanup. 00081 // 00082 00083 try { 00084 00085 PLBCB ActiveLbcb; 00086 00087 // 00088 // We allocate another restart area and 00089 // copy the current area into it. Attach the new area to the Lfcb. 00090 // 00091 00092 LfsAllocateRestartArea( &NewRestart, ThisRestartSize ); 00093 00094 // 00095 // We allocate a Lbcb structure and update the values to 00096 // reflect this restart area. 00097 // 00098 00099 LfsAllocateLbcb( Lfcb, &NewLbcb ); 00100 SetFlag( NewLbcb->LbcbFlags, LBCB_RESTART_LBCB ); 00101 00102 // 00103 // If this is the second page, then add a system page to the offset. 00104 // 00105 00106 if (!Lfcb->InitialRestartArea) { 00107 00108 NewLbcb->FileOffset = Lfcb->SystemPageSize + NewLbcb->FileOffset; 00109 } 00110 00111 (ULONG)NewLbcb->Length = ThisRestartSize; 00112 00113 NewLbcb->PageHeader = (PVOID) Lfcb->RestartArea; 00114 00115 // 00116 // Lets put the current lsn in the Lbcb. 00117 // 00118 00119 NewLbcb->LastEndLsn = NewLbcb->LastLsn = Lfcb->NextRestartLsn; 00120 Lfcb->NextRestartLsn.QuadPart = 1 + Lfcb->NextRestartLsn.QuadPart; 00121 00122 // 00123 // Copy the existing restart area into the new area. 00124 // 00125 00126 RtlCopyMemory( NewRestart, Lfcb->RestartArea, ThisRestartSize ); 00127 Lfcb->RestartArea = NewRestart; 00128 00129 Lfcb->ClientArray = Add2Ptr( NewRestart, Lfcb->ClientArrayOffset, PLFS_CLIENT_RECORD ); 00130 00131 NewRestart = NULL; 00132 00133 // 00134 // Update the Lfcb to indicate that the other restart area 00135 // on the disk is to be used. 00136 // 00137 00138 Lfcb->InitialRestartArea = !Lfcb->InitialRestartArea; 00139 00140 // 00141 // Add this Lbcb to the end of the workque and flush to that point. 00142 // 00143 00144 InsertTailList( &Lfcb->LbcbWorkque, &NewLbcb->WorkqueLinks ); 00145 00146 // 00147 // If we don't support a packed log file then we need to make 00148 // sure that all file records written out ahead of this 00149 // restart area make it out to disk and we don't add anything 00150 // to this page. 00151 // 00152 00153 if (!FlagOn( Lfcb->Flags, LFCB_PACK_LOG ) 00154 && !IsListEmpty( &Lfcb->LbcbActive )) { 00155 00156 ActiveLbcb = CONTAINING_RECORD( Lfcb->LbcbActive.Flink, 00157 LBCB, 00158 ActiveLinks ); 00159 00160 if (FlagOn( ActiveLbcb->LbcbFlags, LBCB_NOT_EMPTY )) { 00161 00162 RemoveEntryList( &ActiveLbcb->ActiveLinks ); 00163 ClearFlag( ActiveLbcb->LbcbFlags, LBCB_ON_ACTIVE_QUEUE ); 00164 } 00165 } 00166 00167 if (WaitForIo) { 00168 00169 LfsFlushLbcb( Lfcb, NewLbcb ); 00170 } 00171 00172 } finally { 00173 00174 DebugUnwind( LfsWriteLfsRestart ); 00175 00176 if (NewRestart != NULL) { 00177 00178 ExFreePool( NewRestart ); 00179 } 00180 00181 DebugTrace( -1, Dbg, "LfsWriteLfsRestart: Exit\n", 0 ); 00182 } 00183 00184 return; 00185 }

BOOLEAN LfsWriteLogRecordIntoLogPage IN PLFCB  Lfcb,
IN PLCH  Lch,
IN ULONG  NumberOfWriteEntries,
IN PLFS_WRITE_ENTRY  WriteEntries,
IN LFS_RECORD_TYPE  RecordType,
IN TRANSACTION_ID *TransactionId  OPTIONAL,
IN LSN ClientUndoNextLsn  OPTIONAL,
IN LSN ClientPreviousLsn  OPTIONAL,
IN LONG  UndoRequirement,
IN BOOLEAN  ForceToDisk,
OUT PLSN  Lsn
 

Definition at line 55 of file logrcsup.c.

References Add2Ptr, _LFS_WRITE_ENTRY::Buffer, _LBCB::BufferOffset, _LFS_WRITE_ENTRY::ByteLength, ClearFlag, _LFS_RECORD_HEADER::ClientDataLength, _LFS_RECORD_HEADER::ClientId, _LFS_RECORD_HEADER::ClientPreviousLsn, _LFS_RECORD_HEADER::ClientUndoNextLsn, _LFS_RECORD_PAGE_HEADER::Copy, Dbg, DebugTrace, Executive, FALSE, FlagOn, _LFS_RECORD_HEADER::Flags, _LBCB::Flags, _LFS_RECORD_PAGE_HEADER::Flags, _LFS_RECORD_PAGE_HEADER::Header, KernelMode, KeWaitForSingleObject(), _LBCB::LastEndLsn, _LBCB::LastLsn, LBCB_NOT_EMPTY, LBCB_ON_ACTIVE_QUEUE, _LBCB::LbcbFlags, LFCB_NO_LAST_LSN, LFCB_PACK_LOG, LfsAcquireLfcb, LfsComputeLsnFromLbcb, LfsPrepareLfcbForLogRecord(), LfsReleaseLfcb, LfsTransferLogBytes(), LfsVerifyLogSpaceAvail(), LOG_PAGE_LOG_RECORD_END, LOG_RECORD_MULTI_PAGE, _LBCB::LogPageBcb, LSN, NULL, PAGED_CODE, _LBCB::PageHeader, QuadAlign, _LFS_RECORD_HEADER::RecordType, SetFlag, _LFS_RECORD_HEADER::ThisLsn, _LFS_RECORD_HEADER::TransactionId, TRUE, USHORT, and _LBCB::WorkqueLinks.

Referenced by LfsForceWrite(), LfsWrite(), and LfsWriteRestartArea().

00071 : 00072 00073 This routine is called to write a log record into the log file 00074 using the cache manager. If there is room in the current log 00075 page it is added to that. Otherwise we allocate a new log page 00076 and write the log record header for this log page. We then 00077 write the log record into the remaining bytes of this page and 00078 into any subsequent pages if needed. 00079 00080 Arguments: 00081 00082 Lfcb - File control block for this log file. 00083 00084 Lch - This is the client handle, we may update the undo space for this 00085 client. 00086 00087 NumberOfWriteEntries - Number of components of the log record. 00088 00089 WriteEntries - Pointer to an array of write entries. 00090 00091 UndoRequirement - Signed value indicating the requirement to write 00092 an abort log record for this log record. A negative 00093 value indicates that this is the abort record. 00094 00095 RecordType - The Lfs-defined type of this log record. 00096 00097 TransactionId - Pointer to the transaction structure containing the 00098 Id for transaction containing this operation. 00099 00100 ClientUndoNextLsn - This is the Lsn provided by the client for use 00101 in his restart. Will be the zero Lsn for 00102 a restart log record. 00103 00104 ClientPreviousLsn - This is the Lsn provided by the client for use 00105 in his restart. Will the the zero Lsn for a 00106 restart log record. 00107 00108 UndoRequirement - This is the data size for the undo record for 00109 this log record. 00110 00111 ForceToDisk - Indicates if this log record will be flushed immediately 00112 to disk. 00113 00114 Lsn - A pointer to store the Lsn for this log record. 00115 00116 Return Value: 00117 00118 BOOLEAN - Advisory, TRUE indicates that less than 1/4 of the log file is 00119 available. 00120 00121 --*/ 00122 00123 { 00124 PLFS_WRITE_ENTRY ThisWriteEntry; 00125 00126 ULONG RemainingLogBytes; 00127 ULONG OriginalLogBytes; 00128 00129 ULONG RemainingPageBytes; 00130 ULONG HeaderAdjust; 00131 00132 PLBCB ThisLbcb; 00133 00134 LSN NextLsn; 00135 00136 PLFS_RECORD_HEADER RecordHeader; 00137 00138 PCHAR CurrentBuffer; 00139 ULONG CurrentByteCount; 00140 ULONG PadBytes; 00141 00142 BOOLEAN LogFileFull = FALSE; 00143 00144 PAGED_CODE(); 00145 00146 DebugTrace( +1, Dbg, "LfsWriteLogRecordIntoLogPage: Entered\n", 0 ); 00147 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00148 DebugTrace( 0, Dbg, "Lch -> %08lx\n", Lch ); 00149 DebugTrace( 0, Dbg, "Number of Write Entries -> %08lx\n", NumberOfWriteEntries ); 00150 DebugTrace( 0, Dbg, "Write Entries -> %08lx\n", WriteEntries ); 00151 DebugTrace( 0, Dbg, "Record Type -> %08lx\n", RecordType ); 00152 DebugTrace( 0, Dbg, "Transaction Id -> %08lx\n", TransactionId ); 00153 DebugTrace( 0, Dbg, "ClientUndoNextLsn (Low) -> %08lx\n", ClientUndoNextLsn.LowPart ); 00154 DebugTrace( 0, Dbg, "ClientUndoNextLsn (High) -> %08lx\n", ClientUndoNextLsn.HighPart ); 00155 DebugTrace( 0, Dbg, "ClientPreviousLsn (Low) -> %08lx\n", ClientPreviousLsn.LowPart ); 00156 DebugTrace( 0, Dbg, "ClientPreviousLsn (High) -> %08lx\n", ClientPreviousLsn.HighPart ); 00157 DebugTrace( 0, Dbg, "UndoRequirement -> %08lx\n", UndoRequirement ); 00158 DebugTrace( 0, Dbg, "ForceToDisk -> %04x\n", ForceToDisk ); 00159 00160 // 00161 // We compute the size of this log record. 00162 // 00163 00164 ThisWriteEntry = WriteEntries; 00165 00166 RemainingLogBytes = 0; 00167 00168 while (NumberOfWriteEntries--) { 00169 00170 RemainingLogBytes += QuadAlign( ThisWriteEntry->ByteLength ); 00171 00172 ThisWriteEntry++; 00173 } 00174 00175 OriginalLogBytes = RemainingLogBytes; 00176 00177 ThisWriteEntry = WriteEntries; 00178 00179 // 00180 // Loop until we have the Lbcb and we know it is not part of 00181 // a partial page transfer. We need to make sure we have 00182 // a Bcb for this page. 00183 // 00184 00185 while (TRUE) { 00186 00187 LogFileFull = LfsVerifyLogSpaceAvail( Lfcb, 00188 Lch, 00189 RemainingLogBytes, 00190 UndoRequirement, 00191 ForceToDisk ); 00192 00193 // 00194 // We update the Lfcb so that we can start putting the log record into 00195 // the top of the Lbcb active list. 00196 // 00197 00198 LfsPrepareLfcbForLogRecord( Lfcb, 00199 RemainingLogBytes + Lfcb->RecordHeaderLength ); 00200 00201 ThisLbcb = CONTAINING_RECORD( Lfcb->LbcbActive.Flink, 00202 LBCB, 00203 ActiveLinks ); 00204 00205 // 00206 // If there is a Bcb then we are golden. 00207 // 00208 00209 if (ThisLbcb->LogPageBcb != NULL) { break; } 00210 00211 // 00212 // Otherwise we want to drop the Lfcb and wait for the IO to complete. 00213 // 00214 00215 Lfcb->Waiters += 1; 00216 00217 LfsReleaseLfcb( Lfcb ); 00218 00219 KeWaitForSingleObject( &Lfcb->Sync->Event, 00220 Executive, 00221 KernelMode, 00222 FALSE, 00223 NULL ); 00224 00225 LfsAcquireLfcb( Lfcb ); 00226 Lfcb->Waiters -= 1; 00227 } 00228 00229 RemainingPageBytes = (ULONG)Lfcb->LogPageSize - (ULONG)ThisLbcb->BufferOffset; 00230 00231 // 00232 // Compute the Lsn starting in the next log buffer. 00233 // 00234 00235 NextLsn.QuadPart = LfsComputeLsnFromLbcb( Lfcb, ThisLbcb ); 00236 00237 // 00238 // We get a pointer to the log record header and the start of the 00239 // log record in the pinned buffer. 00240 // 00241 00242 RecordHeader = Add2Ptr( ThisLbcb->PageHeader, 00243 (ULONG)ThisLbcb->BufferOffset, 00244 PLFS_RECORD_HEADER ); 00245 00246 // 00247 // We update the record header. 00248 // 00249 00250 // 00251 // Zero out the structure initially. 00252 // 00253 00254 RtlZeroMemory( RecordHeader, Lfcb->RecordHeaderLength ); 00255 00256 // 00257 // Update all the fields. 00258 // 00259 00260 RecordHeader->ThisLsn = NextLsn; 00261 RecordHeader->ClientPreviousLsn = ClientPreviousLsn; 00262 RecordHeader->ClientUndoNextLsn = ClientUndoNextLsn; 00263 00264 if (TransactionId != NULL) { 00265 RecordHeader->TransactionId = *TransactionId; 00266 } 00267 00268 RecordHeader->ClientDataLength = RemainingLogBytes; 00269 RecordHeader->ClientId = Lch->ClientId; 00270 RecordHeader->RecordType = RecordType; 00271 00272 // 00273 // Check if this is a multi-page record. 00274 // 00275 00276 if (RemainingLogBytes + Lfcb->RecordHeaderLength > RemainingPageBytes) { 00277 00278 SetFlag( RecordHeader->Flags, LOG_RECORD_MULTI_PAGE ); 00279 } 00280 00281 RemainingPageBytes -= Lfcb->RecordHeaderLength; 00282 00283 // 00284 // Update the buffer position in the Lbcb 00285 // 00286 00287 (ULONG)ThisLbcb->BufferOffset += Lfcb->RecordHeaderLength; 00288 HeaderAdjust = Lfcb->RecordHeaderLength; 00289 00290 // 00291 // Remember the values in the current write entry. 00292 // 00293 00294 CurrentBuffer = ThisWriteEntry->Buffer; 00295 CurrentByteCount = ThisWriteEntry->ByteLength; 00296 00297 PadBytes = (8 - (CurrentByteCount & ~(0xfffffff8))) & ~(0xfffffff8); 00298 00299 // 00300 // Continue to transfer bytes until all the client's data has 00301 // been transferred. 00302 // 00303 00304 while (RemainingLogBytes != 0) { 00305 00306 PLFS_RECORD_PAGE_HEADER PageHeader; 00307 00308 PageHeader = (PLFS_RECORD_PAGE_HEADER) ThisLbcb->PageHeader; 00309 00310 // 00311 // If the Lbcb is empty and we are about to store data into it we 00312 // subtract the data size of the page from the available space. 00313 // Update all the information we want to put in the header. 00314 // 00315 00316 if (!FlagOn( ThisLbcb->LbcbFlags, LBCB_NOT_EMPTY )) { 00317 00318 // 00319 // We subtract this page from the available pages only if 00320 // we are at the beginning of the page. Otherwise this 00321 // could be a reuse page. In that case it has already 00322 // been subtracted. 00323 // 00324 00325 if ((ULONG)ThisLbcb->BufferOffset - HeaderAdjust == (ULONG)Lfcb->LogPageDataOffset) { 00326 00327 00328 Lfcb->CurrentAvailable = Lfcb->CurrentAvailable - Lfcb->ReservedLogPageSize; //**** xxSub( Lfcb->CurrentAvailable, Lfcb->ReservedLogPageSize ); 00329 } 00330 00331 InsertTailList( &Lfcb->LbcbWorkque, &ThisLbcb->WorkqueLinks ); 00332 SetFlag( ThisLbcb->LbcbFlags, LBCB_NOT_EMPTY ); 00333 } 00334 00335 HeaderAdjust = 0; 00336 00337 // 00338 // Compute the number of transfer bytes. Update the remaining 00339 // page bytes, remaining log bytes and position in the write 00340 // buffer array. This routine also copies the bytes into the buffer. 00341 // 00342 00343 LfsTransferLogBytes( ThisLbcb, 00344 &ThisWriteEntry, 00345 &CurrentBuffer, 00346 &CurrentByteCount, 00347 &PadBytes, 00348 &RemainingPageBytes, 00349 &RemainingLogBytes ); 00350 00351 // 00352 // This log record ends on this page. Update the fields for the 00353 // ending Lsn. 00354 // 00355 00356 if (RemainingLogBytes == 0) { 00357 00358 SetFlag( ThisLbcb->Flags, LOG_PAGE_LOG_RECORD_END ); 00359 ThisLbcb->LastEndLsn = NextLsn; 00360 00361 if (FlagOn( Lfcb->Flags, LFCB_PACK_LOG )) { 00362 00363 PageHeader->Header.Packed.LastEndLsn = NextLsn; 00364 PageHeader->Header.Packed.NextRecordOffset = (USHORT)ThisLbcb->BufferOffset; 00365 } 00366 } 00367 00368 // 00369 // We are done with this page, update the fields in the page header. 00370 // 00371 00372 if (RemainingPageBytes == 0 00373 || RemainingLogBytes == 0) { 00374 00375 // 00376 // We are done with this page. Update the Lbcb and page header. 00377 // 00378 00379 ThisLbcb->LastLsn = NextLsn; 00380 PageHeader->Copy.LastLsn = NextLsn; 00381 PageHeader->Flags = ThisLbcb->Flags; 00382 00383 // 00384 // We can't put any more log records on this page. Remove 00385 // it from the active queue. 00386 // 00387 00388 if (RemainingPageBytes < Lfcb->RecordHeaderLength) { 00389 00390 RemoveHeadList( &Lfcb->LbcbActive ); 00391 ClearFlag( ThisLbcb->LbcbFlags, LBCB_ON_ACTIVE_QUEUE ); 00392 00393 // 00394 // If there are more log bytes then get the next Lbcb. 00395 // 00396 00397 if (RemainingLogBytes != 0) { 00398 00399 ThisLbcb = CONTAINING_RECORD( Lfcb->LbcbActive.Flink, 00400 LBCB, 00401 ActiveLinks ); 00402 00403 RemainingPageBytes = (ULONG)Lfcb->LogPageSize 00404 - (ULONG)ThisLbcb->BufferOffset; 00405 } 00406 } 00407 } 00408 } 00409 00410 *Lsn = NextLsn; 00411 00412 Lfcb->RestartArea->CurrentLsn = NextLsn; 00413 00414 Lfcb->RestartArea->LastLsnDataLength = OriginalLogBytes; 00415 00416 ClearFlag( Lfcb->Flags, LFCB_NO_LAST_LSN ); 00417 00418 DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn->LowPart ); 00419 DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn->HighPart ); 00420 DebugTrace( -1, Dbg, "LfsWriteLogRecordIntoLogPage: Exit\n", 0 ); 00421 00422 return LogFileFull; 00423 }


Generated on Sat May 15 19:44:32 2004 for test by doxygen 1.3.7