/*++ BUILD Version: 0000 // Increment this if a change has global effects Copyright (c) 1989 Microsoft Corporation Module Name: LfsDisk.h Abstract: This module defines the on-disk structures present in the log file. Author: Brian Andrew [BrianAn] 13-June-1991 Revision History: IMPORTANT NOTE: The Log File Service will by used on systems that require that on-disk structures guarantee the natural alignment of all arithmetic quantities up to and including quad-word (64-bit) numbers. Therefore, all Lfs on-disk structures are quad-word aligned, etc. --*/ #ifndef _LFSDISK_ #define _LFSDISK_ #define MINIMUM_LFS_PAGES 0x00000030 #define MINIMUM_LFS_CLIENTS 1 // // The following macros are used to set and query with respect to the // update sequence arrays. // #define UpdateSequenceStructureSize( MSH ) \ ((((PMULTI_SECTOR_HEADER) (MSH))->UpdateSequenceArraySize - 1) * SEQUENCE_NUMBER_STRIDE) #define UpdateSequenceArraySize( STRUCT_SIZE ) \ ((STRUCT_SIZE) / SEQUENCE_NUMBER_STRIDE + 1) #define FIRST_STRIDE \ (SEQUENCE_NUMBER_STRIDE - sizeof( UPDATE_SEQUENCE_NUMBER )) // // Log client ID. This is used to uniquely identify a client for a // particular log file. // typedef struct _LFS_CLIENT_ID { USHORT SeqNumber; USHORT ClientIndex; } LFS_CLIENT_ID, *PLFS_CLIENT_ID; // // Log Record Header. This is the header that begins every Log Record in // the log file. // typedef struct _LFS_RECORD_HEADER { // // Log File Sequence Number of this log record. // LSN ThisLsn; // // The following fields are used to back link Lsn's. The ClientPrevious // and ClientUndoNextLsn fields are used by a client to link his log // records. // LSN ClientPreviousLsn; LSN ClientUndoNextLsn; // // The following field is the size of data area for this record. The // log record header will be padded if necessary to fill to a 64-bit // boundary, so the client data will begin on a 64-bit boundary to // insure that all of his data is 64-bit aligned. The below value // has not been padded to 64 bits however. // ULONG ClientDataLength; // // Client ID. This identifies the owner of this log record. The owner // is uniquely identified by his offset in the client array and the // sequence number associated with that client record. // LFS_CLIENT_ID ClientId; // // This the Log Record type. This could be a commit protocol record, // a client restart area or a client update record. // LFS_RECORD_TYPE RecordType; // // Transaction ID. This is used externally by a client (Transaction // Manager) to group log file entries. // TRANSACTION_ID TransactionId; // // Log record flags. // USHORT Flags; // // Alignment field. // USHORT AlignWord; } LFS_RECORD_HEADER, *PLFS_RECORD_HEADER; #define LOG_RECORD_MULTI_PAGE (0x0001) #define LFS_RECORD_HEADER_SIZE QuadAlign( sizeof( LFS_RECORD_HEADER )) // // Following are the version specific fields in the record page header. // typedef struct _LFS_UNPACKED_RECORD_PAGE { // // This gives us the offset of the free space in the page. // USHORT NextRecordOffset; USHORT WordAlign; // // Reserved. The following array is reserved for possible future use. // USHORT Reserved; // // Update Sequence Array. Used to protect the page block. // UPDATE_SEQUENCE_ARRAY UpdateSequenceArray; } LFS_UNPACKED_RECORD_PAGE, *PLFS_UNPACKED_RECORD_PAGE; typedef struct _LFS_PACKED_RECORD_PAGE { // // This gives us the offset of the free space in the page. // USHORT NextRecordOffset; USHORT WordAlign; ULONG DWordAlign; // // The following is the Lsn for the last log record which ends on the page. // LSN LastEndLsn; // // Update Sequence Array. Used to protect the page block. // UPDATE_SEQUENCE_ARRAY UpdateSequenceArray; } LFS_PACKED_RECORD_PAGE, *PLFS_PACKED_RECORD_PAGE; // // Log Record Page Header. This structure is present at the beginning of each // log file page in the client record section. // typedef struct _LFS_RECORD_PAGE_HEADER { // // Cache multisector protection header. // MULTI_SECTOR_HEADER MultiSectorHeader; union { // // Highest Lsn in this log file page. This field is only for // regular log pages. // LSN LastLsn; // // Log file offset. This is for the tail copies and indicates the // location in the file where the original lays. In this case the // LastLsn field above can be obtained from the last ending Lsn // field in the PACKED_RECORD_PAGE structure. // LONGLONG FileOffset; } Copy; // // Page Header Flags. These are the same flags that are stored in the // Lbcb->Flags field. // // LOG_PAGE_LOG_RECORD_END - Page contains the end of a log record // ULONG Flags; // // I/O Page Position. The following fields are used to determine // where this log page resides within a Lfs I/O transfer. // USHORT PageCount; USHORT PagePosition; // // The following is the difference between version 1.1 and earlier. // union { LFS_UNPACKED_RECORD_PAGE Unpacked; LFS_PACKED_RECORD_PAGE Packed; } Header; } LFS_RECORD_PAGE_HEADER, *PLFS_RECORD_PAGE_HEADER; #define LOG_PAGE_LOG_RECORD_END (0x00000001) #define LFS_UNPACKED_RECORD_PAGE_HEADER_SIZE ( \ FIELD_OFFSET( LFS_RECORD_PAGE_HEADER, Header.Unpacked.UpdateSequenceArray ) \ ) #define LFS_PACKED_RECORD_PAGE_HEADER_SIZE ( \ FIELD_OFFSET( LFS_RECORD_PAGE_HEADER, Header.Packed.UpdateSequenceArray ) \ ) // // Log Restart Page Header. This structure is at the head of the restart // areas in a log file. // typedef struct _LFS_RESTART_PAGE_HEADER { // // Cache multisector protection header. // MULTI_SECTOR_HEADER MultiSectorHeader; // // This is the last Lsn found by checkdisk for this volume. // LSN ChkDskLsn; // // System page size. This is the page size of the system which // initialized the log file. Unless the log file has been gracefully // shutdown (there are no clients with restart areas), it is a fatal // error to attempt to write to a log file on a system with a differen // page size. // ULONG SystemPageSize; // // Log Page Size. This is the log page size used for this log file. // The entire Lfs restart area must fit on a single log page. // ULONG LogPageSize; // // Lfs restart area offset. This is the offset from the start of this // structure to the Lfs restart area. // USHORT RestartOffset; // // The indicates major and minor versions. Note that the pre-release versions // have -1 in both positions. Major version 0 indicates the transition // from Beta to USA support. // // Major Version // // -1 Beta Version // 0 Transition // 1 Update sequence support. // SHORT MinorVersion; SHORT MajorVersion; // // Update Sequence Array. Used to protect the page block. // UPDATE_SEQUENCE_ARRAY UpdateSequenceArray; } LFS_RESTART_PAGE_HEADER, *PLFS_RESTART_PAGE_HEADER; #define LFS_RESTART_PAGE_HEADER_SIZE ( \ FIELD_OFFSET( LFS_RESTART_PAGE_HEADER, UpdateSequenceArray ) \ ) // // Id strings for the page headers. // #define LFS_SIGNATURE_RESTART_PAGE "RSTR" #define LFS_SIGNATURE_RESTART_PAGE_ULONG 0x52545352 #define LFS_SIGNATURE_RECORD_PAGE "RCRD" #define LFS_SIGNATURE_RECORD_PAGE_ULONG 0x44524352 #define LFS_SIGNATURE_BAD_USA "BAAD" #define LFS_SIGNATURE_BAD_USA_ULONG 0x44414142 #define LFS_SIGNATURE_MODIFIED "CHKD" #define LFS_SIGNATURE_MODIFIED_ULONG 0x444b4843 #define LFS_SIGNATURE_UNINITIALIZED "\377\377\377\377" #define LFS_SIGNATURE_UNINITIALIZED_ULONG 0xffffffff // // Log Client Record. A log client record exists for each client user of // the log file. One of these is in each Lfs restart area. // #define LFS_NO_CLIENT 0xffff #define LFS_CLIENT_NAME_MAX 64 typedef struct _LFS_CLIENT_RECORD { // // Oldest Lsn. This is the oldest Lsn that this client requires to // be in the log file. // LSN OldestLsn; // // Client Restart Lsn. This is the Lsn of the latest client restart // area written to the disk. A reserved Lsn will indicate that no // restart area exists for this client. // LSN ClientRestartLsn; // // // Previous/Next client area. These are the indexes into an array of // Log Client Records for the previous and next client records. // USHORT PrevClient; USHORT NextClient; // // Sequence Number. Incremented whenever this record is reused. This // will happen whenever a client opens (reopens) the log file and has // no current restart area. USHORT SeqNumber; // // Alignment field. // USHORT AlignWord; // // Align the entire record. // ULONG AlignDWord; // // The following fields are used to describe the client name. A client // name consists of at most 32 Unicode character (64 bytes). The Log // file service will treat client names as case sensitive. // ULONG ClientNameLength; WCHAR ClientName[LFS_CLIENT_NAME_MAX]; } LFS_CLIENT_RECORD, *PLFS_CLIENT_RECORD; // // Lfs Restart Area. Two copies of these will exist at the beginning of the // log file. // typedef struct _LFS_RESTART_AREA { // // Current Lsn. This is periodic snapshot of the current logical end of // log file to facilitate restart. // LSN CurrentLsn; // // Number of Clients. This is the maximum number of clients supported // for this log file. // USHORT LogClients; // // The following are indexes into the client record arrays. The client // records are linked into two lists. A free list of client records and // an in-use list of records. // USHORT ClientFreeList; USHORT ClientInUseList; // // Flag field. // // RESTART_SINGLE_PAGE_IO All log pages written 1 by 1 // LFS_CLEAN_SHUTDOWN // USHORT Flags; // // The following is the number of bits to use for the sequence number. // ULONG SeqNumberBits; // // Length of this restart area. // USHORT RestartAreaLength; // // Offset from the start of this structure to the client array. // Ignored in versions prior to 1.1 // USHORT ClientArrayOffset; // // Usable log file size. We will stop sharing the value in the page header. // LONGLONG FileSize; // // DataLength of last Lsn. This doesn't include the length of // the Lfs header. // ULONG LastLsnDataLength; // // The following apply to log pages. This is the log page data offset and // the length of the log record header. Ignored in versions prior to 1.1 // USHORT RecordHeaderLength; USHORT LogPageDataOffset; // // Log file open count. Used to determine if there has been a change to the disk. // ULONG RestartOpenLogCount; // // Track log flush failures // ULONG LastFailedFlushStatus; LONGLONG LastFailedFlushOffset; LSN LastFailedFlushLsn; // // Keep this structure quadword aligned. // // // Client data. // LFS_CLIENT_RECORD LogClientArray[1]; } LFS_RESTART_AREA, *PLFS_RESTART_AREA; #define RESTART_SINGLE_PAGE_IO (0x0001) #define LFS_CLEAN_SHUTDOWN (0x0002) #define LFS_RESTART_AREA_SIZE (FIELD_OFFSET( LFS_RESTART_AREA, LogClientArray )) // // Remember the old size of the restart area when accessing older disks. // typedef struct _LFS_OLD_RESTART_AREA { // // Current Lsn. This is periodic snapshot of the current logical end of // log file to facilitate restart. // LSN CurrentLsn; // // Number of Clients. This is the maximum number of clients supported // for this log file. // USHORT LogClients; // // The following are indexes into the client record arrays. The client // records are linked into two lists. A free list of client records and // an in-use list of records. // USHORT ClientFreeList; USHORT ClientInUseList; // // Flag field. // // RESTART_SINGLE_PAGE_IO All log pages written 1 by 1 // USHORT Flags; // // The following is the number of bits to use for the sequence number. // ULONG SeqNumberBits; // // Length of this restart area. // USHORT RestartAreaLength; // // Offset from the start of this structure to the client array. // Ignored in versions prior to 1.1 // USHORT ClientArrayOffset; // // Usable log file size. We will stop sharing the value in the page header. // LONGLONG FileSize; // // DataLength of last Lsn. This doesn't include the length of // the Lfs header. // ULONG LastLsnDataLength; // // The following apply to log pages. This is the log page data offset and // the length of the log record header. Ignored in versions prior to 1.1 // USHORT RecordHeaderLength; USHORT LogPageDataOffset; // // Client data. // LFS_CLIENT_RECORD LogClientArray[1]; } LFS_OLD_RESTART_AREA, *PLFS_OLD_RESTART_AREA; #endif // _LFSDISK_