]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: support logging EFIs for realtime extents
authorDarrick J. Wong <djwong@kernel.org>
Mon, 25 Nov 2024 21:14:23 +0000 (13:14 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 24 Dec 2024 02:01:30 +0000 (18:01 -0800)
Source kernel commit: 4c8900bbf106592ce647285e308abd2a7f080d88

Teach the EFI mechanism how to free realtime extents.  We're going to
need this to enforce proper ordering of operations when we enable
realtime rmap.

Declare a new log intent item type (XFS_LI_EFI_RT) and a separate defer
ops for rt extents.  This keeps the ondisk artifacts and processing code
completely separate between the rt and non-rt cases.  Hopefully this
will make it easier to debug filesystem problems.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/xfs_alloc.c
libxfs/xfs_alloc.h
libxfs/xfs_defer.c
libxfs/xfs_defer.h
libxfs/xfs_log_format.h

index c449285743534d22ea54b45af7e075febd26026f..9aebe7227a6148063a12c9e40b14e40d2b04d326 100644 (file)
@@ -2644,8 +2644,17 @@ xfs_defer_extent_free(
        ASSERT(!isnullstartblock(bno));
        ASSERT(!(free_flags & ~XFS_FREE_EXTENT_ALL_FLAGS));
 
-       if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbext(mp, bno, len)))
-               return -EFSCORRUPTED;
+       if (free_flags & XFS_FREE_EXTENT_REALTIME) {
+               if (type != XFS_AG_RESV_NONE) {
+                       ASSERT(type == XFS_AG_RESV_NONE);
+                       return -EFSCORRUPTED;
+               }
+               if (XFS_IS_CORRUPT(mp, !xfs_verify_rtbext(mp, bno, len)))
+                       return -EFSCORRUPTED;
+       } else {
+               if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbext(mp, bno, len)))
+                       return -EFSCORRUPTED;
+       }
 
        xefi = kmem_cache_zalloc(xfs_extfree_item_cache,
                               GFP_KERNEL | __GFP_NOFAIL);
@@ -2654,6 +2663,8 @@ xfs_defer_extent_free(
        xefi->xefi_agresv = type;
        if (free_flags & XFS_FREE_EXTENT_SKIP_DISCARD)
                xefi->xefi_flags |= XFS_EFI_SKIP_DISCARD;
+       if (free_flags & XFS_FREE_EXTENT_REALTIME)
+               xefi->xefi_flags |= XFS_EFI_REALTIME;
        if (oinfo) {
                ASSERT(oinfo->oi_offset == 0);
 
index efbde04fbbb15f1fa63a724002366b532ab2dbaa..50ef79a1ed41a1e4564bfe022715cb2195a7e62f 100644 (file)
@@ -237,7 +237,11 @@ int xfs_free_extent_later(struct xfs_trans *tp, xfs_fsblock_t bno,
 /* Don't issue a discard for the blocks freed. */
 #define XFS_FREE_EXTENT_SKIP_DISCARD   (1U << 0)
 
-#define XFS_FREE_EXTENT_ALL_FLAGS      (XFS_FREE_EXTENT_SKIP_DISCARD)
+/* Free blocks on the realtime device. */
+#define XFS_FREE_EXTENT_REALTIME       (1U << 1)
+
+#define XFS_FREE_EXTENT_ALL_FLAGS      (XFS_FREE_EXTENT_SKIP_DISCARD | \
+                                        XFS_FREE_EXTENT_REALTIME)
 
 /*
  * List of extents to be free "later".
@@ -257,6 +261,12 @@ struct xfs_extent_free_item {
 #define XFS_EFI_ATTR_FORK      (1U << 1) /* freeing attr fork block */
 #define XFS_EFI_BMBT_BLOCK     (1U << 2) /* freeing bmap btree block */
 #define XFS_EFI_CANCELLED      (1U << 3) /* dont actually free the space */
+#define XFS_EFI_REALTIME       (1U << 4) /* freeing realtime extent */
+
+static inline bool xfs_efi_is_realtime(const struct xfs_extent_free_item *xefi)
+{
+       return xefi->xefi_flags & XFS_EFI_REALTIME;
+}
 
 struct xfs_alloc_autoreap {
        struct xfs_defer_pending        *dfp;
index e3a608f64536ecfc775e944ab1998666ddf06f7c..8f6708c0f3bfcd22a775ceccac2b12b3a1669bfe 100644 (file)
@@ -839,6 +839,12 @@ xfs_defer_add(
 
        ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
 
+       if (!ops->finish_item) {
+               ASSERT(ops->finish_item != NULL);
+               xfs_force_shutdown(tp->t_mountp, SHUTDOWN_CORRUPT_INCORE);
+               return NULL;
+       }
+
        dfp = xfs_defer_find_last(tp, ops);
        if (!dfp || !xfs_defer_can_append(dfp, ops))
                dfp = xfs_defer_alloc(&tp->t_dfops, ops);
index 8b338031e487c4b98d127340109e25db34994950..ec51b8465e61cba15bbd99791e2596bc119b65a7 100644 (file)
@@ -71,6 +71,7 @@ extern const struct xfs_defer_op_type xfs_refcount_update_defer_type;
 extern const struct xfs_defer_op_type xfs_rmap_update_defer_type;
 extern const struct xfs_defer_op_type xfs_extent_free_defer_type;
 extern const struct xfs_defer_op_type xfs_agfl_free_defer_type;
+extern const struct xfs_defer_op_type xfs_rtextent_free_defer_type;
 extern const struct xfs_defer_op_type xfs_attr_defer_type;
 extern const struct xfs_defer_op_type xfs_exchmaps_defer_type;
 
index ace7384a275bfb7926952dde67d1e9c090b9adc7..15dec19b6c32ad7aa182c378f3e0563075dfc6d7 100644 (file)
@@ -248,6 +248,8 @@ typedef struct xfs_trans_header {
 #define        XFS_LI_ATTRD            0x1247  /* attr set/remove done */
 #define        XFS_LI_XMI              0x1248  /* mapping exchange intent */
 #define        XFS_LI_XMD              0x1249  /* mapping exchange done */
+#define        XFS_LI_EFI_RT           0x124a  /* realtime extent free intent */
+#define        XFS_LI_EFD_RT           0x124b  /* realtime extent free done */
 
 #define XFS_LI_TYPE_DESC \
        { XFS_LI_EFI,           "XFS_LI_EFI" }, \
@@ -267,7 +269,9 @@ typedef struct xfs_trans_header {
        { XFS_LI_ATTRI,         "XFS_LI_ATTRI" }, \
        { XFS_LI_ATTRD,         "XFS_LI_ATTRD" }, \
        { XFS_LI_XMI,           "XFS_LI_XMI" }, \
-       { XFS_LI_XMD,           "XFS_LI_XMD" }
+       { XFS_LI_XMD,           "XFS_LI_XMD" }, \
+       { XFS_LI_EFI_RT,        "XFS_LI_EFI_RT" }, \
+       { XFS_LI_EFD_RT,        "XFS_LI_EFD_RT" }
 
 /*
  * Inode Log Item Format definitions.