Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

X File System (XFS)

The X File System (XFS) is a file system that originates from SGI but is used in various Linux distributions like RHEL. Some sources indicate that X was a a placeholder for a name that never given.

Overview

CharacteristicsDescription
Byte orderbig-endian
Date and time valuesnumber of seconds since January 1, 1970 00:00:00 UTC (POSIX epoch) and fraction of second in number of nanoseconds, or in bigtime (number of nanoseconds since December 13, 1901 20:45:52 UTC)
Character stringsUTF-8 or a narrow character (Single Byte Character (SBC) or Multi Byte Character (MBC)) stored using a system defined codepage

Terminology

Absolute and relative inode numbers

A relative inode number is an inode number used within a specific allocation group. An absolute inode number combines the allocation group number and the relative inode number.

number_of_relative_inode_number_bits = (
    allocation_group_size_log2 + number_of_inodes_per_block_log2
)
absolute_inode_number = (
    (allocation_group_number << number_of_relative_inode_number_bits) | relative_inode_number
)

File system block number

A relative block number is a block number relative to the start of an allocation group. A file system block number (xfs_fsblock_t) combines the allocation group number and the relative block number.

number_of_relative_block_number_bits = allocation_group_size_log2

file_system_block_number = (
    (allocation_group_number << number_of_relative_block_number_bits) | relative_block_number
)
file_offset = (allocation_group_block_number + relative_block_number) * block_size

The allocation group

An allocation group consists of:

  • a sector containing a superblock
  • a sector containing free block information
  • a sector containing inode tree information
  • a sector containing internal free list
  • blocks containing
    • root of the inode tree
    • root of the free space B+ tree
    • free list
    • inodes table

The superblock

The XFS superblock (xfs_sb_t) is (at least) 512 bytes in size and consists of:

OffsetSizeValueDescription
04"XFSB"Signature
44Block size, which is typicaly 4096 bytes (4 KiB) and can range from 512 to 65536 bytes
88Total number of blocks
168Number of real-time (device) blocks
248Number of real-time (device) extents
3216File system (or volume) identifier, which contains an UUID
488Journal block number, which contains a file system block number or 0 if the journal is stored on a separate device
568Root directory (absolute) inode number, which contains -1 (0xffffffffffffffff) if not set
648Real-time bitmap extents inode number, which contains -1 (0xffffffffffffffff) if not set
728Real-time bitmap summary inode number, which contains -1 (0xffffffffffffffff) if not set
804Real-time extent size, in number of blocks
844Allocation group size, in number of blocks
884Number of allocation groups
924Real-time bitmap size, in number of blocks
964Journal size, in number of blocks
1002Format version and feature flags
1022Sector size (in bytes)
1042Inode size (in bytes), which can range from 256 to 2048
1062Number of inodes per block
10812Volume label (or name)
1201Block size in log2, where value = ( 2 ^ value in log2 ) or 0 if value in log2 is 0
1211Sector size in log2, where value = ( 2 ^ value in log2 ) or 0 if value in log2 is 0
1221Inode size in log2, where value = ( 2 ^ value in log2 ) or 0 if value in log2 is 0
1231Number of inodes per block in log2, where value = ( 2 ^ value in log2 ) or 0 if value in log2 is 0
1241Allocation group size in log2, where value = ( 2 ^ value in log2 ) or 0 if value in log2 is 0
1251Number of real-time (device) extents in log2, where value = ( 2 ^ value in log2 ) or 0 if value in log2 is 0
1261Creation flag, which contains a value to indicate file system is being created
1271Inodes percentage, which contains the percentage of the maximum space of the volume to use for inodes
Only used in the first superblock
1288Number of inodes
1368Number of free inodes
1448Number of free data blocks
1528Number of free real-time extents
Only used if the XFS_SB_VERSION_QUOTABIT feature flag is set
1608User quota inode number
1688Group (or project) quota inode number
1762Quota flags
Common
1781Miscellaneous flags
17910Unknown (reserved or shared version number)
Only used if the XFS_SB_VERSION_ALIGNBIT feature flag is set
1804Inode chunk alignment size, in number of blocks
Common
1844Stripe (or RAID) unit size, in number of blocks
1884Stripe (or RAID) width, in number of blocks
1921Directory block size in log2, in number of blocks
1931Journal device sector size in log2
1942Journal device sector size (in bytes)
Only used if the XFS_SB_VERSION_LOGV2BIT feature flag is set
1964Journal device stripe or RAID unit size
Common
2004Secondary feature flags
2044Copy of secondary feature flags, which was introduced to work-around 64-bit alignment errors
If superblock format version >= 5 (XFS_SB_VERSION_5)
2084(Read-write) compatible feature flags
2124Read-only compatible feature flags
2164(Read-write) incompatible feature flags
2204Journal (read-write) incompatible feature flags
2244Checksum of the superblock
2284Unknown (Sparse inode chunk alignment in number of blocks)
2324Project quota inode number
2368Journal log sequence number (LSN) of the last superblock update
Only used if the XFS_SB_FEAT_INCOMPAT_META_UUID incompatible feature flag is set
24416Metadata identifier, which contains an UUID
Only used if the XFS_SB_FEAT_RO_COMPAT_RMAPBT incompatible feature flag is set
2608Real-time Reverse Mapping B+tree inode number
268244Unknown (empty values)

Note that the allocation group size and allocation group size in log2 are not necessarily equivalent.

Format version and feature flags

The 4 LSB contain the version the remaining bits are used to store feature flags.

