/*++ BUILD Version: 0000 // Increment this if a change has global effects Copyright (c) 1989 Microsoft Corporation Module Name: LfsStruc.h Abstract: This module defines the data structures that make up the major internal part of the Log File Service. Author: Brian Andrew [BrianAn] 13-June-1991 Revision History: --*/ #ifndef _LFSSTRUC_ #define _LFSSTRUC_ typedef PVOID PBCB; //**** Bcb's are now part of the cache module // // Log Enumeration Block. A pointer to this structure is returned to the user // when a client is reading a particular set of log records from the log // file. // typedef struct _LEB { // // The type and size of this record (must be LFS_NTC_LEB) // NODE_TYPE_CODE NodeTypeCode; NODE_BYTE_SIZE NodeByteSize; // // Log record header. This is the mapped log record header and bcb // for the record header of the current Lsn. // struct _LFS_RECORD_HEADER *RecordHeader; PBCB RecordHeaderBcb; // // Context Mode. This is the mode governing the log record lookup. We // can look backwards via the ClientUndoNextLsn or ClientPreviousLsn. // We can also look forwards by walking through all the log records and // comparing ClientId fields. // LFS_CONTEXT_MODE ContextMode; // // Client Id. This is the client ID for the log records being returned. // LFS_CLIENT_ID ClientId; // // Log record pointer. This is the address returned to the user as the // log record referred to by CurrentLsn. If we allocated a buffer to // hold the record, we need to deallocate it as necessary. // // This field is either the actual mapped log record or a pointer to // an auxilary buffer allocated by the Lfs. // PVOID CurrentLogRecord; BOOLEAN AuxilaryBuffer; } LEB, *PLEB; // // Lfcb synchronization. This is the synchronization structure used by the Lfcb. // typedef struct _LFCB_SYNC { // // Principal Lfcb Resource. // ERESOURCE Resource; // // Notification Event. This event is set to the Signalled state when // pages are flushed to the cache file. Any waiters will then check // to see if the Lsn they're waiting for made it to disk. // KEVENT Event; // // User Count. Number of clients using this structure. We will deallocate // when all clients are gone. // ULONG UserCount; // // Mutant to guard Leb spare list // FAST_MUTEX SpareListMutex; } LFCB_SYNC, *PLFCB_SYNC; // // Log Client Structure. The Lfs allocates one of these for each active // client. The address of this structure will be returned to the user // as a log handle. // typedef struct _LCH { // // The type and size of this record (must be LFS_NTC_LCH) // NODE_TYPE_CODE NodeTypeCode; NODE_BYTE_SIZE NodeByteSize; // // Links for all the client handles on an Lfcb. // LIST_ENTRY LchLinks; // // Log File Control Block. This is the log file for this log handle. // struct _LFCB *Lfcb; // // Client Id. This refers to the client record for this client in the // Lfs restart area. // LFS_CLIENT_ID ClientId; // // The following is the number of bytes this client has asked to // have reserved in the log file. It includes the space // for the log record headers. // LONGLONG ClientUndoCommitment; // // Byte offset in the client array. // ULONG ClientArrayByteOffset; // // Pointer to the resource in the Lfcb. We access the resource with // this pointer for the times when the lfcb has been deleted. // PLFCB_SYNC Sync; } LCH, *PLCH; // // Log Buffer Control Block. A buffer control block is associated with // each of the log buffers. They are used to serialize access to the // log file. // typedef struct _LBCB { // // The type and size of this record (must be LFS_NTC_LBCB) // NODE_TYPE_CODE NodeTypeCode; NODE_BYTE_SIZE NodeByteSize; // // Buffer Block Links. These fields are used to link the buffer blocks // together. // LIST_ENTRY WorkqueLinks; LIST_ENTRY ActiveLinks; // // Log file position and length. This is the location in the log file to write // out this buffer. // LONGLONG FileOffset; LONGLONG Length; // // Sequence number. This is the sequence number for log records which // begin on this page. // LONGLONG SeqNumber; // // Next Offset. This is the next offset to write a log record in the // this log page. Stored as a large integer to facilitate large // integer operations. // LONGLONG BufferOffset; // // Buffer. This field points to the buffer containing the log page // for this block. For a log record page this is a pointer to // a pinned cache buffer, for a log restart page, this is a pointer // to an auxilary buffer. // PVOID PageHeader; // // Bcb for Log Page Block. This is the Bcb for the pinned data. // If this buffer block describes an Lfs restart area, this field is NULL. // PBCB LogPageBcb; // // Last Lsn. This is the Lsn for the last log record on this page. We delay // writing it until the page is flushed, storing it here instead. // LSN LastLsn; // // Last complete Lsn. This is the Lsn for the last log record which ends // on this page. // LSN LastEndLsn; // // Page Flags. These are the flags associated with this log page. // We store them in the Lbcb until the page is written. They flags // to use are the same as in the log record page header. // // LOG_PAGE_LOG_RECORD_END - Page contains the end of a log record // LOG_PAGE_PACKED - Page contains packed log records // LOG_PAGE_TAIL_COPY - Page is a copy of the log file end // ULONG Flags; // // Lbcb flags. These are flags used to describe this Lbcb. // // LBCB_LOG_WRAPPED - Lbcb has wrapped the log file // LBCB_ON_ACTIVE_QUEUE - Lbcb is on the active queue // LBCB_NOT_EMPTY - Page has existing log record // LBCB_FLUSH_COPY - Write copy of this page first // LBCB_RESTART_LBCB - This Lbcb contains a restart page // ULONG LbcbFlags; // // This is the thread which has locked the log page. // ERESOURCE_THREAD ResourceThread; } LBCB, *PLBCB; #define LBCB_LOG_WRAPPED (0x00000001) #define LBCB_ON_ACTIVE_QUEUE (0x00000002) #define LBCB_NOT_EMPTY (0x00000004) #define LBCB_FLUSH_COPY (0x00000008) #define LBCB_RESTART_LBCB (0x00000020) // // Log file data. This data structure is used on a per-log file basis. // typedef enum _LFS_IO_STATE { LfsNoIoInProgress = 0, LfsClientThreadIo } LFS_IO_STATE; typedef struct _LFCB { // // The type and size of this record (must be LFS_NTC_LFCB) // NODE_TYPE_CODE NodeTypeCode; NODE_BYTE_SIZE NodeByteSize; // // Lfcb Links. The following links the file control blocks to the // global data structure. // LIST_ENTRY LfcbLinks; // // Lch Links. The following links all of the handles for the Lfcb. // LIST_ENTRY LchLinks; // // // File Object. This is the file object for the log file. // PFILE_OBJECT FileObject; // // Log File Size. This is the size of the log file. // The second value is the size proposed by this open. // LONGLONG FileSize; // // Log page size, masks and shift count to do multiplication and division // of log pages. // LONGLONG LogPageSize; ULONG LogPageMask; LONG LogPageInverseMask; ULONG LogPageShift; // // First log page. This is the offset in the file of the first // log page with log records. // LONGLONG FirstLogPage; // // Next log page offset. This is the offset of the next log page to use. // If we are reusing this page we store the offset to begin with. // LONGLONG NextLogPage; ULONG ReusePageOffset; // // Data Offset. This is the offset within a log page of the data that // appears on that page. This will be the actual restart data for // an Lfs restart page, or the beginning of log record data for a log // record page. // ULONG RestartDataOffset; LONGLONG LogPageDataOffset; // // Data Size. This is the amount of data that may be stored on a // log page. It is included here because it is frequently used. It // is simply the log page size minus the data offset. // ULONG RestartDataSize; LONGLONG LogPageDataSize; // // Record header size. This is the size to use for the record headers // when reading the log file. // USHORT RecordHeaderLength; // // Sequence number. This is the number of times we have cycled through // the log file. The wrap sequence number is used to confirm that we // have gone through the entire file at least once. When we write a // log record page for an Lsn with this sequence number, then we have // cycled through the file. // LONGLONG SeqNumber; LONGLONG SeqNumberForWrap; ULONG SeqNumberBits; ULONG FileDataBits; // // Buffer Block Links. The following links the buffer blocks for this // log file. // LIST_ENTRY LbcbWorkque; LIST_ENTRY LbcbActive; PLBCB ActiveTail; PLBCB PrevTail; // // The enumerated type indicates if there is an active write for // this log file and whether it is being done by an Lfs or // client thread. // LFS_IO_STATE LfsIoState; // // Current Restart Area. The following is the in-memory image of the // next restart area. We also store a pointer to the client data // array in the restart area. The client array offset is from the start of // the restart area. // PLFS_RESTART_AREA RestartArea; PLFS_CLIENT_RECORD ClientArray; USHORT ClientArrayOffset; USHORT ClientNameOffset; // // Restart Area size. This is the usable size of the restart area. // ULONG RestartAreaSize; USHORT LogClients; // // Initial Restart area. If true, then the in-memory restart area is to // be written to the first position on the disk. // BOOLEAN InitialRestartArea; // // The following pseudo Lsn's are used to track when restart areas // are flushed to the disk. // LSN NextRestartLsn; LSN LastFlushedRestartLsn; // // The following is the earliest Lsn we will guarantee is still in the // log file. // LSN OldestLsn; // // The following is the file offset of the oldest Lsn in the system. // We redundantly store it in this form since we will be constantly // checking if a new log record will write over part of the file // we are trying to maintain. // LONGLONG OldestLsnOffset; // // Last Flushed Lsn. The following is the last Lsn guaranteed to // be flushed to the disk. // LSN LastFlushedLsn; // // // The following fields are used to track current usage in the log file. // // TotalAvailable - is the total number of bytes available for // log records. It is the number of log pages times the // data size of each page. // // TotalAvailInPages - is the total number of bytes in the log // pages for log records. This is TotalAvailable without // subtracting the size of the page headers. // // TotalUndoCommitment - is the number of bytes reserved for // possible abort operations. This includes space for // log record headers as well. // // MaxCurrentAvail - is the maximum available in all pages // subtracting the page header and any reserved tail. // // CurrentAvailable - is the total number of bytes available in // unused pages in the log file. // // ReservedLogPageSize - is the number of bytes on a page available // for reservation. // LONGLONG TotalAvailable; LONGLONG TotalAvailInPages; LONGLONG TotalUndoCommitment; LONGLONG MaxCurrentAvail; LONGLONG CurrentAvailable; LONGLONG ReservedLogPageSize; // // The following fields are used to store information about the // update sequence arrays. // USHORT RestartUsaOffset; USHORT UsaArraySize; USHORT LogRecordUsaOffset; // // Major and minor version numbers. // SHORT MajorVersion; SHORT MinorVersion; // // Log File Flags. // // LFCB_LOG_WRAPPED - We found an Lbcb which wraps the log file // LFCB_MULTIPLE_PAGE_IO - Write multiple pages if possible // LFCB_NO_LAST_LSN - There are no log records to return // LFCB_PACK_LOG - Pack the records into the pages // LFCB_REUSE_TAIL - We will be reusing the tail of the log file after restart // LFCB_NO_OLDEST_LSN - There is no oldest page being reserved // ULONG Flags; // // The following are the spare Lbcb's for the volume and a field with // the count for these. // ULONG SpareLbcbCount; LIST_ENTRY SpareLbcbList; // // The following are sparse LEB's to be used rather than having to allocate // then when reading log records // ULONG SpareLebCount; LIST_ENTRY SpareLebList; // // The following structure synchronizes access to this structure. // PLFCB_SYNC Sync; // // Count of waiters wanting access to flush the Lfcb. // ULONG Waiters; // // On-disk value for OpenLogCount. This is the value we will stuff into // the client handles. // ULONG CurrentOpenLogCount; // // Maintain the flush range for this file. // PLFS_WRITE_DATA UserWriteData; ERESOURCE_THREAD LfsIoThread; // // Buffer and mdls which hold down the first 4 pages at the head of the log // this includes the lfs restart areas and the ping pong pages. The partial mdl // is used to pin pieces of the total buffer // PMDL LogHeadMdl; PMDL LogHeadPartialMdl; PVOID LogHeadBuffer; // // preallocated error log packet for use logging errors to the eventlog // PIO_ERROR_LOG_PACKET ErrorLogPacket; #ifdef LFS_CLUSTER_CHECK LSN LsnAtMount; ULONG LsnRangeIndex; #endif // // Embedded array with enough space for SYSTEM PAGE / LOG PAGE SIZE // used to facilitate flushing partial system pages // PLBCB DirtyLbcb[0]; } LFCB, *PLFCB; #define LFCB_LOG_WRAPPED (0x00000001) #define LFCB_MULTIPLE_PAGE_IO (0x00000002) #define LFCB_NO_LAST_LSN (0x00000004) #define LFCB_PACK_LOG (0x00000008) #define LFCB_REUSE_TAIL (0x00000010) #define LFCB_NO_OLDEST_LSN (0x00000020) #define LFCB_LOG_FILE_CORRUPT (0x00000040) #define LFCB_FINAL_SHUTDOWN (0x00000080) #define LFCB_READ_FIRST_RESTART (0x00000100) #define LFCB_READ_SECOND_RESTART (0x00000200) #define LFCB_READ_ONLY (0x00000400) #ifdef LFS_CLUSTER_CHECK #define LFCB_DEVICE_OFFLINE_SEEN (0x80000000) #define LFCB_FLUSH_FAILED (0x40000000) #endif #define LFCB_RESERVE_LBCB_COUNT (5) #define LFCB_MAX_LBCB_COUNT (25) #define LFCB_RESERVE_LEB_COUNT (5) #define LFCB_MAX_LEB_COUNT (25) // // Global Log Data. The following structure has only one instance and // maintains global information for the entire logging service. // typedef struct _LFS_DATA { // // The type and size of this record (must be LFS_NTC_DATA) // NODE_TYPE_CODE NodeTypeCode; NODE_BYTE_SIZE NodeByteSize; // // The following field links all of the Log File Control Blocks for // the logging system. // LIST_ENTRY LfcbLinks; // // Flag field. // ULONG Flags; // // The following mutex controls access to this structure. // FAST_MUTEX LfsDataLock; // // Allocated buffers for reading spanning log records in low memory case. // Flags indicate which buffers owned. // LFS_BUFFER1_OWNED // LFS_BUFFER2_OWNED // PVOID Buffer1; PVOID Buffer2; ERESOURCE_THREAD BufferOwner; ULONG BufferFlags; FAST_MUTEX BufferLock; KEVENT BufferNotification; } LFS_DATA, *PLFS_DATA; #define LFS_DATA_INIT_FAILED (0x00000001) #define LFS_DATA_INITIALIZED (0x00000002) #define LFS_BUFFER1_OWNED (0x00000001) #define LFS_BUFFER2_OWNED (0x00000002) #define LFS_BUFFER_SIZE (0x10000) #endif // _LFSSTRUC_