2.2.2 Headers

Since the header is used to locate the log, updates to the headers cannot be made through the log. To provide power failure consistency, there are two headers in every VHDX file.

Each of the two headers is a 4-KB structure that is aligned to a 64-KB boundary.<1> One header is stored at offset 64 KB and the other at 128 KB. Only one header is considered current and in use at any point in time.


0


1


2


3


4


5


6


7


8


9

1
0


1


2


3


4


5


6


7


8


9

2
0


1


2


3


4


5


6


7


8


9

3
0


1

Signature

Checksum

SequenceNumber

...

FileWriteGuid

...

...

...

DataWriteGuid

...

...

...

LogGuid

...

...

...

LogVersion

Version

LogLength

LogOffset

...

Reserved (4016 bytes)

Signature (4 bytes): MUST be 0x68656164 which is a UTF-8 string representing "head".

Checksum (4 bytes): A CRC-32C hash over the entire 4-KB structure, with the Checksum field taking the value of zero during the computation of the checksum value.

SequenceNumber (8 bytes): A 64-bit unsigned integer.

A header is valid if the Signature and Checksum fields both validate correctly. A header is current if it is the only valid header or if it is valid and its SequenceNumber field is greater than the other header's SequenceNumber field. The implementation MUST only use data from the current header. If there is no current header, then the VHDX file is corrupt.

FileWriteGuid (16 bytes): Specifies a 128-bit unique identifier that identifies the file's contents. On every open of a VHDX file, an implementation MUST change this GUID to a new and unique identifier before the first modification is made to the file, including system and user metadata as well as log playback. The implementation can skip updating this field if the storage media on which the file is stored is read-only, or if the file is opened in read-only mode.

DataWriteGuid (16 bytes): Specifies a 128-bit unique identifier that identifies the contents of the user visible data. On every open of the VHDX file, an implementation MUST change this field to a new and unique identifier before the first modification is made to user-visible data. If the user of the virtual disk can observe the change through a virtual disk read, then the implementation MUST update this field.<2> This includes changing the system and user metadata, raw block data, or disk size, or any block state transitions that will result in a virtual disk sector read being different from a previous read. This does not include movement of blocks within a file, which changes only the physical layout of the file, not the virtual identity.

LogGuid (16 bytes): Specifies a 128-bit unique identifier used to determine the validity of log entries. If this field is zero, then the log is empty or has no valid entries and MUST not be replayed. Otherwise, only log entries that contain this identifier in their header are valid log entries. Upon open, the implementation MUST update this field to a new nonzero value before overwriting existing space within the log region.

LogVersion (2 bytes): Specifies the version of the log format used within the VHDX file. This field MUST be set to zero. If it is not, the implementation MUST NOT continue to process the file unless the LogGuid field is zero, indicating that there is no log to replay.

Version (2 bytes): Specifies the version of the VHDX format used within the VHDX file. This field MUST be set to 1. If it is not, an implementation MUST NOT attempt to process the file using the details from this format specification.

LogLength (4 bytes): A 32-bit unsigned integer. Specifies the size, in bytes of the log. This value MUST be a multiple of 1MB.

LogOffset (8 bytes): A 64-bit unsigned integer. Specifies the byte offset in the file of the log. This value MUST be a multiple of 1MB. The log MUST NOT overlap any other structures.

Reserved (4016 bytes): MUST be set to 0 and ignored.

The space between a 4-KB structure containing header data and a 64-KB alignment boundary for the header is reserved.