The attribute fork in the inode always contains the location of the extended attributes associated with the inode.
The location of the attribute fork in the inode's literal area (offset 100 to the end of the inode) is specified by the di_forkoff
value in the inode's core. If this value is zero, the inode does not contain any extended attributes. Non-zero, the byte offset into the literal area = di_forkoff
* 8, which also determines the 2048 byte maximum size for an inode. Attributes must be allocated on a 64-bit boundary on the disk. To access the extended attributes in code, use the XFS_DFORK_PTR
macro specifying XFS_ATTR_FORK
for the "which" parameter. Alternatively, the XFS_DFORK_APTR
macro can be used.
Which structure in the attribute fork is used depends on the di_aformat
value in the inode. It can be one of the following values:
XFS_DINODE_FMT_LOCAL
: The extended attributes are contained entirely within the inode. This is accessed by casting the value from XFS_DFORK_APTR
to xfs_attr_shortform_t*
.
XFS_DINODE_FMT_EXTENTS
: The attributes are located in another filesystem block, the inode contains an array of pointers to these filesystem blocks. They are accessed by casting the value from XFS_DFORK_APTR
to xfs_bmbt_rec_t*
.
XFS_DINODE_FMT_BTREE
: The extents for the attributes are contained in the leaves of a B+tree. The inode contains the root node of the tree and is accessed by casting the value from XFS_DFORK_APTR
to xfs_bmdr_block_t*
.
Detailed information on the layouts of extended attributes are covered in the Extended Attributes section (
Chapter 8, Extended Attributes) later on in this document.
4.4.1. Extended Attribute Versions
Extended attributes come in two versions: "attr1" or "attr2". The attribute version is specified by the XFS_SB_VERSION2_ATTR2BIT
flag in the sb_features2
field in the superblock. It determines how the inode's extra space is split between di_u
and di_a
forks which also determines how the di_forkoff
value is maintained in the inode's core.
With "attr1" attributes, the di_forkoff
is set to somewhere in the middle of the space between the core and end of the inode and never changes (which has the effect of artificially limiting the space for data information). As the data fork grows, when it gets to di_forkoff
, it will move the data to the level format level (ie. local > extent > btree). If very little space is used for either attributes or data, then a good portion of the available inode space is wasted with this version.
"Attr2" was introduced to maximum the utilisation of the inode's literal area. The di_forkoff
starts at the end of the inode and works its way to the data fork as attributes are added. Attr2 is highly recommended if extended attributes are used.
The following diagram compares the two versions: