]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: add a realtime flag to the rmap update log redo items
authorDarrick J. Wong <djwong@kernel.org>
Tue, 7 Mar 2023 03:55:50 +0000 (19:55 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 22 Nov 2023 23:03:37 +0000 (15:03 -0800)
Extend the rmap update (RUI) log items with a new realtime flag that
indicates that the updates apply against the realtime rmapbt.  We'll
wire up the actual rmap code later.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/defer_item.c
libxfs/xfs_defer.c
libxfs/xfs_defer.h
libxfs/xfs_log_format.h
libxfs/xfs_refcount.c
libxfs/xfs_rmap.c
libxfs/xfs_rmap.h

index 5be7c40ba88e65d6f87f6da1678a7fef6c3ed359..25ed6a97f88fb893c1de9358460195dc91493770 100644 (file)
@@ -29,6 +29,7 @@
 #include "xfs_swapext.h"
 #include "defer_item.h"
 #include "xfs_btree.h"
+#include "xfs_rtgroup.h"
 
 /* Dummy defer item ops, since we don't do logging. */
 
@@ -324,11 +325,28 @@ xfs_rmap_defer_add(
        struct xfs_rmap_intent  *ri)
 {
        struct xfs_mount        *mp = tp->t_mountp;
+       enum xfs_defer_ops_type optype;
 
        trace_xfs_rmap_defer(mp, ri);
 
-       ri->ri_pag = xfs_perag_intent_get(mp, ri->ri_bmap.br_startblock);
-       xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
+       /*
+        * Deferred rmap updates for the realtime and data sections must use
+        * separate transactions to finish deferred work because updates to
+        * realtime metadata files can lock AGFs to allocate btree blocks and
+        * we don't want that mixing with the AGF locks taken to finish data
+        * section updates.
+        */
+       if (ri->ri_realtime) {
+               xfs_rgnumber_t  rgno;
+
+               rgno = xfs_rtb_to_rgno(mp, ri->ri_bmap.br_startblock);
+               ri->ri_rtg = xfs_rtgroup_get(mp, rgno);
+               optype = XFS_DEFER_OPS_TYPE_RMAP_RT;
+       } else {
+               ri->ri_pag = xfs_perag_intent_get(mp, ri->ri_bmap.br_startblock);
+               optype = XFS_DEFER_OPS_TYPE_RMAP;
+       }
+       xfs_defer_add(tp, optype, &ri->ri_list);
 }
 
 /* Cancel a deferred rmap update. */
@@ -392,6 +410,81 @@ const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
        .cancel_item    = xfs_rmap_update_cancel_item,
 };
 
