ReFS Reference

USN Journal

The USN (Update Sequence Number) Journal records every change to files and directories on the volume. ReFS uses the USN_RECORD_V3 format with 128-bit file IDs (NTFS uses the older USN_RECORD_V2 form with a 64-bit file reference). The journal is not active by default — it must be enabled with fsutil usn createjournal.

On-disk ReFS journal records are version 3. ReFS’s 128-bit file IDs require the USN_RECORD_V3 layout; fsutil usn queryjournal on ReFS reports Maximum record version supported : 3. Version 2 (NTFS’s 64-bit form) and version 4 (USN_RECORD_V4, the NTFS-only range-tracking / extent record — fsutil usn enablerangetracking refuses a ReFS volume with “A local NTFS volume is required for this operation”) do not occur on a ReFS journal (erratum E58). The parser decodes every record with the V3 field layout; it still accepts a V2 or V4 record if one is present (a non-ReFS journal, or crafted/corrupt input) but prints a one-time note that such records are parsed with V3 offsets and their fields are not validated — it does not silently refuse them.

USN_RECORD_V3 layout

OffsetSizeFieldDescription
0x004Record length (u32)Total record size = pad8(0x4C + UTF-16 name byte length); name-dominated, driver minimum 80 (0x50), observed 80–312 B across the corpus, no fixed ceiling — all records 8-byte aligned
0x042Major version (u16)3 on every ReFS record (the 128-bit File ID requires the V3 layout). The parser decodes with V3 offsets and tolerates a stray V2/V4 — a non-ReFS/corrupt input — with a one-time note rather than refusing it (see above)
0x062Minor version (u16)Always 0
0x0816File ID (u128)See 128-bit File ID structure below
0x1816Parent file ID (u128)Same format
0x288USN (u64)The record’s own USN = its virtual byte offset in the journal (monotonic, never reused; can far exceed the live $J stream size because $J is a sliding window). A file’s $SI+0x40 LastUsn points at this value for its most recent record.
0x308Timestamp (FILETIME)100 ns ticks since 1601-01-01
0x384Reason (u32)See Reason codes below
0x3C4Source info (u32)
0x404Security ID (u32)
0x444File attributes (u32)Current WIN32_FILE_ATTRIBUTE flags
0x482File name length (u16)In bytes
0x4A2File name offset (u16)Offset from record start
0x4CvarFile name (UTF-16LE)

128-bit File ID structure

ComponentSizeMeaning
Upper 8 bytesu64B+-tree table OID (directory’s Object Table OID)
Lower 8 bytesu64Sequential entry index within directory (monotonically increasing, never reused)

The upper 8 bytes identify which directory’s B+-tree contains this entry; the lower 8 bytes identify the specific entry within that tree. This makes a USN record directly resolvable to a B+-tree node location without a separate lookup table (see Object IDs & File IDs).

Reason codes

Reason codes are bitmask flags. A single record can combine multiple flags (e.g. 0x80000100 = FILE_CREATE + CLOSE).

Code (hex)NameDescription
0x00000001DATA_OVERWRITEDefault data stream content overwritten
0x00000002DATA_EXTENDDefault data stream extended
0x00000004DATA_TRUNCATIONDefault data stream truncated
0x00000010NAMED_DATA_OVERWRITENamed data stream (ADS) overwritten
0x00000020NAMED_DATA_EXTENDNamed data stream extended
0x00000040NAMED_DATA_TRUNCATIONNamed data stream truncated
0x00000100FILE_CREATEFile or directory creation
0x00000200FILE_DELETEFile deleted
0x00000400EA_CHANGEExtended attributes changed
0x00000800SECURITY_CHANGESecurity descriptor (ACL) changed
0x00001000RENAME_OLD_NAMESource name in rename operation
0x00002000RENAME_NEW_NAMETarget name in rename operation
0x00004000INDEXABLE_CHANGEContent indexing attribute changed
0x00008000BASIC_INFO_CHANGETimestamps or file attributes changed
0x00010000HARD_LINK_CHANGEHard link count changed
0x00020000COMPRESSION_CHANGECompression state changed
0x00040000ENCRYPTION_CHANGEEFS encryption state changed
0x00080000OBJECT_ID_CHANGEObject ID changed
0x00100000REPARSE_POINT_CHANGEReparse point set or removed
0x00200000STREAM_CHANGENamed data stream added or removed
0x00400000TRANSACTED_CHANGEChange within a TxF transaction
0x00800000INTEGRITY_CHANGEData integrity attribute changed
0x80000000CLOSEHandle closed (OR-ed with the final reason)

