windows-nt/Source/XPSP1/NT/base/fs/lfs/lfsprocs.h

823 lines
19 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++ BUILD Version: 0000 // Increment this if a change has global effects
Copyright (c) 1989 Microsoft Corporation
Module Name:
LfsProcs.h
Abstract:
This module defines all of the globally used procedures in the Log
File Service.
Author:
Brian Andrew [BrianAn] 20-June-1991
Revision History:
--*/
#ifndef _LFSPROCS_
#define _LFSPROCS_
#include <ntifs.h>
#include <string.h>
#include <lfs.h>
#include "nodetype.h"
#include "LfsDisk.h"
#include "LfsStruc.h"
#include "LfsData.h"
//
// Tag all of our allocations if tagging is turned on
//
#undef FsRtlAllocatePool
#undef FsRtlAllocatePoolWithQuota
#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)
#ifndef INLINE
// definition of inline
#define INLINE __inline
#endif
//
// The following routines provide an interface with the cache package.
// They are contained in 'CacheSup.c'.
//
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
// LfsPreparePinWriteData (
// IN PLFCB Lfcb,
// IN LONGLONG FileOffset,
// IN ULONG Length,
// IN LOGICAL ReadFromDisk,
// OUT PVOID *Buffer,
// OUT PBCB *Bcb
// );
//
#ifdef LFS_CLUSTER_CHECK
#define LfsPreparePinWriteData(L,FO,LEN,R,BUF,B) { \
LONGLONG _LocalFileOffset = (FO); \
CcPinRead( (L)->FileObject, \
(PLARGE_INTEGER)&_LocalFileOffset, \
(LEN), \
TRUE, \
(B), \
(BUF) ); \
}
#else
#define LfsPreparePinWriteData(L,FO,LEN,R,BUF,B) { \
LONGLONG _LocalFileOffset = (FO); \
if (R) { \
CcPinRead( (L)->FileObject, \
(PLARGE_INTEGER)&_LocalFileOffset, \
(LEN), \
TRUE, \
(B), \
(BUF) ); \
} else { \
CcPreparePinWrite( (L)->FileObject, \
(PLARGE_INTEGER)&_LocalFileOffset, \
(LEN), \
FALSE, \
TRUE, \
(B), \
(BUF) ); \
} \
}
#endif
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
);
//
// The following routines manipulate buffer control blocks. They are
// contained in 'LbcbSup.c'
//
VOID
LfsFlushLbcb (
IN PLFCB Lfcb,
IN PLBCB Lbcb
);
VOID
LfsFlushToLsnPriv (
IN PLFCB Lfcb,
IN LSN Lsn
);
PLBCB
LfsGetLbcb (
IN PLFCB Lfcb
);
//
// The following routines are in LfsData.c
//
LONG
LfsExceptionFilter (
IN PEXCEPTION_POINTERS ExceptionPointer
);
//
// Log page support routines. The following routines manipulate and
// modify log pages. They are contained in 'LogPgSup.c'
//
//
// VOID
// LfsTruncateOffsetToLogPage (
// IN PLFCB Lfcb,
// IN LONGLONG LargeInt,
// OUT PLONGLONG Result
// );
//
// ULONG
// LfsLogPageOffset (
// IN PLFCB Lfcb,
// IN ULONG Integer
// );
//
#define LfsTruncateOffsetToLogPage(LFCB,LI,OUTLI) \
*(OUTLI) = LI; \
*((PULONG)(OUTLI)) &= (LFCB)->LogPageInverseMask
#define LfsLogPageOffset(LFCB,INT) \
(INT & (LFCB)->LogPageMask)
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
);
//
// The following routines provide support for dealing with log records. They
// are contained in 'LogRcSup.c'
//
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
);
//
// Lsn support routines. The following routines provide support for
// manipulating Lsn values. They are contained in 'LsnSup.c'
//
//
// LSN
// LfsFileOffsetToLsn (
// IN PLFCB Lfcb,
// IN LONGLONG FileOffset,
// IN LONGLONG SequenceNumber
// );
//
// BOOLEAN
// LfsIsLsnInFile (
// IN PLFCB Lfcb,
// IN LSN Lsn
// );
//
// LSN
// LfsComputeLsnFromLbcb (
// IN PLFCB Lfcb,
// IN PLBCB Lbcb
// );
//
// VOID
// LfsTruncateLsnToLogPage (
// IN PLFCB Lfcb,
// IN LSN Lsn,
// OUT PLONGLONG FileOffset
// );
//
// LONGLONG
// LfsLsnToFileOffset (
// IN PLFCB Lfcb,
// IN LSN Lsn
// );
//
// LONGLONG
// LfsLsnToSeqNumber (
// IN PLFCB Lfcb,
// IN LSN Lsn
// );
//
// ULONG
// LfsLsnToPageOffset (
// IN PLFCB Lfcb,
// IN LSN Lsn
// );
//
#define LfsFileOffsetToLsn(LFCB,FO,SN) ( \
(((ULONGLONG)(FO)) >> 3) + Int64ShllMod32((SN), (LFCB)->FileDataBits) \
)
#define LfsIsLsnInFile(LFCB,LSN) \
(/*xxGeq*/( (LSN).QuadPart >= ((LFCB)->OldestLsn).QuadPart ) \
&& /*xxLeq*/( (LSN).QuadPart <= ((LFCB)->RestartArea->CurrentLsn).QuadPart ))
#define LfsComputeLsnFromLbcb(LFCB,LBCB) ( \
LfsFileOffsetToLsn( LFCB, \
(LBCB)->FileOffset + (LBCB)->BufferOffset, \
(LBCB)->SeqNumber ) \
)
#define LfsTruncateLsnToLogPage(LFCB,LSN,FO) { \
*(FO) = LfsLsnToFileOffset( LFCB, LSN ); \
*((PULONG)(FO)) &= (LFCB)->LogPageInverseMask; \
}
#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 )
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
);
//
// The following routines support the Lfs restart areas. They are contained
// in 'RstrtSup.c'
//
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
);
//
// The following routines are used for managing the structures allocated
// by us. They are contained in 'StrucSup.c'
//
PLFCB
LfsAllocateLfcb (
IN ULONG LogPageSize,
IN LONGLONG FileSize
);
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
LfsAllocateLeb (
IN PLFCB Lfcb,
OUT PLEB *NewLeb
);
VOID
LfsDeallocateLeb (
IN PLFCB Lfcb,
IN PLEB Leb
);
VOID
LfsReadPage (
IN PLFCB Lfcb,
IN PLARGE_INTEGER Offset,
OUT PMDL *Mdl,
OUT PVOID *Buffer
);
//
// VOID
// LfsInitializeLeb (
// IN PLEB Leb,
// IN LFS_CLIENT_ID ClientId,
// IN LFS_CONTEXT_MODE ContextMode
// );
//
//
// VOID
// LfsAllocateLch (
// OUT PLCH *Lch
// );
//
// VOID
// LfsDeallocateLch (
// IN PLCH Lch
// );
//
// VOID
// LfsAllocateRestartArea (
// OUT PLFS_RESTART_AREA *RestartArea,
// ULONG Size
// );
//
// VOID
// LfsDeallocateRestartArea (
// IN PLFS_RESTART_AREA RestartArea
// );
//
// BOOLEAN
// LfsLbcbIsRestart (
// IN PLBCB Lbcb
// );
//
#define LfsInitializeLeb(LEB,ID,MODE) \
(LEB)->ClientId = ID; \
(LEB)->ContextMode = MODE
#define LfsAllocateLch(NEW) { \
*(NEW) = FsRtlAllocatePool( PagedPool, sizeof( LCH )); \
RtlZeroMemory( (*NEW), sizeof( LCH )); \
(*(NEW))->NodeTypeCode = LFS_NTC_LCH; \
(*(NEW))->NodeByteSize = sizeof( LCH ); \
}
#define LfsDeallocateLch(LCH) \
ExFreePool( LCH )
#define LfsAllocateRestartArea(RS,SIZE) \
*(RS) = FsRtlAllocatePool( PagedPool, (SIZE) ); \
RtlZeroMemory( *(RS), (SIZE) )
#define LfsDeallocateRestartArea(RS) \
ExFreePool( RS )
#define LfsLbcbIsRestart(LBCB) \
(FlagOn( (LBCB)->LbcbFlags, LBCB_RESTART_LBCB ))
//
// The following routines provide synchronization support for the Lfs
// shared structures. They are contained in 'SyncSup.c'
//
//
// VOID
// LfsAcquireLfsData (
// );
//
// VOID
// LfsReleaseLfsData (
// );
//
// VOID
// LfsAcquireLfcb (
// IN PLFCB Lfcb
// );
//
// VOID
// LfsReleaseLfcb (
// IN PLFCB Lfcb
// );
//
// VOID
// LfsAcquireLch (
// IN PLCH Lch
// );
//
// VOID
// LfsReleaseLfcb (
// IN PLCH Lch
// );
//
#define LfsAcquireLfsData() \
ExAcquireFastMutex( &LfsData.LfsDataLock )
#define LfsReleaseLfsData() \
ExReleaseFastMutex( &LfsData.LfsDataLock )
#define LfsAcquireBufferLock() \
ExAcquireFastMutex( &LfsData.BufferLock )
#define LfsReleaseBufferLock() \
ExReleaseFastMutex( &LfsData.BufferLock )
#define LfsWaitForBufferNotification() \
KeWaitForSingleObject( &LfsData.BufferNotification, \
Executive, \
KernelMode, \
FALSE, \
NULL )
#define LfsNotifyBufferWaiters() \
KeSetEvent( &LfsData.BufferNotification, 0, FALSE )
#define LfsBlockBufferWaiters() \
KeClearEvent( &LfsData.BufferNotification )
INLINE
VOID
LfsAcquireLfcb (
IN PLFCB Lfcb
)
{
ExAcquireResourceExclusiveLite( &Lfcb->Sync->Resource, TRUE );
}
INLINE
VOID
LfsReleaseLfcb (
IN PLFCB Lfcb
)
{
if (Lfcb->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) {
ExReleaseResourceLite( &Lfcb->Sync->Resource );
}
}
INLINE
VOID
LfsAcquireLch (
IN PLCH Lch
)
{
ExAcquireResourceExclusiveLite( &(Lch->Sync->Resource), TRUE );
}
INLINE
VOID
LfsReleaseLch (
IN PLCH Lch
)
{
if (Lch->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) {
ExReleaseResourceLite( &Lch->Sync->Resource );
}
}
//
// The following routines are used to check various structures for validity
// and comparability. They are contained in 'VerfySup.c'.
//
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
);
BOOLEAN
LfsCheckSubsequentLogPage (
IN PLFCB Lfcb,
IN PLFS_RECORD_PAGE_HEADER RecordPageHeader,
IN LONGLONG LogFileOffset,
IN LONGLONG SequenceNumber
);
//
// VOID
// LfsValidateLch (
// IN PLCH Lch
// );
//
// VOID
// LfsValidateClientId (
// IN PLFCB Lfcb,
// IN PLCH Lch
// );
//
// BOOLEAN
// LfsVerifyClientLsnInRange (
// IN PLFCB Lfcb,
// IN PLFS_CLIENT_RECORD ClientRecord,
// IN LSN Lsn
// );
//
// BOOLEAN
// LfsClientIdMatch (
// IN PLFS_CLIENT_ID ClientA,
// IN PLFS_CLIENT_ID ClientB
// )
//
// VOID
// LfsValidateLeb (
// IN PLFS_CONTEXT_BLOCK Leb,
// IN PLCH Lch
// )
//
#define LfsValidateLch(LCH) \
if ((LCH) == NULL \
|| (LCH)->NodeTypeCode != LFS_NTC_LCH \
|| ((LCH)->Lfcb != NULL \
&& (LCH)->Lfcb->NodeTypeCode != LFS_NTC_LFCB)) { \
\
ExRaiseStatus( STATUS_ACCESS_DENIED ); \
}
#define LfsValidateClientId(LFCB,LCH) \
if ((LCH)->ClientId.ClientIndex >= (LFCB)->RestartArea->LogClients \
|| (LCH)->ClientId.SeqNumber \
!= Add2Ptr( Lfcb->ClientArray, \
(LCH)->ClientArrayByteOffset, \
PLFS_CLIENT_RECORD )->SeqNumber) { \
ExRaiseStatus( STATUS_ACCESS_DENIED ); \
}
#define LfsVerifyClientLsnInRange(LFCB,CLIENT,LSN) \
(/*xxGeq*/( (LSN).QuadPart >= ((CLIENT)->OldestLsn).QuadPart ) \
&& /*xxLeq*/( (LSN).QuadPart <= ((LFCB)->RestartArea->CurrentLsn).QuadPart ) \
&& /*xxNeqZero*/( (LSN).QuadPart != 0 ))
#define LfsClientIdMatch(CLIENT_A,CLIENT_B) \
((BOOLEAN) ((CLIENT_A)->SeqNumber == (CLIENT_B)->SeqNumber \
&& (CLIENT_A)->ClientIndex == (CLIENT_B)->ClientIndex))
#define LfsValidateLeb(LEB,LCH) \
if (LEB == NULL \
|| (LEB)->NodeTypeCode != LFS_NTC_LEB \
|| !LfsClientIdMatch( &(LEB)->ClientId, &(LCH)->ClientId )) { \
ExRaiseStatus( STATUS_ACCESS_DENIED ); \
}
//
// Miscellaneous support routines
//
//
// ULONG
// FlagOn (
// IN ULONG Flags,
// IN ULONG SingleFlag
// );
//
// BOOLEAN
// BooleanFlagOn (
// IN ULONG Flags,
// IN ULONG SingleFlag
// );
//
// VOID
// SetFlag (
// IN ULONG Flags,
// IN ULONG SingleFlag
// );
//
// VOID
// ClearFlag (
// IN ULONG Flags,
// IN ULONG SingleFlag
// );
//
//#ifndef BooleanFlagOn
//#define BooleanFlagOn(F,SF) ( \
// (BOOLEAN)(((F) & (SF)) != 0) \
//)
//#endif
//#ifndef SetFlag
//#define SetFlag(Flags,SingleFlag) { \
// (Flags) |= (SingleFlag); \
//}
//#endif
//#ifndef ClearFlag
//#define ClearFlag(Flags,SingleFlag) { \
// (Flags) &= ~(SingleFlag); \
//}
//#endif
//
// This macro takes a pointer (or ulong) and returns its rounded up word
// value
//
#define WordAlign(Ptr) ( \
((((ULONG)(Ptr)) + 1) & 0xfffffffe) \
)
//
// This macro takes a pointer (or ulong) and returns its rounded up longword
// value
//
#define LongAlign(Ptr) ( \
((((ULONG)(Ptr)) + 3) & 0xfffffffc) \
)
//
// This macro takes a pointer (or ulong) and returns its rounded up quadword
// value
//
#define QuadAlign(Ptr) ( \
((((ULONG)(Ptr)) + 7) & 0xfffffff8) \
)
//
// This macro will up a 64 bit value to the next quad align boundary.
//
#define LiQuadAlign(LI,OUT) { \
*(OUT) = /*xxAdd*/( (LI) + 7 ); \
*((PULONG)(OUT)) &= 0xfffffff8; \
}
//
// CAST
// Add2Ptr (
// IN PVOID Pointer,
// IN ULONG Increment
// IN (CAST)
// );
//
// ULONG
// PtrOffset (
// IN PVOID BasePtr,
// IN PVOID OffsetPtr
// );
//
#define Add2Ptr(PTR,INC,CAST) ((CAST)((PUCHAR)(PTR) + (INC)))
#define PtrOffset(BASE,OFFSET) ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE)))
//
// The following macros are used to establish the semantics needed
// to do a return from within a try-finally clause. As a rule every
// try clause must end with a label call try_exit. For example,
//
// try {
// :
// :
//
// try_exit: NOTHING;
// } finally {
//
// :
// :
// }
//
// Every return statement executed inside of a try clause should use the
// try_return macro. If the compiler fully supports the try-finally construct
// then the macro should be
//
// #define try_return(S) { return(S); }
//
// If the compiler does not support the try-finally construct then the macro
// should be
//
// #define try_return(S) { S; goto try_exit; }
//
#define try_return(S) { S; goto try_exit; }
#endif // _LFSPROCS_