+/* Sort rmap intents by rtgroup. */
+static int
+xfs_rtrmap_update_diff_items(
+       void                            *priv,
+       const struct list_head          *a,
+       const struct list_head          *b)
+{
+       struct xfs_rmap_intent          *ra = ri_entry(a);
+       struct xfs_rmap_intent          *rb = ri_entry(b);
+
+       return ra->ri_rtg->rtg_rgno - rb->ri_rtg->rtg_rgno;
+}
+
+static struct xfs_log_item *
+xfs_rtrmap_update_create_intent(
+       struct xfs_trans                *tp,
+       struct list_head                *items,
+       unsigned int                    count,
+       bool                            sort)
+{
+       struct xfs_mount                *mp = tp->t_mountp;
+
+       if (sort)
+               list_sort(mp, items, xfs_rtrmap_update_diff_items);
+       return NULL;
+}
+
+/* Cancel a deferred realtime rmap update. */
+STATIC void
+xfs_rtrmap_update_cancel_item(
+       struct list_head                *item)
+{
+       struct xfs_rmap_intent          *ri = ri_entry(item);
+
+       xfs_rtgroup_put(ri->ri_rtg);
+       kmem_cache_free(xfs_rmap_intent_cache, ri);
+}
+
+/* Process a deferred realtime rmap update. */
+STATIC int
+xfs_rtrmap_update_finish_item(
+       struct xfs_trans                *tp,
+       struct xfs_log_item             *done,
+       struct list_head                *item,
+       struct xfs_btree_cur            **state)
+{
+       struct xfs_rmap_intent          *ri = ri_entry(item);
+       int                             error;
+
+       error = xfs_rtrmap_finish_one(tp, ri, state);
+
+       xfs_rtrmap_update_cancel_item(item);
+       return error;
+}
+
+/* Clean up after calling xfs_rtrmap_finish_one. */
+STATIC void
+xfs_rtrmap_finish_one_cleanup(
+       struct xfs_trans        *tp,
+       struct xfs_btree_cur    *rcur,
+       int                     error)
+{
+       if (rcur)
+               xfs_btree_del_cursor(rcur, error);
+}
+
+const struct xfs_defer_op_type xfs_rtrmap_update_defer_type = {
+       .create_intent  = xfs_rtrmap_update_create_intent,
+       .abort_intent   = xfs_rmap_update_abort_intent,
+       .create_done    = xfs_rmap_update_create_done,
+       .finish_item    = xfs_rtrmap_update_finish_item,
+       .finish_cleanup = xfs_rtrmap_finish_one_cleanup,
+       .cancel_item    = xfs_rtrmap_update_cancel_item,
+};
+
 /* Reference Counting */
 
 /* Sort refcount intents by AG. */
index fb5e72640dbc58485671c191c40c659ce8927682..f32b122171e2550714422ecba79be2aab2ad5902 100644 (file)
@@ -241,6 +241,7 @@ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX] =
        [XFS_DEFER_OPS_TYPE_SWAPEXT]    = &xfs_swapext_defer_type,
 #ifdef CONFIG_XFS_RT
        [XFS_DEFER_OPS_TYPE_FREE_RT]    = &xfs_rtextent_free_defer_type,
+       [XFS_DEFER_OPS_TYPE_RMAP_RT]    = &xfs_rtrmap_update_defer_type,
 #endif
 };
 
index 93f899fd2f21d3216e03034ba74bbb2a7fe482c2..51a0028b5953979fc7fe5712e88baeb452a2c2c3 100644 (file)
@@ -23,6 +23,7 @@ enum xfs_defer_ops_type {
        XFS_DEFER_OPS_TYPE_BARRIER,
        XFS_DEFER_OPS_TYPE_SWAPEXT,
        XFS_DEFER_OPS_TYPE_FREE_RT,
+       XFS_DEFER_OPS_TYPE_RMAP_RT,
        XFS_DEFER_OPS_TYPE_MAX,
 };
 
