611 lines
14 KiB
C
611 lines
14 KiB
C
|
/*++ 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_
|