blob: bfe5eb9233344c9209357615aafddf3424f67dbd [file] [log] [blame]
[[Symbolic_Links]]
= Symbolic Links
Symbolic links to a file can be stored in one of two formats: ``local'' and
``extents''. The length of the symlink contents is always specified by the inode's
+di_size+ value.
[[Shortform_Symbolic_Links]]
== Short Form Symbolic Links
Symbolic links are stored with the ``local'' +di_format+ if the symbolic link can
fit within the inode's data fork. The link data is an array of characters
(+di_symlink+ array in the data fork union).
.Symbolic link short form layout
image::images/61.png[]
=== xfs_db Short Form Symbolic Link Example
A short symbolic link to a file is created:
----
xfs_db> inode <inode#>
xfs_db> p
core.magic = 0x494e
core.mode = 0120777
core.version = 1
core.format = 1 (local)
...
core.size = 12
core.nblocks = 0
core.extsize = 0
core.nextents = 0
...
u.symlink = "small_target"
----
Raw on-disk data with the link contents highlighted:
[subs="quotes"]
----
xfs_db> type text
xfs_db> p
00: 49 4e a1 ff 01 01 00 01 00 00 00 00 00 00 00 00 IN..............
10: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 01 ................
20: 44 be e1 c7 03 c4 d4 18 44 be el c7 03 c4 d4 18 D.......D.......
30: 44 be e1 c7 03 c4 d4 18 00 00 00 00 00 00 00 Oc D...............
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
50: 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: ff ff ff ff *73 6d 61 6c 6c 5f 74 61 72 67 65 74* ....small.target
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
----
[[Extent_Symbolic_Links]]
== Extent Symbolic Links
If the length of the symbolic link exceeds the space available in the inode's
data fork, the link is moved to a new filesystem block and the inode's
+di_format+ is changed to ``extents''. The location of the block(s) is specified
by the data fork's +di_bmx[]+ array. In the significant majority of cases, this
will be in one filesystem block as a symlink cannot be longer than 1024
characters.
On a v5 filesystem, the first block of each extent starts with the following
header structure:
[source, c]
----
struct xfs_dsymlink_hdr {
__be32 sl_magic;
__be32 sl_offset;
__be32 sl_bytes;
__be32 sl_crc;
uuid_t sl_uuid;
__be64 sl_owner;
__be64 sl_blkno;
__be64 sl_lsn;
};
-----
*sl_magic*::
Specifies the magic number for the symlink block: "XSLM" (0x58534c4d).
*sl_offset*::
Offset of the symbolic link target data, in bytes.
*sl_bytes*::
Number of bytes used to contain the link target data.
*sl_crc*::
Checksum of the symlink block.
*sl_uuid*::
The UUID of this block, which must match either +sb_uuid+ or +sb_meta_uuid+
depending on which features are set.
*sl_owner*::
The inode number that this symlink block belongs to.
*sl_blkno*::
Disk block number of this symlink.
*sl_lsn*::
Log sequence number of the last write to this block.
Filesystems formatted prior to v5 do not have this header in the remote block.
Symlink data begins immediately at offset zero.
.Symbolic link extent layout
image::images/62.png[]
=== xfs_db Symbolic Link Extent Example
A longer link is created (greater than 156 bytes):
----
xfs_db> inode <inode#>
xfs_db> p
core.magic = 0x494e
core.mode = 0120777
core.version = 1
core.format = 2 (extents)
...
core.size = 182
core.nblocks = 1
core.extsize = 0
core.nextents = 1
...
u.bmx[0] = [startoff,startblock,blockcount,extentflag] 0:[0,37530,1,0]
xfs_db> dblock 0
xfs_db> type symlink
xfs_db> p
"symlink contents..."
----