@@ -78,6 +79,7 @@ struct xfs_defer_op_type {
 extern const struct xfs_defer_op_type xfs_bmap_update_defer_type;
 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_rtrmap_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;
index 1f5fe4a588eca2930f67eea100805a238de67248..ea4e88d665707bcbdb452bab55b66bd5ab833f2f 100644 (file)
@@ -250,6 +250,8 @@ typedef struct xfs_trans_header {
 #define        XFS_LI_SXD              0x1249  /* extent swap done */
 #define        XFS_LI_EFI_RT           0x124a  /* realtime extent free intent */
 #define        XFS_LI_EFD_RT           0x124b  /* realtime extent free done */
+#define        XFS_LI_RUI_RT           0x124c  /* realtime rmap update intent */
+#define        XFS_LI_RUD_RT           0x124d  /* realtime rmap update done */
 
 #define XFS_LI_TYPE_DESC \
        { XFS_LI_EFI,           "XFS_LI_EFI" }, \
@@ -271,7 +273,9 @@ typedef struct xfs_trans_header {
        { XFS_LI_SXI,           "XFS_LI_SXI" }, \
        { XFS_LI_SXD,           "XFS_LI_SXD" }, \
        { XFS_LI_EFI_RT,        "XFS_LI_EFI_RT" }, \
-       { XFS_LI_EFD_RT,        "XFS_LI_EFD_RT" }
+       { XFS_LI_EFD_RT,        "XFS_LI_EFD_RT" }, \
+       { XFS_LI_RUI_RT,        "XFS_LI_RUI_RT" }, \
+       { XFS_LI_RUD_RT,        "XFS_LI_RUD_RT" }
 
 /*
  * Inode Log Item Format definitions.
index 32d5aa6d499a9329000e4ae6d01072db6e1f6e9e..05d4177106c7560a218ad1b41c980a8ea54d1ff3 100644 (file)
@@ -1894,7 +1894,7 @@ xfs_refcount_alloc_cow_extent(
        __xfs_refcount_add(tp, XFS_REFCOUNT_ALLOC_COW, fsb, len);
 
        /* Add rmap entry */
-       xfs_rmap_alloc_extent(tp, fsb, len, XFS_RMAP_OWN_COW);
+       xfs_rmap_alloc_extent(tp, false, fsb, len, XFS_RMAP_OWN_COW);
 }
 
 /* Forget a CoW staging event in the refcount btree. */
@@ -1910,7 +1910,7 @@ xfs_refcount_free_cow_extent(
                return;
 
        /* Remove rmap entry */
-       xfs_rmap_free_extent(tp, fsb, len, XFS_RMAP_OWN_COW);
+       xfs_rmap_free_extent(tp, false, fsb, len, XFS_RMAP_OWN_COW);
        __xfs_refcount_add(tp, XFS_REFCOUNT_FREE_COW, fsb, len);
 }
 
index bf84b58dd36c935e24d04ea7440824b6e3e62ce3..099bbe2c8c4eae4561b2a1800702e3fe399836b0 100644 (file)
@@ -2681,6 +2681,21 @@ xfs_rmap_finish_one(
        return 0;
 }
 
+/*
+ * Process one of the deferred realtime rmap operations.  We pass back the
+ * btree cursor to reduce overhead.
+ */
+int
+xfs_rtrmap_finish_one(
+       struct xfs_trans                *tp,
+       struct xfs_rmap_intent          *ri,
+       struct xfs_btree_cur            **pcur)
+{
+       /* coming in a subsequent patch */
+       ASSERT(0);
+       return -EFSCORRUPTED;
+}
+
 /*
  * Don't defer an rmap if we aren't an rmap filesystem.
  */
@@ -2701,6 +2716,7 @@ __xfs_rmap_add(
        struct xfs_trans                *tp,
        enum xfs_rmap_intent_type       type,
        uint64_t                        owner,
+       bool                            isrt,
        int                             whichfork,
        struct xfs_bmbt_irec            *bmap)
 {
@@ -2712,6 +2728,7 @@ __xfs_rmap_add(
        ri->ri_owner = owner;
        ri->ri_whichfork = whichfork;
        ri->ri_bmap = *bmap;
+       ri->ri_realtime = isrt;
 
        xfs_rmap_defer_add(tp, ri);
 }
@@ -2725,6 +2742,7 @@ xfs_rmap_map_extent(
        struct xfs_bmbt_irec    *PREV)
 {
        enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
+       bool                    isrt = xfs_ifork_is_realtime(ip, whichfork);
 
        if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
                return;
@@ -2732,7 +2750,7 @@ xfs_rmap_map_extent(
        if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
                type = XFS_RMAP_MAP_SHARED;
 
-       __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
+       __xfs_rmap_add(tp, type, ip->i_ino, isrt, whichfork, PREV);
 }
 
 /* Unmap an extent out of a file. */
@@ -2744,6 +2762,7 @@ xfs_rmap_unmap_extent(
        struct xfs_bmbt_irec    *PREV)
 {
        enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
+       bool                    isrt = xfs_ifork_is_realtime(ip, whichfork);
 
        if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
                return;
@@ -2751,7 +2770,7 @@ xfs_rmap_unmap_extent(
        if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
                type = XFS_RMAP_UNMAP_SHARED;
 
-       __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
+       __xfs_rmap_add(tp, type, ip->i_ino, isrt, whichfork, PREV);
 }
 
 /*
@@ -2769,6 +2788,7 @@ xfs_rmap_convert_extent(
        struct xfs_bmbt_irec    *PREV)
 {
        enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
+       bool                    isrt = xfs_ifork_is_realtime(ip, whichfork);
 
        if (!xfs_rmap_update_is_needed(mp, whichfork))
                return;
@@ -2776,13 +2796,14 @@ xfs_rmap_convert_extent(
        if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
                type = XFS_RMAP_CONVERT_SHARED;
 
-       __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
+       __xfs_rmap_add(tp, type, ip->i_ino, isrt, whichfork, PREV);
 }
 
 /* Schedule the creation of an rmap for non-file data. */
 void
 xfs_rmap_alloc_extent(
        struct xfs_trans        *tp,
+       bool                    isrt,
        xfs_fsblock_t           fsbno,
        xfs_extlen_t            len,
        uint64_t                owner)
@@ -2797,13 +2818,14 @@ xfs_rmap_alloc_extent(
        bmap.br_startoff = 0;
        bmap.br_state = XFS_EXT_NORM;
 
-       __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
+       __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, isrt, XFS_DATA_FORK, &bmap);
 }
 
 /* Schedule the deletion of an rmap for non-file data. */
 void
 xfs_rmap_free_extent(
        struct xfs_trans        *tp,
+       bool                    isrt,
        xfs_fsblock_t           fsbno,
        xfs_extlen_t            len,
        uint64_t                owner)
@@ -2818,7 +2840,7 @@ xfs_rmap_free_extent(
        bmap.br_startoff = 0;
        bmap.br_state = XFS_EXT_NORM;
 
-       __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
+       __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, isrt, XFS_DATA_FORK, &bmap);
 }
 
 /* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
index ca38168c8709a19e8eafe49537040e3e4cb3c07d..5f30d0d2259311b4a45cc6debefa9f31efc24f28 100644 (file)
@@ -173,7 +173,11 @@ struct xfs_rmap_intent {
        int                                     ri_whichfork;
        uint64_t                                ri_owner;
        struct xfs_bmbt_irec                    ri_bmap;
-       struct xfs_perag                        *ri_pag;
+       union {
+               struct xfs_perag                *ri_pag;
+               struct xfs_rtgroup              *ri_rtg;
+       };
+       bool                                    ri_realtime;
 };
 
 /* functions for updating the rmapbt based on bmbt map/unmap operations */
@@ -184,11 +188,13 @@ void xfs_rmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip,
 void xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_trans *tp,
                struct xfs_inode *ip, int whichfork,
                struct xfs_bmbt_irec *imap);
-void xfs_rmap_alloc_extent(struct xfs_trans *tp, xfs_fsblock_t fsbno,
+void xfs_rmap_alloc_extent(struct xfs_trans *tp, bool isrt, xfs_fsblock_t fsbno,
                xfs_extlen_t len, uint64_t owner);
-void xfs_rmap_free_extent(struct xfs_trans *tp, xfs_fsblock_t fsbno,
+void xfs_rmap_free_extent(struct xfs_trans *tp, bool isrt, xfs_fsblock_t fsbno,
                xfs_extlen_t len, uint64_t owner);
 
+int xfs_rtrmap_finish_one(struct xfs_trans *tp, struct xfs_rmap_intent *ri,
+               struct xfs_btree_cur **pcur);
 int xfs_rmap_finish_one(struct xfs_trans *tp, struct xfs_rmap_intent *ri,
                struct xfs_btree_cur **pcur);
 int __xfs_rmap_finish_intent(struct xfs_btree_cur *rcur,