| [[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..." |
| ---- |
| |