VersionIdentifierIntroduced in
First generation
1XFS_SB_VERSION_1Introduced in Irix 5.3
2XFS_SB_VERSION_2Introduced in Irix 6.2, added extended attribute support
3XFS_SB_VERSION_3Introduced in Irix 6.2, added inode version 2 support
Second generation
4XFS_SB_VERSION_4Introduced in Irix 6.2, added directory version 2 support
Third generation
5XFS_SB_VERSION_5Introduced in Linux 3.10
ValueIdentifierDescription
Introduced in XFS_SB_VERSION_2
0x0010XFS_SB_VERSION_ATTRBITInodes support extended attributes
Introduced in XFS_SB_VERSION_3
0x0020XFS_SB_VERSION_NLINKBITInodes use a 32-bit number of links value
Introduced in XFS_SB_VERSION_4
0x0040XFS_SB_VERSION_QUOTABITQuotas enabled
0x0080XFS_SB_VERSION_ALIGNBITUse inode chunk alignment
0x0100XFS_SB_VERSION_DALIGNBITHas underlying stripe or RAID. The Stripe (or RAID) unit size and width values in the superblock should be set
0x0200XFS_SB_VERSION_SHAREDBITUnknown (set if reserved shared version is used)
0x0400XFS_SB_VERSION_LOGV2BITHas version 2 journaling logs
0x0800XFS_SB_VERSION_SECTORBITSector size is not 512 bytes
0x1000XFS_SB_VERSION_EXTFLGBITUnwritten extents are used, which should always be set
0x2000XFS_SB_VERSION_DIRV2BITVersion 2 directories are used
0x4000XFS_SB_VERSION_BORGBITUnknown (ASCII only case-insensitive)
0x8000XFS_SB_VERSION_MOREBITSBITSecondary feature flags are used

Secondary feature flags

ValueIdentifierDescription
0x00000001XFS_SB_VERSION2_RESERVED1BITUnknown (reserved)
0x00000002XFS_SB_VERSION2_LAZYSBCOUNTBITHas lazy global counters. Free space and inode values are only tracked in the primary superblock
0x00000004XFS_SB_VERSION2_RESERVED4BITUnknown (reserved)
0x00000008XFS_SB_VERSION2_ATTR2BITVersion 2 extended attributes are used
0x00000010XFS_SB_VERSION2_PARENTBITInodes have a parent pointer
0x00000080XFS_SB_VERSION2_PROJID32BITHas 32-bit project identifiers
0x00000100XFS_SB_VERSION2_CRCBITHas metadata checksums
0x00000200XFS_SB_VERSION2_FTYPEDirectory entries contain a file type

Miscellaneous flags

ValueIdentifierDescription
0x01XFS_SBF_READONLYRead-only file system

Quota flags

ValueIdentifierDescription
0x0001XFS_UQUOTA_ACCTUser quota accounting is enabled
0x0002XFS_UQUOTA_ENFDUser quotas are enforced
0x0004XFS_UQUOTA_CHKDUser quotas have been checked and updated on disk
0x0008XFS_PQUOTA_ACCTProject quota accounting is enabled
0x0010XFS_OQUOTA_ENFDOther (group/project) quotas are enforced
0x0020XFS_OQUOTA_CHKDOther (group/project) quotas have been checked
0x0040XFS_GQUOTA_ACCTGroup quota accounting is enabled
0x0080XFS_GQUOTA_ENFDGroup quotas are enforced
0x0100XFS_GQUOTA_CHKDGroup quotas have been checked
0x0200XFS_PQUOTA_ENFDProject quotas are enforced
0x0400XFS_PQUOTA_CHKDProject quotas have been checked

Compatible feature flags

Currently no compatible feature flags are defined.

Read-only compatible feature flags

ValueIdentifierDescription
0x00000001XFS_SB_FEAT_RO_COMPAT_FINOBTHas free inode btree
0x00000002XFS_SB_FEAT_RO_COMPAT_RMAPBTHas reverse map btree
0x00000004XFS_SB_FEAT_RO_COMPAT_REFLINKHas reflinked files
0x00000008XFS_SB_FEAT_RO_COMPAT_INOBTCNTHas inobt block counts

Incompatible feature flags

ValueIdentifierDescription
0x00000001XFS_SB_FEAT_INCOMPAT_FTYPEHas filetype in dirent
0x00000002XFS_SB_FEAT_INCOMPAT_SPINODESHas sparse inode chunks
0x00000004XFS_SB_FEAT_INCOMPAT_META_UUIDUse a metadata identifier
0x00000008XFS_SB_FEAT_INCOMPAT_BIGTIMEInode (v3) contains bigtime timestamps
0x00000010XFS_SB_FEAT_INCOMPAT_NEEDSREPAIRNeeds repair
0x00000020XFS_SB_FEAT_INCOMPAT_NREXT64Inode (v3) contains a 64-bit number of data extents and 32-bit number of (extended) attribute extent values
0x00000040XFS_SB_FEAT_INCOMPAT_EXCHRANGEHas exchangerange
0x00000080XFS_SB_FEAT_INCOMPAT_PARENTHas parent directory reference attributes
0x00000100XFS_SB_FEAT_INCOMPAT_METADIRHas metadata directory (tree)
0x00000200XFS_SB_FEAT_INCOMPAT_ZONEDHas zoned RT allocator
0x00000400XFS_SB_FEAT_INCOMPAT_ZONE_GAPSRTGs have LBA gaps

Journal incompatible feature flags

Currently no journal incompatible feature flags are defined.

Free block information

The free block information stores references:

  • the block offset B+ tree, that tracks the free space by block number
  • the block count B+ tree, that tracks the size of the free space block

The free block information (xfs_agf_t) is 64 or 224 bytes in size and consists of:

