@@ -458,6 +458,16 @@ xfs_repair before it can be mounted.
Large file fork extent counts. This greatly expands the maximum number of
space mappings allowed in data and extended attribute file forks.
+| +XFS_SB_FEAT_INCOMPAT_EXCHRANGE+ |
+Atomic file mapping exchanges. The filesystem is capable of exchanging a range
+of mappings between two arbitrary ranges of a file's fork by using log intent
+items to track the progress of the high level exchange operation. In other
+words, the exchange operation can be restarted if the system goes down, which
+is necessary for userspace to commit of new file contents atomically. This
+flag has user-visible impacts, which is why it is a permanent incompat flag.
+See the section about xref:XMI_Log_Item[mapping exchange log intents] for more
+information.
+
|=====
*sb_features_log_incompat*::
@@ -217,6 +217,8 @@ magic number to distinguish themselves. Buffer data items only appear after
| +XFS_LI_BUD+ | 0x1245 | xref:BUD_Log_Item[File Block Mapping Update Done]
| +XFS_LI_ATTRI+ | 0x1246 | xref:ATTRI_Log_Item[Extended Attribute Update Intent]
| +XFS_LI_ATTRD+ | 0x1247 | xref:ATTRD_Log_Item[Extended Attribute Update Done]
+| +XFS_LI_XMI+ | 0x1248 | xref:XMI_Log_Item[File Mapping Exchange Intent]
+| +XFS_LI_XMD+ | 0x1249 | xref:XMD_Log_Item[File Mapping Exchange Done]
|=====
Note that all log items (except for transaction headers) MUST start with
@@ -649,6 +651,8 @@ file block mapping operation we want. The upper three bytes are flag bits.
| Value | Description
| +XFS_BMAP_EXTENT_ATTR_FORK+ | Extent is for the attribute fork.
| +XFS_BMAP_EXTENT_UNWRITTEN+ | Extent is unwritten.
+| +XFS_BMAP_EXTENT_REALTIME+ | Mapping applies to the data fork of a
+realtime file. This flag cannot be combined with +XFS_BMAP_EXTENT_ATTR_FORK+.
|=====
The ``file block mapping update intent'' operation comes first; it tells the
@@ -821,6 +825,125 @@ These regions contain the name and value components of the extended attribute
being updated, as needed. There are no magic numbers; each region contains the
data and nothing else.
+[[XMI_Log_Item]]
+=== File Mapping Exchange Intent
+
+These two log items work together to track the exchange of mapped extents
+between the forks of two files. Each operation requires a separate XMI/XMD
+pair. The log intent item has the following format:
+
+[source, c]
+----
+struct xfs_xmi_log_format {
+ uint16_t xmi_type;
+ uint16_t xmi_size;
+ uint32_t __pad;
+ uint64_t xmi_id;
+ uint64_t xmi_inode1;
+ uint64_t xmi_inode2;
+ uint32_t xmi_igen1;
+ uint32_t xmi_igen2;
+ uint64_t xmi_startoff1;
+ uint64_t xmi_startoff2;
+ uint64_t xmi_blockcount;
+ uint64_t xmi_flags;
+ int64_t xmi_isize1;
+ int64_t xmi_isize2;
+};
+----
+
+*xmi_type*::
+The signature of an XMI operation, 0x1248. This value is in host-endian order,
+not big-endian like the rest of XFS.
+
+*xmi_size*::
+Size of this log item. Should be 1.
+
+*__pad*::
+Must be zero.
+
+*xmi_id*::
+A 64-bit number that binds the corresponding XMD log item to this XMI log item.
+
+*xmi_inode1*::
+Inode number of the first file involved in the operation.
+
+*xmi_inode2*::
+Inode number of the second file involved in the operation.
+
+*xmi_igen1*::
+Generation number of the first file involved in the operation.
+
+*xmi_igen2*::
+Generation number of the second file involved in the operation.
+
+*xmi_startoff1*::
+Starting point within the first file, in units of filesystem blocks.
+
+*xmi_startoff2*::
+Starting point within the second file, in units of filesystem blocks.
+
+*xmi_blockcount*::
+The length to be exchanged, in units of filesystem blocks.
+
+*xmi_flags*::
+Behavioral changes to the operation, as follows:
+
+.File Extent Swap Intent Item Flags
+[options="header"]
+|=====
+| Value | Description
+| +XFS_EXCHMAPS_ATTR_FORK+ | Exchange extents between attribute forks.
+| +XFS_EXCHMAPS_SET_SIZES+ | Exchange the file sizes of the two files
+after the operation completes.
+| +XFS_EXCHMAPS_INO1_WRITTEN+ | Exchange the mappings of two files only
+if the file allocation units mapped to file1's range have been written.
+| +XFS_EXCHMAPS_CLEAR_INO1_REFLINK+ | Clear the reflink flag from inode1 after
+the operation.
+| +XFS_EXCHMAPS_CLEAR_INO2_REFLINK+ | Clear the reflink flag from inode2 after
+the operation.
+|=====
+
+*xmi_isize1*::
+The original size of the first file, in bytes. This is zero if the
++XFS_EXCHMAPS_SET_SIZES+ flag is not set.
+
+*xmi_isize2*::
+The original size of the second file, in bytes. This is zero if the
++XFS_EXCHMAPS_SET_SIZES+ flag is not set.
+
+[[XMD_Log_Item]]
+=== Completion of File Mapping Exchange
+
+The ``file mapping exchange done'' operation complements the ``file mapping
+exchange intent'' operation. This second operation indicates that the update
+actually happened, so that log recovery needn't replay the update. The XMD
+item and the actual updates are typically found in a new transaction following
+the transaction in which the XMI was logged. The completion has this format:
+
+[source, c]
+----
+struct xfs_xmd_log_format {
+ uint16_t xmd_type;
+ uint16_t xmd_size;
+ uint32_t __pad;
+ uint64_t xmd_xmi_id;
+};
+----
+
+*xmd_type*::
+The signature of an XMD operation, 0x1249. This value is in host-endian order,
+not big-endian like the rest of XFS.
+
+*xmd_size*::
+Size of this log item. Should be 1.
+
+*__pad*::
+Must be zero.
+
+*xmd_xmi_id*::
+A 64-bit number that binds the corresponding XMI log item to this XMD log item.
+
[[Inode_Log_Item]]
=== Inode Updates
@@ -73,6 +73,8 @@ are not aligned to blocks.
| +XFS_LI_BUD+ | 0x1245 | | xref:BUD_Log_Item[File Block Mapping Update Done]
| +XFS_LI_ATTRI+ | 0x1246 | | xref:ATTRI_Log_Item[Extended Attribute Update Intent]
| +XFS_LI_ATTRD+ | 0x1247 | | xref:ATTRD_Log_Item[Extended Attribute Update Done]
+| +XFS_LI_XMI+ | 0x1248 | | xref:XMI_Log_Item[File Mapping Exchange Intent]
+| +XFS_LI_XMD+ | 0x1249 | | xref:XMD_Log_Item[File Mapping Exchange Done]
|=====
= Theoretical Limits