Forensic patterns

The reason-code combination, not just the individual flag, is the forensic signature of an operation:

OperationUSN signature
Sparse flag setBasic info change (0x8000); file attributes change from 0x20 to 0x220
EFS encrypt/decryptTransient EFS0.LOG in system directory (OID 0x701); reason 0x40000
$RECYCLE.BIN creationCreated on demand at first Explorer deletion
Junction creationReparse point change (0x100000) as a separate event
Symlink creationReparse change combined with create (0x100100)
ADS on symlinkNot possible — ADS cannot be written to symlink files on ReFS

Storage location

The Change Journal is stored as a file entry inside OID 0x520, the FS Metadata directory — the ReFS equivalent of NTFS $Extend (see System OIDs). When journaling is active a type 0x30 B+-tree row appears with key "Change Journal" (UTF-16LE). Fresh volumes have no such entry — it is created by RefsCreateUsnJournal and removed by RefsDeleteUsnJournal.

Change Journal file entry structure

The “Change Journal” filename entry in OID 0x520 carries a stream_count field (3 on v3.14) and a value of ~720 bytes on v3.14. The value holds three sub-records after the standard directory-entry header (the embedded sub-record markers are described in Directory Entries):

Sub-recordTypeOffsetContent
1Multi-instance (0x80000002)varies (scan from 0xA8)Data stream extents (likely $J stream)
2Multi-instance (0x80000002)0x148Data stream extents (likely $Max stream)
3Single-instance (0x80000001)0x288Journal metadata, 240 bytes (likely $USN_INFO)

The $J data stream contains the actual USN_RECORD_V3 entries as non-resident extent data. The $Max stream holds the journal size parameters, and is also surfaced as the type-0xF0 $LOGGED_UTILITY_STREAM attribute (single-instance marker 0x80000001) on the Change Journal file — not to be confused with the type-0x100 $EFS attribute. The single-instance sub-record at 0x288 contains organizational metadata including a creation timestamp and journal configuration.

Activation detection

Image stateOID 0x520 row countChange Journal entry
Fresh (never activated)1 (descriptor only)Absent
Active journaling3+Present (type 0x30, “Change Journal”)
DeactivatedVariesMay persist with zeroed extents

Tooling

USN Journal parsing is integrated into forefst.py (parsing + display). Available via forefst.py <image> usn:

ModeDescription
DefaultRecord listing with reason codes and file names
--csv [FILE]Export as CSV
--jsonMachine-readable JSON output
--statsReason code frequency distribution
--infoJournal metadata, extent layout, format reference

Cross-references

  • Directory Entries — per-file LastUsn at resident value offset 0x68; value+0x58 holds FileSize; UsnJournalId at 0x70
  • $STANDARD_INFORMATION — per-file LastUsn at $SI+0x40, UsnJournalId at $SI+0x48 ($SI+0x30 is an unpopulated slot)
  • System OIDs — OID 0x520 hosts the Change Journal file entry
  • Object IDs & File IDs — how the 128-bit File ID maps to a B+-tree location

Evidence

The USN_RECORD_V3 layout, the 128-bit File ID split (upper = table OID, lower = entry index), and the reason-code catalog are raw-disk decoded across the corpus. The record length range and the pad8 rule are measured corpus-wide (driver minimum 80 (0x50), observed 80–312 B, 8-byte aligned). The USN ↔ $SI+0x40 LastUsn link is both decompiled and disk-proven — every sampled file’s LastUsn resolved to a $J record naming that file. Journal activation, the OID 0x520 Change Journal entry, and the type-0xF0 $Max attribute are corroborated in the driver (RefsSetupUsnJournal, RefsWriteFcbUsnRecordToJournal) and verified on disk.