OffsetSizeValueDescription
04"XAGF"Signature
441Version
84Sequence number, which contains the allocation group number of the corresponding sector
124Unknown (Allocation group size), in number of blocks
164Free space counts B+ tree root block number
204Free space sizes B+ tree root block number
244Unknown (reserved)
284Free space counts B+ tree height/depth
324Free space sizes B+ tree height/depth
364Unknown (reserved)
404Index of the first "free list" block
444Index of the last "free list" block
484"Free list" size, in number of blocks
524Number of free blocks in the allocation group
564Longest contiguous free space in the allocation group, in number of blocks
Only used if the XFS_SB_VERSION2_LAZYSBCOUNTBIT feature flag is set
604Number of blocks used for the free space B+ trees
If superblock format version >= 5 (XFS_SB_VERSION_5)
6416Block type identifier, which contains an UUID that should correspond to sb_uuid or sb_meta_uuid
804Unknown (Size of the reverse mapping B+ tree in blocks)
844Unknown (Size of the reference count B+ tree in blocks)
884Reverse mapping B+ tree root block number, which contains a block number relative to the start of the allocation group
924Reference count B+ tree root block number, which contains a block number relative to the start of the allocation group
9614 x 8Unknown (reserved)
2088Log sequence number
2164Unknown (Checksum of the free sector)
2204Unknown (reserved)

Free list

A free list consists of:

  • As of version 5, free list header
  • Array of free block numbers

Free list header

The free list header is 36 bytes in size and consist of:

OffsetSizeValueDescription
04"AGFL"Signature
44Sequence number, which contains the allocation group number of the corresponding sector
816Block type identifier, which contains an UUID that should correspond to sb_uuid or sb_meta_uuid
248Log sequence number
324Checksum

TODO: describe sb_uuid or sb_meta_uuid

Inode information

The inode information (xfs_agi_t) is (at least) 512 bytes in size and consists of:

OffsetSizeValueDescription
04"XAGI"Signature
441Version
84Sequence number, which contains the allocation group number of the corresponding sector
124Unknown (Allocation group size), in number of blocks
164Number of inodes in the allocation group
204Inode tree root block number, which contains a block number relative to the start of the allocation group
244Inode tree height/depth
284Number of unused (free) inodes in the allocation group
324First inode number of the last allocated inode chunk, which contains an inode number relative to the allocation group
364-1 (0xffffffff)Unknown
4064 x 4Hash table of 32-bit unlinked (deleted) inode numbers that are still being referenced, which contains -1 (0xffffffff) if not set
If superblock format version >= 5 (XFS_SB_VERSION_5)
29616Block type identifier, which contains an UUID that should correspond to sb_uuid or sb_meta_uuid
3124Checksum
3164Unknown (padding)
3208Log sequence number
3284Free inode tree root block number, which contains a block number relative to the start of the allocation group
3324Free inode tree height/depth
3364Unknown
3404Unknown
344168Unknown (empty values)

B+ tree

XFS uses B+ trees to store various types of information. There are 2 different types of B+ trees, namely:

  • Free space block B+ tree
  • Inode tree
  • Reference count B+ tree

B+ tree block

A B+ tree block consists of:

  • B+ tree block header
  • Array of branch or leaf block records

B+ tree block header

B+ tree block header 32-bit

The B+ tree block header 32-bit (xfs_btree_sblock_t or xfs_btree_iblock_t) is 16 or 56 bytes of size and consist of:

OffsetSizeValueDescription
04Signature
42Level (or depth/height), which contains 0 for a leaf block
62Number of records
84Previous B+ tree block number, which is relative to the start of the allocation group or contains -1 (0xffffffff) if not set
124Next B+ tree block number, which is relative to the start of the allocation group or contains -1 (0xffffffff) if not set
If superblock format version >= 5 (XFS_SB_VERSION_5)
168Block number
248Log sequence number
3216Block type identifier, which contains an UUID that should correspond to sb_uuid or sb_meta_uuid
484Owner allocation group, which contains the allocation group the block is part of
524Checksum

B+ tree block header 64-bit

The B+ tree block header 64-bit (xfs_btree_lblock_t) is 24 or 72 bytes in size and consist of:

OffsetSizeValueDescription
04Signature
42Level (or depth/height), where 0 represents a leaf block
62Number of records
88Previous B+ tree block number, which is relative to the start of the allocation group or contains -1 (0xffffffffffffffff) if not set
168Next B+ tree block number, which is relative to the start of the allocation group or contains -1 (0xffffffffffffffff) if not set
If superblock format version >= 5 (XFS_SB_VERSION_5)
248Block number
328Log sequence number
4016Block type identifier, which contains an UUID that should correspond to sb_uuid or sb_meta_uuid
568Owner allocation group, which contains the allocation group the block is part of
644Checksum
6840Unknown (padding)

B+ tree block extended header

TODO: complete section

TODO: determine where this is defined, it seems to be represented in the examples.

B+ tree block header signatures

SignatureDescription
"AB3B"Free space block offset B+ tree (file system version 5)
"AB3C"Free space block count B+ tree (file system version 5)
"ABTB"Free space block offset B+ tree
"ABTC"Free space block count B+ tree
"FIB3"Free inode B+tree (file system version 5)
"FIBT"Free inode B+tree
"IAB3"(Allocated) inode B+tree (file system version 5)
"IABT"(Allocated) inode B+tree
"R3FC"Reference count B+ tree (file system version 5)

Free space B+ tree

TODO: complete section

Free space B+ tree branch node record

The free space B+ tree branch node record (xfs_alloc_ptr_t) is 4 bytes in size and consist of:

OffsetSizeValueDescription
04Unknown

Free space B+ tree leaf node record

The free space B+ tree leaf node record (xfs_alloc_key_t) is 8 bytes in size and consist of:

OffsetSizeValueDescription
04Unknown (ar_startblock)
44Unknown (ar_blockcount)

Inode tree

The inode tree uses the B+ tree block header 32-bit.

Inode tree branch node

The inode tree branch node consists of:

  • node header
  • array of inode tree branch node entry keys
  • array of inode tree branch node entry values

The number of key-value pairs is calculated as following:

number_of_key_value_pairs = node_records_data_size / 8
Inode tree branch node key

The inode tree branch node key (xfs_inobt_key_t) is 4 bytes in size and consist of:

