944 lines
25 KiB
C
944 lines
25 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
NtfsLog.h
|
||
|
||
Abstract:
|
||
|
||
This module defines the Ntfs-specific log file structures.
|
||
|
||
Author:
|
||
|
||
Tom Miller [TomM] 21-Jul-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#ifndef _NTFSLOG_
|
||
#define _NTFSLOG_
|
||
|
||
|
||
//
|
||
// The following type defines the Ntfs log operations.
|
||
//
|
||
// The comment specifies the record type which follows the record.
|
||
// These record types are defined either here or in ntfs.h.
|
||
//
|
||
|
||
typedef enum _NTFS_LOG_OPERATION {
|
||
|
||
Noop = 0x00, //
|
||
CompensationLogRecord = 0x01, //
|
||
InitializeFileRecordSegment = 0x02, // FILE_RECORD_SEGMENT_HEADER
|
||
DeallocateFileRecordSegment = 0x03, //
|
||
WriteEndOfFileRecordSegment = 0x04, // ATTRIBUTE_RECORD_HEADER
|
||
CreateAttribute = 0x05, // ATTRIBUTE_RECORD_HEADER
|
||
DeleteAttribute = 0x06, //
|
||
UpdateResidentValue = 0x07, // (value)
|
||
UpdateNonresidentValue = 0x08, // (value)
|
||
UpdateMappingPairs = 0x09, // (value = mapping pairs bytes)
|
||
DeleteDirtyClusters = 0x0A, // array of LCN_RANGE
|
||
SetNewAttributeSizes = 0x0B, // NEW_ATTRIBUTE_SIZES
|
||
AddIndexEntryRoot = 0x0C, // INDEX_ENTRY
|
||
DeleteIndexEntryRoot = 0x0D, // INDEX_ENTRY
|
||
AddIndexEntryAllocation = 0x0E, // INDEX_ENTRY
|
||
DeleteIndexEntryAllocation = 0x0F, // INDEX_ENTRY
|
||
WriteEndOfIndexBuffer = 0x10, // INDEX_ENTRY
|
||
SetIndexEntryVcnRoot = 0x11, // VCN
|
||
SetIndexEntryVcnAllocation = 0x12, // VCN
|
||
UpdateFileNameRoot = 0x13, // DUPLICATED_INFORMATION
|
||
UpdateFileNameAllocation = 0x14, // DUPLICATED_INFORMATION
|
||
SetBitsInNonresidentBitMap = 0x15, // BITMAP_RANGE
|
||
ClearBitsInNonresidentBitMap = 0x16, // BITMAP_RANGE
|
||
HotFix = 0x17, //
|
||
EndTopLevelAction = 0x18, //
|
||
PrepareTransaction = 0x19, //
|
||
CommitTransaction = 0x1A, //
|
||
ForgetTransaction = 0x1B, //
|
||
OpenNonresidentAttribute = 0x1C, // OPEN_ATTRIBUTE_ENTRY+ATTRIBUTE_NAME_ENTRY
|
||
OpenAttributeTableDump = 0x1D, // OPEN_ATTRIBUTE_ENTRY array
|
||
AttributeNamesDump = 0x1E, // (all attribute names)
|
||
DirtyPageTableDump = 0x1F, // DIRTY_PAGE_ENTRY array
|
||
TransactionTableDump = 0x20, // TRANSACTION_ENTRY array
|
||
UpdateRecordDataRoot = 0x21, // (value)
|
||
UpdateRecordDataAllocation = 0x22 // (value)
|
||
|
||
} NTFS_LOG_OPERATION, *PNTFS_LOG_OPERATION;
|
||
|
||
|
||
//
|
||
// The Ntfs log record header precedes every log record written to
|
||
// disk by Ntfs.
|
||
//
|
||
|
||
//
|
||
// Log record header.
|
||
//
|
||
|
||
typedef struct _NTFS_LOG_RECORD_HEADER {
|
||
|
||
//
|
||
// Log Operations (LOG_xxx codes)
|
||
//
|
||
|
||
USHORT RedoOperation;
|
||
USHORT UndoOperation;
|
||
|
||
//
|
||
// Offset to Redo record, and its length
|
||
//
|
||
|
||
USHORT RedoOffset;
|
||
USHORT RedoLength;
|
||
|
||
//
|
||
// Offset to Undo record, and its length. Note, for some Redo/Undo
|
||
// combinations, the expected records may be the same, and thus
|
||
// these two values will be identical to the above values.
|
||
//
|
||
|
||
USHORT UndoOffset;
|
||
USHORT UndoLength;
|
||
|
||
//
|
||
// Open attribute table index to which this update applies. Index 0 is
|
||
// always reserved for the MFT itself. The value of this field
|
||
// essentially distinguishes two cases for this update, which will be
|
||
// referred to as MFT update and nonresident attribute update.
|
||
//
|
||
// MFT updates are for initialization and deletion of file record
|
||
// segments and updates to resident attributes.
|
||
//
|
||
// Nonresident attribute updates are used to update attributes which
|
||
// have been allocated externally to the MFT.
|
||
//
|
||
|
||
USHORT TargetAttribute;
|
||
|
||
//
|
||
// Number of Lcns in use at end of header.
|
||
//
|
||
|
||
USHORT LcnsToFollow;
|
||
|
||
//
|
||
// Byte offset and Vcn for which this update is to be applied. If the
|
||
// TargetAttribute is the MFT, then the Vcn will always be the exact
|
||
// Vcn of the start of the file record segment being modified, even
|
||
// if the modification happens to be in a subsequent cluster of the
|
||
// same file record. The byte offset in this case is the offset to
|
||
// the attribute being changed. For the Mft, AttributeOffset may be used
|
||
// to represent the offset from the start of the attribute record
|
||
// at which an update is to be applied.
|
||
//
|
||
// If the update is to some other (nonresident) attribute, then
|
||
// TargetVcn and RecordOffset may be used to calculate the reference
|
||
// point for the update. The ClusterBlockOffset refers to the number
|
||
// of 512 byte blocks this structure is from the beginning of the
|
||
// logged Vcn.
|
||
//
|
||
// As a bottom line, the exact use of these fields is up to the
|
||
// writer of this particular log operation, and the associated
|
||
// restart routines for this attribute.
|
||
//
|
||
|
||
USHORT RecordOffset;
|
||
USHORT AttributeOffset;
|
||
USHORT ClusterBlockOffset;
|
||
USHORT Reserved;
|
||
VCN TargetVcn;
|
||
|
||
//
|
||
// Run information. This is a variable-length array of LcnsToFollow
|
||
// entries, only the first of which is declared. Note that the writer
|
||
// always writes log records according to the physical page size on his
|
||
// machine, however whenever the log file is being read, no assumption
|
||
// is made about page size. This is to facilitate moving disks between
|
||
// systems with different page sizes.
|
||
//
|
||
|
||
LCN LcnsForPage[1];
|
||
|
||
//
|
||
// Immediately following the last run is a log-operation-specific record
|
||
// whose length may be calculated by subtracting the length of this header
|
||
// from the length of the entire record returned by LFS. These records
|
||
// are defined below.
|
||
//
|
||
|
||
} NTFS_LOG_RECORD_HEADER, *PNTFS_LOG_RECORD_HEADER;
|
||
|
||
|
||
//
|
||
// RESTART AREA STRUCTURES
|
||
//
|
||
// The following structures are present in the Restart Area.
|
||
//
|
||
|
||
//
|
||
// Generic Restart Table
|
||
//
|
||
// This is a generic table definition for the purpose of describing one
|
||
// of the three table structures used at Restart: the Open Attribute Table,
|
||
// the Dirty Pages Table, and the Transaction Table. This simple structure
|
||
// allows for common initialization and free list management. Allocation
|
||
// and Deallocation and lookup by index are extremely fast, while lookup
|
||
// by value (only performed in the Dirty Pages Table during Restart) is
|
||
// a little slower. I.e., all accesses to these tables during normal
|
||
// operation are extremely fast.
|
||
//
|
||
// If fast access to a table entry by value becomes an issue, then the
|
||
// table may be supplemented by an external Generic Table - it is probably
|
||
// not a good idea to make the Generic Table be part of the structure
|
||
// written to the Log File.
|
||
//
|
||
// Entries in a Restart Table should start with:
|
||
//
|
||
// ULONG AllocatedOrNextFree;
|
||
//
|
||
// An allocated entry will have the pattern RESTART_ENTRY_ALLOCATED
|
||
// in this field.
|
||
//
|
||
|
||
#define RESTART_ENTRY_ALLOCATED (0xFFFFFFFF)
|
||
|
||
typedef struct _RESTART_TABLE {
|
||
|
||
//
|
||
// Entry size, in bytes
|
||
//
|
||
|
||
USHORT EntrySize;
|
||
|
||
//
|
||
// Total number of entries in table
|
||
//
|
||
|
||
USHORT NumberEntries;
|
||
|
||
//
|
||
// Number entries that are allocated
|
||
//
|
||
|
||
USHORT NumberAllocated;
|
||
|
||
//
|
||
// Reserved for alignment
|
||
//
|
||
|
||
USHORT Reserved[3];
|
||
|
||
//
|
||
// Free goal - Offset after which entries should be freed to end of
|
||
// list, as opposed to front. At each checkpoint, the table may be
|
||
// truncated if there are enough free entries at the end of the list.
|
||
// Expressed as an offset from the start of this structure.
|
||
//
|
||
|
||
ULONG FreeGoal;
|
||
|
||
//
|
||
// First Free entry (head of list) and Last Free entry (used to deallocate
|
||
// beyond Free Goal). Expressed as an offset from the start of this
|
||
// structure.
|
||
//
|
||
|
||
ULONG FirstFree;
|
||
ULONG LastFree;
|
||
|
||
//
|
||
// The table itself starts here.
|
||
//
|
||
|
||
} RESTART_TABLE, *PRESTART_TABLE;
|
||
|
||
//
|
||
// Macro to get a pointer to an entry in a Restart Table, from the Table
|
||
// pointer and entry index. NOTE - Don't generate the index in a call
|
||
// to NtfsAllocateRestartTableIndex within this macro. The macro code
|
||
// tends to capture the Table pointer before generating the index. If the
|
||
// table needs to grow then the captured value may be invalid.
|
||
//
|
||
|
||
#define GetRestartEntryFromIndex(TBL,INDX) ( \
|
||
(PVOID)((PCHAR)(TBL)->Table + (INDX)) \
|
||
)
|
||
|
||
//
|
||
// Macro to get an index for an entry in a Restart Table, from the Table
|
||
// pointer and entry pointer.
|
||
//
|
||
|
||
#define GetIndexFromRestartEntry(TBL,ENTRY) ( \
|
||
(ULONG)((PCHAR)(ENTRY) - (PCHAR)(TBL)->Table) \
|
||
)
|
||
|
||
//
|
||
// Macro to see if an entry in a Restart Table is allocated.
|
||
//
|
||
|
||
#define IsRestartTableEntryAllocated(PTR) ( \
|
||
(BOOLEAN)(*(PULONG)(PTR) == RESTART_ENTRY_ALLOCATED) \
|
||
)
|
||
|
||
//
|
||
// Macro to retrieve the size of a Restart Table in bytes.
|
||
//
|
||
|
||
#define SizeOfRestartTable(TBL) ( \
|
||
(ULONG)(((TBL)->Table->NumberEntries * \
|
||
(TBL)->Table->EntrySize) + \
|
||
sizeof(RESTART_TABLE)) \
|
||
)
|
||
|
||
//
|
||
// Macro to see if Restart Table is empty. It is empty if the
|
||
// number allocated is zero.
|
||
//
|
||
|
||
#define IsRestartTableEmpty(TBL) (!(TBL)->Table->NumberAllocated)
|
||
|
||
//
|
||
// Macro to see if an index is within the currently allocated size
|
||
// for that table.
|
||
//
|
||
|
||
#define IsRestartIndexWithinTable(TBL,INDX) ( \
|
||
(BOOLEAN)((INDX) < SizeOfRestartTable(TBL)) \
|
||
)
|
||
|
||
//
|
||
// Macros to acquire and release a Restart Table.
|
||
//
|
||
|
||
#define NtfsAcquireExclusiveRestartTable(TBL,WAIT) { \
|
||
ExAcquireResourceExclusiveLite( &(TBL)->Resource,(WAIT)); \
|
||
}
|
||
|
||
#define NtfsAcquireSharedStartExRestartTable(TBL,WAIT) { \
|
||
ExAcquireSharedStarveExclusive( &(TBL)->Resource,(WAIT)); \
|
||
}
|
||
|
||
#define NtfsAcquireSharedRestartTable(TBL,WAIT) { \
|
||
ExAcquireResourceSharedLite( &(TBL)->Resource,(WAIT)); \
|
||
}
|
||
|
||
#define NtfsReleaseRestartTable(TBL) { \
|
||
ExReleaseResourceLite(&(TBL)->Resource); \
|
||
}
|
||
|
||
//
|
||
// Define some tuning parameters to keep the restart tables a
|
||
// reasonable size.
|
||
//
|
||
|
||
#define INITIAL_NUMBER_TRANSACTIONS (5)
|
||
#define HIGHWATER_TRANSACTION_COUNT (10)
|
||
#define INITIAL_NUMBER_ATTRIBUTES (8)
|
||
#define HIGHWATER_ATTRIBUTE_COUNT (16)
|
||
|
||
//
|
||
// Attribute Name Entry. This is a simple structure used to store
|
||
// all of the attribute names for the Open Attribute Table during
|
||
// checkpoint processing. The Attribute Names record written to the log
|
||
// is a series of Attribute Name Entries terminated by an entry with
|
||
// Index == NameLength == 0. The end of the table may be tested for by
|
||
// looking for either of these fields to be 0, as 0 is otherwise invalid
|
||
// for both.
|
||
//
|
||
// Note that the size of this structure is equal to the overhead for storing
|
||
// an attribute name in the table, including the UNICODE_NULL.
|
||
//
|
||
|
||
typedef struct _ATTRIBUTE_NAME_ENTRY {
|
||
|
||
//
|
||
// Index for Attibute with this name in the Open Attribute Table.
|
||
//
|
||
|
||
USHORT Index;
|
||
|
||
//
|
||
// Length of attribute name to follow in bytes, including a terminating
|
||
// UNICODE_NULL.
|
||
//
|
||
|
||
USHORT NameLength;
|
||
|
||
//
|
||
// Start of attribute name
|
||
//
|
||
|
||
WCHAR Name[1];
|
||
|
||
} ATTRIBUTE_NAME_ENTRY, *PATTRIBUTE_NAME_ENTRY;
|
||
|
||
//
|
||
// Open Attribute Table. This is the on-disk structure for version 0.
|
||
//
|
||
// One entry exists in the Open Attribute Table for each nonresident
|
||
// attribute of each file that is open with modify access.
|
||
//
|
||
// This table is initialized at Restart to the maximum of
|
||
// DEFAULT_ATTRIBUTE_TABLE_SIZE or the size of the table in the log file.
|
||
// It is maintained in the running system.
|
||
//
|
||
|
||
#pragma pack(4)
|
||
|
||
typedef struct _OPEN_ATTRIBUTE_ENTRY_V0 {
|
||
|
||
//
|
||
// Entry is allocated if this field contains RESTART_ENTRY_ALLOCATED.
|
||
// Otherwise, it is a free link.
|
||
//
|
||
|
||
ULONG AllocatedOrNextFree;
|
||
|
||
//
|
||
// Placeholder for Scb in V0. We use it to point to the index
|
||
// in the in-memory structure.
|
||
//
|
||
|
||
ULONG OatIndex;
|
||
|
||
//
|
||
// File Reference of file containing attribute.
|
||
//
|
||
|
||
FILE_REFERENCE FileReference;
|
||
|
||
//
|
||
// Lsn of OpenNonresidentAttribute log record, to distinguish reuses
|
||
// of this open file record. Log records referring to this Open
|
||
// Attribute Entry Index, but with Lsns older than this field, can
|
||
// only occur when the attribute was subsequently deleted - these
|
||
// log records can be ignored.
|
||
//
|
||
|
||
LSN LsnOfOpenRecord;
|
||
|
||
//
|
||
// Flag to say if dirty pages seen for this attribute during dirty
|
||
// page scan.
|
||
//
|
||
|
||
BOOLEAN DirtyPagesSeen;
|
||
|
||
//
|
||
// Flag to indicate if the pointer in Overlay above is to an Scb or
|
||
// attribute name. It is only used during restart when cleaning up
|
||
// the open attribute table.
|
||
//
|
||
|
||
BOOLEAN AttributeNamePresent;
|
||
|
||
//
|
||
// Reserved for alignment
|
||
//
|
||
|
||
UCHAR Reserved[2];
|
||
|
||
//
|
||
// The following two fields identify the actual attribute
|
||
// with respect to its file. We identify the attribute by
|
||
// its type code and name. When the Restart Area is written,
|
||
// all of the names for all of the open attributes are temporarily
|
||
// copied to the end of the Restart Area.
|
||
// The name is not used on disk but must be a 64-bit value.
|
||
//
|
||
|
||
ATTRIBUTE_TYPE_CODE AttributeTypeCode;
|
||
LONGLONG AttributeName;
|
||
|
||
//
|
||
// This field is only relevant to indices, i.e., if AttributeTypeCode
|
||
// above is $INDEX_ALLOCATION.
|
||
//
|
||
|
||
ULONG BytesPerIndexBuffer;
|
||
|
||
} OPEN_ATTRIBUTE_ENTRY_V0, *POPEN_ATTRIBUTE_ENTRY_V0;
|
||
|
||
#pragma pack()
|
||
|
||
#define SIZEOF_OPEN_ATTRIBUTE_ENTRY_V0 ( \
|
||
FIELD_OFFSET( OPEN_ATTRIBUTE_ENTRY_V0, BytesPerIndexBuffer ) + 4 \
|
||
)
|
||
|
||
//
|
||
// Auxiliary OpenAttribute data. This is the data that doesn't need to be
|
||
// logged.
|
||
//
|
||
|
||
typedef struct OPEN_ATTRIBUTE_DATA {
|
||
|
||
//
|
||
// Queue of these structures attached to the Vcb.
|
||
// NOTE - This must be the first entry in this structure.
|
||
//
|
||
|
||
LIST_ENTRY Links;
|
||
|
||
//
|
||
// Index for this entry in the On-disk open attribute table.
|
||
//
|
||
|
||
ULONG OnDiskAttributeIndex;
|
||
|
||
BOOLEAN AttributeNamePresent;
|
||
|
||
//
|
||
// The following overlay either contains an optional pointer to an
|
||
// Attribute Name Entry from the Analysis Phase of Restart, or a
|
||
// pointer to an Scb once attributes have been open and in the normal
|
||
// running system.
|
||
//
|
||
// Specifically, after the Analysis Phase of Restart:
|
||
//
|
||
// AttributeName == NULL if there is no attribute name, or the
|
||
// attribute name was captured in the Attribute
|
||
// Names Dump in the last successful checkpoint.
|
||
// AttributeName != NULL if an OpenNonresidentAttribute log record
|
||
// was encountered, and an Attribute Name Entry
|
||
// was allocated at that time (and must be
|
||
// deallocated when no longer needed).
|
||
//
|
||
// Once the Nonresident Attributes have been opened during Restart,
|
||
// and in the running system, this is an Scb pointer.
|
||
//
|
||
|
||
union {
|
||
PWSTR AttributeName;
|
||
PSCB Scb;
|
||
} Overlay;
|
||
|
||
//
|
||
// Store the unicode string for the attribute name.
|
||
//
|
||
|
||
UNICODE_STRING AttributeName;
|
||
|
||
} OPEN_ATTRIBUTE_DATA, *POPEN_ATTRIBUTE_DATA;
|
||
|
||
//
|
||
// Open Attribute Table. This is the on-disk structure for version 1 and
|
||
// it is the version we always use in-memory.
|
||
//
|
||
// One entry exists in the Open Attribute Table for each nonresident
|
||
// attribute of each file that is open with modify access.
|
||
//
|
||
// This table is initialized at Restart to the maximum of
|
||
// DEFAULT_ATTRIBUTE_TABLE_SIZE or the size of the table in the log file.
|
||
// It is maintained in the running system.
|
||
//
|
||
|
||
typedef struct _OPEN_ATTRIBUTE_ENTRY {
|
||
|
||
//
|
||
// Entry is allocated if this field contains RESTART_ENTRY_ALLOCATED.
|
||
// Otherwise, it is a free link.
|
||
//
|
||
|
||
ULONG AllocatedOrNextFree;
|
||
|
||
//
|
||
// This field is only relevant to indices, i.e., if AttributeTypeCode
|
||
// above is $INDEX_ALLOCATION.
|
||
//
|
||
|
||
ULONG BytesPerIndexBuffer;
|
||
|
||
//
|
||
// The following two fields identify the actual attribute
|
||
// with respect to its file. We identify the attribute by
|
||
// its type code and name. When the Restart Area is written,
|
||
// all of the names for all of the open attributes are temporarily
|
||
// copied to the end of the Restart Area.
|
||
//
|
||
|
||
ATTRIBUTE_TYPE_CODE AttributeTypeCode;
|
||
|
||
//
|
||
// Flag to say if dirty pages seen for this attribute during dirty
|
||
// page scan.
|
||
//
|
||
|
||
BOOLEAN DirtyPagesSeen;
|
||
CHAR Unused[3];
|
||
|
||
//
|
||
// File Reference of file containing attribute.
|
||
//
|
||
|
||
FILE_REFERENCE FileReference;
|
||
|
||
//
|
||
// Lsn of OpenNonresidentAttribute log record, to distinguish reuses
|
||
// of this open file record. Log records referring to this Open
|
||
// Attribute Entry Index, but with Lsns older than this field, can
|
||
// only occur when the attribute was subsequently deleted - these
|
||
// log records can be ignored.
|
||
//
|
||
|
||
LSN LsnOfOpenRecord;
|
||
|
||
//
|
||
// Point to the OpenAttribute data.
|
||
//
|
||
|
||
union {
|
||
|
||
POPEN_ATTRIBUTE_DATA OatData;
|
||
ULONGLONG Alignment;
|
||
};
|
||
|
||
} OPEN_ATTRIBUTE_ENTRY, *POPEN_ATTRIBUTE_ENTRY;
|
||
|
||
//
|
||
// VOID
|
||
// NtfsFreeAllOpenAttributeData (
|
||
// IN PVCB vCB
|
||
// );
|
||
//
|
||
|
||
#define NtfsFreeAllOpenAttributeData(V) { \
|
||
while (!IsListEmpty( &(V)->OpenAttributeData )) { \
|
||
POPEN_ATTRIBUTE_DATA _Next = CONTAINING_RECORD( (V)->OpenAttributeData.Flink, \
|
||
OPEN_ATTRIBUTE_DATA, \
|
||
Links ); \
|
||
NtfsFreeOpenAttributeData( _Next ); \
|
||
} \
|
||
}
|
||
|
||
//
|
||
// Dirty Pages Table - Version 0
|
||
//
|
||
// This entry is for restart version 0. It is inadvertently misaligned.
|
||
//
|
||
// One entry exists in the Dirty Pages Table for each page which is
|
||
// dirty at the time the Restart Area is written.
|
||
//
|
||
// This table is initialized at Restart to the maximum of
|
||
// DEFAULT_DIRTY_PAGES_TABLE_SIZE or the size of the table in the log file.
|
||
// It is *not* maintained in the running system.
|
||
//
|
||
|
||
#pragma pack(4)
|
||
|
||
typedef struct _DIRTY_PAGE_ENTRY_V0 {
|
||
|
||
//
|
||
// Entry is allocated if this field contains RESTART_ENTRY_ALLOCATED.
|
||
// Otherwise, it is a free link.
|
||
//
|
||
|
||
ULONG AllocatedOrNextFree;
|
||
|
||
//
|
||
// Target attribute index. This is the index into the Open Attribute
|
||
// Table to which this dirty page entry applies.
|
||
//
|
||
|
||
ULONG TargetAttribute;
|
||
|
||
//
|
||
// Length of transfer, in case this is the end of file, and we cannot
|
||
// write an entire page.
|
||
//
|
||
|
||
ULONG LengthOfTransfer;
|
||
|
||
//
|
||
// Number of Lcns in the array at end of this structure. See comment
|
||
// with this array.
|
||
//
|
||
|
||
ULONG LcnsToFollow;
|
||
|
||
//
|
||
// Reserved for alignment
|
||
//
|
||
|
||
ULONG Reserved;
|
||
|
||
//
|
||
// Vcn of dirty page.
|
||
//
|
||
|
||
VCN Vcn;
|
||
|
||
//
|
||
// OldestLsn for log record for which the update has not yet been
|
||
// written through to disk.
|
||
//
|
||
|
||
LSN OldestLsn;
|
||
|
||
//
|
||
// Run information. This is a variable-length array of LcnsToFollow
|
||
// entries, only the first of which is declared. Note that the writer
|
||
// always writes pages according to the physical page size on his
|
||
// machine, however whenever the log file is being read, no assumption
|
||
// is made about page size. This is to facilitate moving disks between
|
||
// systems with different page sizes.
|
||
//
|
||
|
||
LCN LcnsForPage[1];
|
||
|
||
} DIRTY_PAGE_ENTRY_V0, *PDIRTY_PAGE_ENTRY_V0;
|
||
|
||
#pragma pack()
|
||
|
||
//
|
||
// Dirty Pages Table - Version 1
|
||
//
|
||
// This version correctly aligns the 64-bit fields.
|
||
//
|
||
// One entry exists in the Dirty Pages Table for each page which is
|
||
// dirty at the time the Restart Area is written.
|
||
//
|
||
// This table is initialized at Restart to the maximum of
|
||
// DEFAULT_DIRTY_PAGES_TABLE_SIZE or the size of the table in the log file.
|
||
// It is *not* maintained in the running system.
|
||
//
|
||
|
||
typedef struct _DIRTY_PAGE_ENTRY {
|
||
|
||
//
|
||
// Entry is allocated if this field contains RESTART_ENTRY_ALLOCATED.
|
||
// Otherwise, it is a free link.
|
||
//
|
||
|
||
ULONG AllocatedOrNextFree;
|
||
|
||
//
|
||
// Target attribute index. This is the index into the Open Attribute
|
||
// Table to which this dirty page entry applies.
|
||
//
|
||
|
||
ULONG TargetAttribute;
|
||
|
||
//
|
||
// Length of transfer, in case this is the end of file, and we cannot
|
||
// write an entire page.
|
||
//
|
||
|
||
ULONG LengthOfTransfer;
|
||
|
||
//
|
||
// Number of Lcns in the array at end of this structure. See comment
|
||
// with this array.
|
||
//
|
||
|
||
ULONG LcnsToFollow;
|
||
|
||
//
|
||
// Vcn of dirty page.
|
||
//
|
||
|
||
VCN Vcn;
|
||
|
||
//
|
||
// OldestLsn for log record for which the update has not yet been
|
||
// written through to disk.
|
||
//
|
||
|
||
LSN OldestLsn;
|
||
|
||
//
|
||
// Run information. This is a variable-length array of LcnsToFollow
|
||
// entries, only the first of which is declared. Note that the writer
|
||
// always writes pages according to the physical page size on his
|
||
// machine, however whenever the log file is being read, no assumption
|
||
// is made about page size. This is to facilitate moving disks between
|
||
// systems with different page sizes.
|
||
//
|
||
|
||
LCN LcnsForPage[1];
|
||
|
||
} DIRTY_PAGE_ENTRY, *PDIRTY_PAGE_ENTRY;
|
||
|
||
//
|
||
// Transaction Table
|
||
//
|
||
// One transaction entry exists for each existing transaction at the time
|
||
// the Restart Area is written.
|
||
//
|
||
// Currently only local transactions are supported, and the transaction
|
||
// ID is simply used to index into this table.
|
||
//
|
||
// This table is initialized at Restart to the maximum of
|
||
// DEFAULT_TRANSACTION_TABLE_SIZE or the size of the table in the log file.
|
||
// It is maintained in the running system.
|
||
//
|
||
|
||
typedef struct _TRANSACTION_ENTRY {
|
||
|
||
//
|
||
// Entry is allocated if this field contains RESTART_ENTRY_ALLOCATED.
|
||
// Otherwise, it is a free link.
|
||
//
|
||
|
||
ULONG AllocatedOrNextFree;
|
||
|
||
//
|
||
// Transaction State
|
||
//
|
||
|
||
UCHAR TransactionState;
|
||
|
||
//
|
||
// Reserved for proper alignment
|
||
//
|
||
|
||
UCHAR Reserved[3];
|
||
|
||
//
|
||
// First Lsn for transaction. This tells us how far back in the log
|
||
// we may have to read to abort the transaction.
|
||
//
|
||
|
||
LSN FirstLsn;
|
||
|
||
//
|
||
// PreviousLsn written for the transaction and UndoNextLsn (next record
|
||
// which should be undone in the event of a rollback.
|
||
//
|
||
|
||
LSN PreviousLsn;
|
||
LSN UndoNextLsn;
|
||
|
||
//
|
||
// Number of of undo log records pending abort, and total undo size.
|
||
//
|
||
|
||
ULONG UndoRecords;
|
||
LONG UndoBytes;
|
||
|
||
} TRANSACTION_ENTRY, *PTRANSACTION_ENTRY;
|
||
|
||
//
|
||
// Restart record
|
||
//
|
||
// The Restart record used by NTFS is small, and it only describes where
|
||
// the above information has been written to the log. The above records
|
||
// may be considered logically part of NTFS's restart area.
|
||
//
|
||
|
||
typedef struct _RESTART_AREA {
|
||
|
||
//
|
||
// Version numbers of NTFS Restart Implementation
|
||
//
|
||
|
||
ULONG MajorVersion;
|
||
ULONG MinorVersion;
|
||
|
||
//
|
||
// Lsn of Start of Checkpoint. This is the Lsn at which the Analysis
|
||
// Phase of Restart must begin.
|
||
//
|
||
|
||
LSN StartOfCheckpoint;
|
||
|
||
//
|
||
// Lsns at which the four tables above plus the attribute names reside.
|
||
//
|
||
|
||
LSN OpenAttributeTableLsn;
|
||
LSN AttributeNamesLsn;
|
||
LSN DirtyPageTableLsn;
|
||
LSN TransactionTableLsn;
|
||
|
||
//
|
||
// Lengths of the above structures in bytes.
|
||
//
|
||
|
||
ULONG OpenAttributeTableLength;
|
||
ULONG AttributeNamesLength;
|
||
ULONG DirtyPageTableLength;
|
||
ULONG TransactionTableLength;
|
||
|
||
//
|
||
// Oldest Usn from which scan must occur to pickup all files which
|
||
// have not been through cleanup.
|
||
//
|
||
|
||
USN LowestOpenUsn;
|
||
|
||
LSN CurrentLsnAtMount;
|
||
ULONG BytesPerCluster;
|
||
|
||
ULONG Reserved;
|
||
|
||
//
|
||
// Keep some additional information about the Usn journal so we
|
||
// can reduce the amount of caching we do.
|
||
//
|
||
|
||
FILE_REFERENCE UsnJournalReference;
|
||
LONGLONG UsnCacheBias;
|
||
|
||
} RESTART_AREA, *PRESTART_AREA;
|
||
|
||
//
|
||
// This symbols is used to accept Restart Areas with or without the OldestUsn
|
||
//
|
||
|
||
#define SIZEOF_OLD_RESTART_AREA (FIELD_OFFSET( RESTART_AREA, LowestOpenUsn ))
|
||
|
||
|
||
//
|
||
// RECORD STRUCTURES USED BY LOG RECORDS
|
||
//
|
||
|
||
//
|
||
// Set new attribute sizes
|
||
//
|
||
|
||
typedef struct _NEW_ATTRIBUTE_SIZES {
|
||
|
||
LONGLONG AllocationSize;
|
||
LONGLONG ValidDataLength;
|
||
LONGLONG FileSize;
|
||
LONGLONG TotalAllocated;
|
||
|
||
} NEW_ATTRIBUTE_SIZES, *PNEW_ATTRIBUTE_SIZES;
|
||
|
||
#define SIZEOF_FULL_ATTRIBUTE_SIZES ( \
|
||
sizeof( NEW_ATTRIBUTE_SIZES ) \
|
||
)
|
||
|
||
#define SIZEOF_PARTIAL_ATTRIBUTE_SIZES ( \
|
||
FIELD_OFFSET( NEW_ATTRIBUTE_SIZES, TotalAllocated ) \
|
||
)
|
||
|
||
//
|
||
// Describe a bitmap range
|
||
//
|
||
|
||
typedef struct _BITMAP_RANGE {
|
||
|
||
ULONG BitMapOffset;
|
||
ULONG NumberOfBits;
|
||
|
||
} BITMAP_RANGE, *PBITMAP_RANGE;
|
||
|
||
//
|
||
// Describe a range of Lcns
|
||
//
|
||
|
||
typedef struct _LCN_RANGE {
|
||
|
||
LCN StartLcn;
|
||
LONGLONG Count;
|
||
|
||
} LCN_RANGE, *PLCN_RANGE;
|
||
|
||
#endif // _NTFSLOG_
|