getfattr
command. To set or delete extended attributes, use the setfattr
command. ACLs control should use the getfacl
and setfacl
commands.
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 except shortform attributes (they are tightly packed). To determine the offset into the inode itself, add 100 (0x64) to di_forkoff * 8
.
di_aformat
is set to "local" and the attributes are stored in the inode's literal area starting at offset di_forkoff * 8
.
typedef struct xfs_attr_shortform { struct xfs_attr_sf_hdr { __be16 totsize; __u8 count; } hdr; struct xfs_attr_sf_entry { __uint8_t namelen; __uint8_t valuelen; __uint8_t flags; __uint8_t nameval[1]; } list[1]; } xfs_attr_shortform_t; typedef struct xfs_attr_sf_hdr xfs_attr_sf_hdr_t; typedef struct xfs_attr_sf_entry xfs_attr_sf_entry_t;
namelen
and valuelen
specify the size of the two byte arrays containing the name and value pairs. valuelen
is zero for extended attributes with no value.
nameval[]
is a single array where it's size is the sum of namelen
and valuelen
. The names and values are not null terminated on-disk. The value immediately follows the name in the array.
flags
specifies the namespace for the attribute (0 = "user"):
Flag
|
Description
|
---|---|
XFS_ATTR_ROOT
|
The attribute's namespace is "trusted".
|
XFS_ATTR_SECURE
|
The attribute's namespace is "secure".
|
# setfattr -n user.empty few_attr # setfattr -n trusted.trust -v val1 few_attr
xfs_db> inode <inode#> xfs_db> p core.magic = 0x494e core.mode = 0100644 ... core.naextents = 0 core.forkoff = 15 core.aformat = 1 (local) ... a.sfattr.hdr.totsize = 24 a.sfattr.hdr.count = 2 a.sfattr.list[0].namelen = 5 a.sfattr.list[0].valuelen = 0 a.sfattr.list[0].root = 0 a.sfattr.list[0].secure = 0 a.sfattr.list[0].name = "empty" a.sfattr.list[1].namelen = 5 a.sfattr.list[1].valuelen = 4 a.sfattr.list[1].root = 1 a.sfattr.list[1].secure = 0 a.sfattr.list[1].name = "trust" a.sfattr.list[1].value = "val1"
0xdc
.
di_forkoff
remains unchanged (and all those zeros in the dump above remain unused):
xfs_db> inode <inode#> xfs_db> p ... core.naextents = 1 core.forkoff = 15 core.aformat = 2 (extents) ... a.bmx[0] = [startoff,startblock,blockcount,extentflag] 0:[0,37534,1,0]
di_forkoff
change as attributes are added:
xfs_db> inode <inode#> xfs_db> p ... core.naextents = 0 core.forkoff = 15 core.aformat = 1 (local) ... a.sfattr.hdr.totsize = 17 a.sfattr.hdr.count = 1 a.sfattr.list[0].namelen = 10 a.sfattr.list[0].valuelen = 0 a.sfattr.list[0].root = 0 a.sfattr.list[0].secure = 0 a.sfattr.list[0].name = "empty_attr"
xfs_db> p ... core.naextents = 0 core.forkoff = 15 core.aformat = 1 (local) ... a.sfattr.hdr.totsize = 31 a.sfattr.hdr.count = 2 a.sfattr.list[0].namelen = 10 a.sfattr.list[0].valuelen = 0 a.sfattr.list[0].root = 0 a.sfattr.list[0].secure = 0 a.sfattr.list[0].name = "empty_attr" a.sfattr.list[1].namelen = 7 a.sfattr.list[1].valuelen = 4 a.sfattr.list[1].root = 1 a.sfattr.list[1].secure = 0 a.sfattr.list[1].name = "trust_a" a.sfattr.list[1].value = "val1"
xfs_db> p core.naextents = 0 core.forkoff = 10 core.aformat = 1 (local) ... a.sfattr.hdr.totsize = 69 a.sfattr.hdr.count = 4 a.sfattr.list[0].namelen = 10 a.sfattr.list[0].valuelen = 0 a.sfattr.list[0].root = 0 a.sfattr.list[0].secure = 0 a.sfattr.list[0].name = "empty_attr" a.sfattr.list[1].namelen = 7 a.sfattr.list[1].valuelen = 4 a.sfattr.list[1].root = 1 a.sfattr.list[1].secure = 0 a.sfattr.list[1].name = "trust_a" a.sfattr.list[1].value = "val1" a.sfattr.list[2].namelen = 6 a.sfattr.list[2].valuelen = 12 a.sfattr.list[2].root = 0 a.sfattr.list[2].secure = 0 a.sfattr.list[2].name = "second" a.sfattr.list[2].value = "second_value" a.sfattr.list[3].namelen = 6 a.sfattr.list[3].valuelen = 8 a.sfattr.list[3].root = 0 a.sfattr.list[3].secure = 1 a.sfattr.list[3].name = "policy" a.sfattr.list[3].value = "contents"