OffsetSizeValueDescription
04Number of the first inode in the branch, which contains an inode number relative to the allocation group

Note that the inode number of the last key can be 0.

Inode tree branch node value

The inode tree branch node key is 4 bytes in size and consist of:

OffsetSizeValueDescription
04Block number of the inode tree sub node, which contains a block number relative to the start of the allocation group

Inode tree leaf node

The inode tree branch node consists of:

  • node header
  • array of inode tree leaf node entry records
Inode tree leaf node record

The inode tree leaf node record (xfs_inobt_rec_t) is 16 bytes in size and consist of:

OffsetSizeValueDescription
04Number of the first inode of the inode chunk, which contains an inode number relative to the allocation group
44Number of unused (free) inodes of the inode chunk
88Inode chunk allocation bitmap, which tracks which inodes of the inode chunk are unused (free)

The inode chunk is a group of 64 inodes. The file offset of the inode chunk is calculated as following:

file_offset = allocation_group_file_offset + (inode_number * inode_size)

Inode

The inode can be followed by:

  • data fork (descriptor)
    • device identifier (fork type is XFS_DINODE_FMT_DEV)
    • inline data fork (fork type is XFS_DINODE_FMT_LOCAL)
    • extents list data fork (fork type is XFS_DINODE_FMT_EXTENTS)
    • extents tree data fork (fork type is XFS_DINODE_FMT_BTREE)
  • optional (extended) attributes data fork (descriptor)
    • inline attributes fork (fork type is XFS_DINODE_FMT_LOCAL)
    • extents list attributes fork (fork type is XFS_DINODE_FMT_EXTENTS)
    • extents tree attributes fork (fork type is XFS_DINODE_FMT_BTREE)

Inode version 1

The inode version 1 (xfs_dinode_core_t) is 100 bytes in size and consist of:

OffsetSizeValueDescription
02"IN"Signature
22File mode, which contains file type and permissions
411Format version
51(Data) fork type
62Number of links
84Owner (or user) identifier (UID)
124Group identifier (GID)
16140Unknown (contains data in XFS_SB_VERSION_1)
302Flush counter, which contains a value that is incremented on flush
324(last) access time, which contains a POSIX timestamp in seconds
364(last) access time fraction of second, which contains number of nanoseconds
404(last) modification time, which contains a POSIX timestamp in seconds
444(last) modification time fraction of second, which contains number of nanoseconds
484(last) inode change time, which contains a POSIX timestamp in seconds
524(last) inode change time fraction of second, which contains number of nanoseconds
568(Data) size
648Number of (data) blocks
724Extent size
764Number of data extents
802Number of (extended) attributes extents, which can contain 0 if an attributes fork of type XFS_DINODE_FMT_EXTENTS is empty
821(Extended) attributes fork descriptor offset, which contains an offset (value x 8) relative to the end of the inode
831(Extended) attributes fork type
844Unknown (DMAPI event mask)
882Unknown (DMAPI state)
902Inode flags
924Generation number
Non-inode core field
964Unknown (next unlinked inode), which contains -1 (0xffffffff) if not set

Inode version 2

The inode version 2 (xfs_dinode_core_t) is 100 bytes in size and consist of:

OffsetSizeValueDescription
02"IN"Signature
22File mode, which contains file type and permissions
412Format version
51(Data) fork type
62Unknown
84Owner (or user) identifier (UID)
124Group identifier (GID)
164Number of links
202Project identifier
2280Unknown (padding)
302Flush counter, which contains a value that is incremented on flush
324(last) access time, which contains a POSIX timestamp in seconds
364(last) access time fraction of second, which contains number of nanoseconds
404(last) modification time, which contains a POSIX timestamp in seconds
444(last) modification time fraction of second, which contains number of nanoseconds
484(last) inode change time, which contains a POSIX timestamp in seconds
524(last) inode change time fraction of second, which contains number of nanoseconds
568(Data) size
648Number of (data) blocks
724Extent size
764Number of data extents
802Number of (extended) attributes extents, which can contain 0 if an attributes fork of type XFS_DINODE_FMT_EXTENTS is empty
821(Extended) attributes fork descriptor offset, which contains an offset (value x 8) relative to the end of the inode
831(Extended) attributes fork type
844Unknown (DMAPI event mask)
882Unknown (DMAPI state)
902Inode flags
924Generation number
Non-inode core field
964Unknown (next unlinked inode), which contains -1 (0xffffffff) if not set

Inode version 3

The inode version 3 (xfs_dinode_core_t) is 176 bytes in size and consist of:

OffsetSizeValueDescription
02"IN"Signature
22File mode, which contains file type and permissions
413Format version
51(Data) fork type
62Unknown
84Owner (or user) identifier (UID)
124Group identifier (GID)
164Number of links
202Project identifier lower 16-bit
222Project identifier upper 16-bit
If incompatible feature flag XFS_SB_FEAT_INCOMPAT_NREXT64 not is set
2480Unknown (padding)
If incompatible feature flag XFS_SB_FEAT_INCOMPAT_NREXT64 is set
248Number of data extents (64-bit)
Common
If incompatible feature flag XFS_SB_FEAT_INCOMPAT_BIGTIME not is set
324(last) access time, which contains a POSIX timestamp in seconds
364(last) access time fraction of second, which contains number of nanoseconds
404(last) modification time, which contains a POSIX timestamp in seconds
444(last) modification time fraction of second, which contains number of nanoseconds
484(last) inode change time, which contains a POSIX timestamp in seconds
524(last) inode change time fraction of second, which contains number of nanoseconds
If incompatible feature flag XFS_SB_FEAT_INCOMPAT_BIGTIME is set
328(last) access time, which contains a bigtime timestamp
408(last) modification time, which contains a bigtime timestamp
488(last) inode change time, which contains a bigtime timestamp
Common
568(Data) size
648Number of (data) blocks
724Extent size
If incompatible feature flag XFS_SB_FEAT_INCOMPAT_NREXT64 not is set
764Number of data extents
802Number of (extended) attributes extents, which can contain 0 if an attributes fork of type XFS_DINODE_FMT_EXTENTS is empty
If incompatible feature flag XFS_SB_FEAT_INCOMPAT_NREXT64 is set
764Number of (extended) attributes extents (32-bit), which can contain 0 if an attributes fork of type XFS_DINODE_FMT_EXTENTS is empty
802Unknown (padding)
Common
821(Extended) attributes fork descriptor offset, which contains an offset (value x 8) relative to the end of the inode
831(Extended) attributes fork type
844Unknown (DMAPI event mask)
882Unknown (DMAPI state)
902Inode flags
924Generation number
Pre version 3 non-inode core field
964Unknown (next unlinked inode), which contains -1 (0xffffffff) if not set
Introduced in version 3
1004Checksum
1048Change count, which contains the number of changes made to the inode
1128Log sequence number
1208Extended inode flags
1284Copy-on-write (COW) extent size
13212Unknown (padding)
If incompatible feature flag XFS_SB_FEAT_INCOMPAT_BIGTIME not is set
1444Creation time, which contains a POSIX timestamp in seconds
1484Creation time fraction of second, which contains number of nanoseconds
If incompatible feature flag XFS_SB_FEAT_INCOMPAT_BIGTIME is set
1448Creation time, which contains a bigtime timestamp
Common
1528Inode number, which contains an absolute inode number
16016Inode type identifier, which contains an UUID that should correspond to sb_uuid or sb_meta_uuid

File mode

ValueIdentifierDescription
Access other, bitmask: 0x0007 (S_IRWXO)
0x0001S_IXOTHX-access for other
0x0002S_IWOTHW-access for other
0x0004S_IROTHR-access for other
Access group, bitmask: 0x0038 (S_IRWXG)
0x0008S_IXGRPX-access for group
0x0010S_IWGRPW-access for group
0x0020S_IRGRPR-access for group
Access owner (or user), bitmask: 0x01c0 (S_IRWXU)
0x0040S_IXUSRX-access for owner (or user)
0x0080S_IWUSRW-access for owner (or user)
0x0100S_IRUSRR-access for owner (or user)
Other
0x0200S_ISTXTSticky bit
0x0400S_ISGIDSet group identifer (GID) on execution
0x0800S_ISUIDSet owner (or user) identifer (UID) on execution
Type of file, bitmask: 0xf000 (S_IFMT)
0x1000S_IFIFONamed pipe (FIFO)
0x2000S_IFCHRCharacter device
0x4000S_IFDIRDirectory
0x6000S_IFBLKBlock device
0x8000S_IFREGRegular file
0xa000S_IFLNKSymbolic link
0xc000S_IFSOCKSocket

Fork type

ValueIdentifierDescription
0XFS_DINODE_FMT_DEVDevice identifier is stored inline (in the inode)
1XFS_DINODE_FMT_LOCALData is stored inline (in the inode)
2XFS_DINODE_FMT_EXTENTSData is referrenced by extents stored in an extents list
3XFS_DINODE_FMT_BTREEData is referrence by extents stored in an extents tree
4XFS_DINODE_FMT_UUIDUnknown (currently not used)
5XFS_DINODE_FMT_RMAPData is referrence by a reverse mapping

Inode flags

ValueIdentifierDescription
0x0001XFS_DIFLAG_REALTIMEThe data is located on the real-time device
0x0002XFS_DIFLAG_PREALLOCThe extents have been preallocated
0x0004XFS_DIFLAG_NEWRTBMUses the new real-time bitmap format
0x0008XFS_DIFLAG_IMMUTABLEImmutable (cannot be modified)
0x0010XFS_DIFLAG_APPENDAppend only
0x0020XFS_DIFLAG_SYNCUse synchronous write
0x0040XFS_DIFLAG_NOATIMEDo not update access time (atime)
0x0080XFS_DIFLAG_NODUMPDo not "dump", which indicates that xfsdump should ignore the file
0x0100XFS_DIFLAG_RTINHERITSub directories inherit XFS_DIFLAG_REALTIME
0x0200XFS_DIFLAG_PROJINHERITSub directories inherit the project identifier
0x0400XFS_DIFLAG_NOSYMLINKSNo symbolic links can be created for sub directories
0x0800XFS_DIFLAG_EXTSIZEHas extent size
0x1000XFS_DIFLAG_EXTSZINHERITSub directories inherit extent size
0x2000XFS_DIFLAG_NODEFRAGDo not defragment
0x4000XFS_DIFLAG_FILESTREAMUnknown (Use filestream allocator)

Extents list

The extents list consists of:

Packed extent

The packed extent (xfs_bmbt_rec_t) is 128 bits of size and consist of:

OffsetSizeValueDescription
021 bitsNumber of blocks
2.452 bitsPhysical block number, which contains a file system block number
9.154 bitsLogical block number
15.71 bitUninitialized (unwritten) extent

Note that uninitialized extents are treated as sparse extents when read.

Extents tree

Extents tree root node

The root node of the extents tree is stored in the inode and equivalent to an extents tree branch node.

The number of key-value pairs is calculated as following:

number_of_key_value_pairs = (node_data_size - 4) / 16

Where “node data size” is (attributes_fork_descriptor_offset * 8) if the value is not 0, or otherwise the remaining inode block size.

Extents tree sub node block

An extents tree sub nodes is stored in a B+ tree block.

The extents tree uses the B+ tree block header 64-bit.

Extents tree sub node block header

The sub node block header (xfs_bmbt_block_t) is equivalent to B+ tree block header.

Extents tree sub node block header signatures
SignatureDescription
"BMA3"Extents tree sub node block ((file system version 5)
"BMAP"Extents tree sub node block

Extents tree branch node

The extents tree branch node record consists of:

  • node header
  • array of extents tree branch node entry keys
  • array of extents tree branch node entry values

The number of key-value pairs is calculated as following:

number_of_key_value_pairs = node_records_data_size / 16
Extents tree branch node header

The branch node header (xfs_bmdr_block_t) is 4 byte of size and consist of:

OffsetSizeValueDescription
02Node level
22Number of used key-value pairs in the node
Extents tree branch node entry key

The branch node entry key (xfs_bmbt_key_t) is 8 byte of size and consist of:

OffsetSizeValueDescription
08Data offset
Extents tree branch node entry value

The branch node entry value (xfs_bmbt_ptr_t or xfs_bmdr_ptr_t) is 8 byte of size and consist of:

OffsetSizeValueDescription
08Block number of the extents tree sub node, which contains a file system block number

Extents tree leaf block node

The extents tree leaf block node consists of:

Directory entries

Directories entries are stored in the data fork of a directory inode. The directory entries can be stored in multiple ways:

  • as a short-form directory table
  • as an extent-based directory list if the XFS_SB_VERSION_DIRV2BIT flag in the superblock is set
  • as an extent-based directory tree if the XFS_SB_VERSION_DIRV2BIT flag in the superblock is not set

Short-form directory table

The short-form directory table (xfs_dir_sf_t or xfs_dir2_sf_t) is stored in the inode (as inline data), where fork type is XFS_DINODE_FMT_LOCAL. The short-form directory table consist of:

  • Short-form directory table header
  • Short-form directory table entries

The XFS_SB_VERSION_DIRV2BIT flag in the superblock indicates if version 2 is used.

Short-form directory table header version 1

The short-form directory table header version 1 (xfs_dir_sf_hdr_t) is 9 bytes in size and consists of:

OffsetSizeValueDescription
08Parent inode number, which contains an absolute inode number
81Number of entries

Short-form directory table header version 2

The short-form directory table header version 2 (xfs_dir2_sf_hdr_t) is 6 or 10 bytes in size and consists of:

OffsetSizeValueDescription
01Number of 32-bit entries
11Number of 64-bit entries
24 or 8Parent inode number, which contains an absolute inode number

Note that if the inode numbers are stored as 32-bit values then number of 32-bit entries is set and number of 64-bit entries must be 0. If the inode numbers are stored as 64-bit values then number of 64-bit entries is set and number of 32-bit entries must be 0.

Short-form directory table entry version 1

The short-form directory table entry version 1 (xfs_dir_sf_entry_t) is of variable size and consists of:

OffsetSizeValueDescription
08Inode number, which contains an absolute inode number
91Name size, which does not include the end-of-string character
10...Name

Short-form directory table entry version 2

The short-form directory table entry version 2 (xfs_dir2_sf_entry_t) is of variable size and consists of:

OffsetSizeValueDescription
01Name size, which does not include the end-of-string character
12Unknown (offset, tag)
3...Name
Only present if XFS_SB_VERSION2_FTYPE is set
...1File type
Common
...4 or 8Inode number, which contains an absolute inode number

Note that file type seems to be present on format version even if XFS_SB_VERSION2_FTYPE is not set.

Directory list

A directory list (xfs_dir2_block_t) consist of one or more elements (block) that consist of:

  • a directory list element header
  • array of used and unused directory entries
  • hash values of the entries
  • a directory list element footer

Directory list element header

Directory list element header version 2

The directory list element header version 2 (xfs_dir2_data_hdr_t) is 16 bytes in size and consist of:

OffsetSizeValueDescription
04"XD2B" or "XD2D"Signature
44 x 3Array of free regions in the block
Directory list element header version 3

The directory list element header version 3 (xfs_dir3_data_hdr_t) is 64 bytes in size and consist of:

OffsetSizeValueDescription
Block header (xfs_dir3_blk_hdr_t)
04"XDB3" or "XDD3"Signature
44Checksum
88Block number
168Log sequence number
2416Block type identifier, which contains an UUID that should correspond to sb_uuid or sb_meta_uuid
408Owner inode number, which contains the absolute inode number the block is part of
 
484 x 3Array of free regions in the block
604Unknown (padding)
Directory list element header version signatures
SignatureDescription
"XD2B"Version 2 directory entries B+ tree (single block)
"XD2D"Version 2 directory entries B+ tree (multi block)
"XD2F"Version 2 directory free space B+ tree
"XDB3"Version 3 directory entries B+ tree (single block)
"XDD3"Version 3 directory entries B+ tree (multi block)
"XDF3"Version 3 directory free space B+ tree
Block free region version 2

The block free region version 2 (xfs_dir2_data_free_t) is 4 bytes in size and consist of:

OffsetSizeValueDescription
02Free region offset, which is relative to the start of the directory block
22Free region size

Directory list element entries

Directory list element entry version 2

The directory list element entry version 2 (xfs_dir2_data_entry_t) is of variable size and consists of:

OffsetSizeValueDescription
08Inode number, which contains an absolute inode number
81Name size, which does not include the end-of-string character
9...Name
Only present if XFS_SB_VERSION2_FTYPE is set
...1Unknown (ftype)
Common
......Unknown (8-byte alignment padding?)
...2Unknown (offset, tag)
Unused directory list element entry version 2

The unused directory list element entry version 2 (xfs_dir2_data_unused_t) is of variable size and consists of:

OffsetSizeValueDescription
020xffffSignature (free tag)
22Entry size, which contains the size of the unused entry including the size of the signature and entry size
42Unknown (padding)
...2Unknown (offset, tag)

Directory list element hash value

The directory list element hash value (xfs_dir_leaf_entry_t or xfs_dir2_leaf_entry_t) is 8 bytes of size and consists of:

OffsetSizeValueDescription
04Hash value of the name of the directory entry
44Entry offset, which is relative to the start of the block

The directory list element footer version 2 (xfs_dir2_block_tail_t) is 8 bytes in size and consists of:

OffsetSizeValueDescription
04Number of used entries
44Number of unused entries

Directory tree

The first block in the extents is the root block.

Directory tree branch node

A directory tree branch node consist of:

Directory tree branch node header

A directory tree branch node header is 16 bytes in size and consist of:

OffsetSizeValueDescription
012File system block header version 1 with signature 0xfebe
Block tree branch header version 1
122Number of entries
142Node level
Directory tree branch node entry

A directory tree branch node entry is 8 bytes in size and consists of:

OffsetSizeValueDescription
04Name hash
44Sub block number, which contains a block number relative to the start of the directory tree

Directory leaf branch node

A directory leaf branch node consist of:

  • a directory leaf branch node header
  • array of directory tree leaf node entries

Directory tree leaf node

A directory tree leaf node (xfs_dir_leafblock_t) consist of:

  • a directory tree leaf node header
  • array of directory tree leaf node entries
  • array of directory tree leaf node values
  • a directory tree leaf node footer
Directory tree leaf node header version 1

A directory tree leaf node header version 1 (xfs_dir_leaf_hdr_t) is 16 bytes in size and consists of:

OffsetSizeValueDescription
012File system block header version 1
Block tree leaf header version 1
122Number of entries
142Used (block) data size, in number of bytes
162Used data offset
181Flag to indicate block compaction is needed
191Unknown (padding)
204 x 3Array of free regions in the block

Note that a directory tree leaf node header version 2 (xfs_dir2_leaf_hdr_t) is equivalent to version 1.

Directory tree leaf node entry version 1

The directory tree leaf node entry (xfs_dir_leaf_entry_t) is 8 bytes in size and consist of:

OffsetSizeValueDescription
04Name hash
42Value offset, which contains an offset relative to the start of the directory block
61Name size, which does not include the end-of-string character
71Unknown (padding)

Note that a directory tree leaf node entry version 2 (xfs_dir2_leaf_entry_t) is equivalent to version 1.

Directory tree leaf node value

The directory tree leaf node value (xfs_dir_leaf_name_t) is of variable size and consist of:

OffsetSizeValueDescription
08Inode number, which contains an absolute inode number
8...Name

A directory tree leaf node footer version 1 (xfs_dir_leaf_tail_t) is 4 bytes in size and consists of:

OffsetSizeValueDescription
04Unknown (bestcount)

Note that a directory tree leaf node footer version 2 (xfs_dir2_leaf_tail_t) is equivalent to version 1.

Device identifier

Character and block devices identifiers are stored as inline data with fork type is XFS_DINODE_FMT_DEV.

The device identifier (xfs_dev_t) is 4 bytes in size and consists of:

OffsetSizeValueDescription
0.018 bitsMinor device number
2.214 bitsMajor device number

File content

XFS supports multiple ways to store file content:

  • inline data (fork type is XFS_DINODE_FMT_LOCAL)
  • extents defined by either an extents list (fork type is XFS_DINODE_FMT_EXTENTS) or an extent B+ tree (fork type is XFS_DINODE_FMT_BTREE)

Inline data

The file content data is stored in the inode data fork.

Extents

The file content data is stored in the block defined by the extents.

If the logical block numbers of successive extents are non-contiguous this means the file content data has an implicit sparse extent (or hole).

TODO: determine if the hole can be at the start or end of the file content data.

File system block B+ tree

The file system block B+ tree is a structure used to store the directory and attributes trees.

File system block header

File system block header version 1

If the superblock format version <= 4 the file system block header version 1 is used. The file system block header version 1 (xfs_da_blkinfo_t) is 12 bytes in size and consist of:

OffsetSizeValueDescription
04(Logical) block number of the next B+ tree block at the same level
44(Logical) block number of the previous B+ tree block at the same level
82Signature
102Unknown (padding)

Note that a file system block header version 2 is equivalent to version 1.

File system block header version 3

If the superblock format version >= 5 the file system block header version 3 is used. The file system block header version 3 (xfs_da3_blkinfo_t) is 56 bytes in size and consist of:

OffsetSizeValueDescription
04(Logical) block number of the next B+ tree block at the same level
44(Logical) block number of the previous B+ tree block at the same level
82Signature
102Unknown (padding)
124Checksum
168Block number
248Log sequence number
3216Block type identifier, which contains an UUID that should correspond to sb_uuid or sb_meta_uuid
488Owner inode number, which contains the absolute inode number the block is part of

File system block header signatures

SignatureIdentifierDescription
0x3beeXFS_ATTR_LEAF_MAGICAttributes tree leaf node (file system version 5)
0x3ebeXFS_DA3_NODE_MAGICDirectory or attributes tree branch node (file system version 5)
0xd2f1XFS_DIR2_LEAF1_MAGIC
0xd2ffXFS_DIR2_LEAFN_MAGIC
0xfbeeXFS_ATTR_LEAF_MAGICAttributes tree leaf node
0xfebeXFS_DA_NODE_MAGICDirectory or attributes tree branch node
0xfeebXFS_DIR_LEAF_MAGICDirectory tree leaf node

A symbolic link can be maximum 1024 bytes (XFS_SYMLINK_MAXLEN).

Extended attributes

Extended attributes are stored in the attributes fork of an inode. The extended attributes can be stored in multiple ways:

The start of the attributes fork can be determined using the attributes fork descriptor offset.

Short-form attributes table

If the inode attributes fork type is XFS_DINODE_FMT_LOCAL the extended attributes are stored in a short-form attributes table (xfs_attr_shortform) inline in the attribtes fork. The short-form attributes table consist of:

  • a short-form attributes table header
  • one or more short-form attributes table entries

The short-form attributes table header

The short-form attributes table header (xfs_attr_sf_hdr) is 4 bytes in size and consists of:

OffsetSizeValueDescription
02Data size, which contains the size of the short form attributes table data
21Number of entries
31Unknown (padding?)

Note that the size of the short-form attribute header deviates from [SGI18] based on analysis of test data.

The short-form attribute entry

The short-form attributes table entry (xfs_attr_sf_entry) is of variable size and consists of:

OffsetSizeValueDescription
01Name size
11Value data size
21Attribute flags
3...Name string, which contains an ASCII string without end-of-string character
......Value data

Attributes tree

If the inode attributes fork type is XFS_DINODE_FMT_BTREE the extended attributes are stored in an attributes tree. The attributes fork contains an extents tree.

The first block in the extents is the B+ tree root block.

Attributes tree branch node

An attributes tree branch node consist of:

Attributes tree branch node header

Attributes tree branch node header version 2

If the superblock format version <= 4 the attributes tree branch node header version 2 is used. The attributes tree branch node header version 2 (xfs_da_blkinfo_t) is 16 bytes in size and consist of:

OffsetSizeValueDescription
012File system block header version 1 with signature 0xfebe
Block tree branch header version 1
122Number of entries
142Node level
Attributes tree branch node header version 3

If the superblock format version >= 5 the attributes tree branch node header version 3 is used. The attributes tree branch node header version 3 (xfs_da3_blkinfo_t) is 64 bytes in size and consist of:

OffsetSizeValueDescription
056File system block header version 3 with signature 0x3ebe
Block tree branch header version 3
562Number of entries
582Node level
604Unknown (padding)
Attributes tree branch node block entry
OffsetSizeValueDescription
04Name hash
44Sub block number, which is relative to the start of the attributes tree

Attributes tree leaf node

If the inode attributes fork type is XFS_DINODE_FMT_EXTENTS the extended attributes are stored as attributes tree. The attributes fork contains an extents list.

Attributes tree (xfs_attr_leafblock_t or xfs_attr3_leafblock_t) consist of:

If more than one block is needed to store the extended attributes an attributes tree is used.

Note that since extended attributes were introduced in superblock format version 2 there are no version 1 structures.

Attributes tree leaf node header

Attributes tree leaf node header version 2

If the superblock format version <= 4 the attributes tree leaf node header version 2 is used. The attributes tree leaf node header version 2 (xfs_attr_leaf_hdr_t) is 32 bytes in size and consist of:

OffsetSizeValueDescription
012File system block header version 1 with signature 0xfbee
Block tree leaf header version 1
122Number of entries
142Used (block) data size, in number of bytes
162Used data offset
181Flag to indicate block compaction is needed
191Unknown (padding)
204 x 3Array of free regions in the block
Attributes tree leaf node header version 3

If the superblock format version >= 5 the attributes tree leaf node header version 3 is used. The attributes tree leaf node header version 3 (xfs_attr3_leaf_hdr_t) is 80 bytes in size and consist of:

OffsetSizeValueDescription
056File system block header version 3 with signature 0x3bee
Block tree leaf header version 3
562Number of entries
582Used (block) data size, in number of bytes
602Used data offset
621Flag to indicate block compaction is needed
631Unknown (padding)
644 x 3Array of free regions in the block
764Unknown (padding)

Attributes tree leaf node entry

The attributes tree leaf node entry (xfs_attr_leaf_entry_t) is 8 bytes in size and consist of:

OffsetSizeValueDescription
04Name hash
42Value offset, which is relative to the start of the leaf node
61Attribute flags
71Unknown (padding)

Attributes tree leaf node value

If the attributes tree leaf node entry flag XFS_ATTR_LOCAL is set the attribute value is stored as local attribute value otherwise as remote attribute value. The value data of remote attribute value are stored in a remote attribute value data block.

Local attribute value

The local attributes value (xfs_attr_leaf_name_local_t) is of variable size and consist of:

OffsetSizeValueDescription
02Value data size
21Name size
3...Name string, which contains an ASCII string without end-of-string character
Remote attribute value

The remote attributes value (xfs_attr_leaf_name_remote_t) is of variable size and consist of:

OffsetSizeValueDescription
04Value data block number, which is relative to the start of the attributes tree
44Value data size
81Name size
9...Name string, which contains an ASCII string without end-of-string character

The attribute flags

The attribute flags indicate the prefix (or namespace) of the attribute name.

ValueIdentifierName prefixDescription
0x00"user."The attribute is part of the user namespace
0x01XFS_ATTR_LOCALThe attribute value is contained within the current block, which should be ignored in an attributes table
0x02XFS_ATTR_ROOT"trusted."The attribute is part of the trusted namespace
0x04XFS_ATTR_SECURE"secure."The attribute is part of the secure namespace
0x08XFS_ATTR_PARENTThe attribute contains a parent directory reference, where the attribute name contains the file tentry name and the attribute value data a reference to the parent directory
0x80XFS_ATTR_INCOMPLETEThe attribute is being modified

Remote attribute value data block

If the superblock format version <= 4 the attribute value data is stored directly in remote attribute value data blocks.

If the superblock format version >= 5 each individual remote attribute value data block will start with a remote attribute value data block header version 3 followed by attribute value data.

The attributes extents contain the physical location of the individual remote attribute value data blocks.

Remote attribute value data block header version 3

The remote attribute value data block header (xfs_attr3_rmt_hdr) is 52 bytes in size and consist of:

OffsetSizeValueDescription
04"XARM"Signature
44Value data offset
84Value data size
124Checksum of the remote attribute value data block
1616Block type identifier, which contains an UUID that should correspond to sb_uuid or sb_meta_uuid
328Owner inode number, which contains the absolute inode number the block is part of
408Block number
488Log sequence number
Parent directory attribute value data

The parent directory attribute value data (xfs_parent_rec) is 12 bytes in size and consist of:

OffsetSizeValueDescription
08Parent directory inode number
84Parent directory generation number

References