]> 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>
Thu, 15 Aug 2024 18:56:38 +0000 (11:56 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 16 Aug 2024 21:57:39 +0000 (14:57 -0700)
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.h
libxfs/xfs_log_format.h
libxfs/xfs_refcount.c
libxfs/xfs_rmap.c
libxfs/xfs_rmap.h

index 170b9023cee99e0eea308426f85f35de797bb1a3..62907c6d0cc997c36989c86126f0f2c73afd4e78 100644 (file)
@@ -28,6 +28,7 @@
 #include "xfs_ag.h"
 #include "xfs_exchmaps.h"
 #include "defer_item.h"
+#include "xfs_rtgroup.h"
 
 /* Dummy defer item ops, since we don't do logging. */
 
@@ -328,8 +329,23 @@ xfs_rmap_defer_add(
 
        trace_xfs_rmap_defer(mp, ri);
 
-       ri->ri_pag = xfs_perag_intent_get(mp, ri->ri_bmap.br_startblock);
-       xfs_defer_add(tp, &ri->ri_list, &xfs_rmap_update_defer_type);
+       /*
+        * 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);
+               xfs_defer_add(tp, &ri->ri_list, &xfs_rtrmap_update_defer_type);
+       } else {
+               ri->ri_pag = xfs_perag_intent_get(mp, ri->ri_bmap.br_startblock);
+               xfs_defer_add(tp, &ri->ri_list, &xfs_rmap_update_defer_type);
+       }
 }
 
 /* Cancel a deferred rmap update. */
@@ -394,6 +410,82 @@ 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 = {
+       .name           = "rtrmap",
+       .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 */
 
 static inline struct xfs_refcount_intent *ci_entry(const struct list_head *e)
index ec51b8465e61cba15bbd99791e2596bc119b65a7..1e2477eaa5a844e1cc0e7338bb2a7da28a41e6d8 100644 (file)
@@ -69,6 +69,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 15dec19b6c32ad7aa182c378f3e0563075dfc6d7..a7e0e479454d3d5196abaea0094d0d8fc7b1492a 100644 (file)
@@ -250,6 +250,8 @@ typedef struct xfs_trans_header {
 #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_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_XMI,           "XFS_LI_XMI" }, \
        { XFS_LI_XMD,           "XFS_LI_XMD" }, \
        { 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 10309aa1ebb04ee6f33b5eb6afadbfaf24c60dbe..9ea93f391731207c9c8e6ff4d691ae7a0dffbcb4 100644 (file)
@@ -1831,7 +1831,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. */
@@ -1847,7 +1847,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 5ca842106c39913c2734d061fb756ca5167d905e..688341e402fbd56c8bc95d9eb86f089561abd32a 100644 (file)
@@ -2689,6 +2689,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.
  */
@@ -2709,6 +2724,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)
 {
@@ -2720,6 +2736,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);
 }
@@ -2733,6 +2750,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;
@@ -2740,7 +2758,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. */
@@ -2752,6 +2770,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;
@@ -2759,7 +2778,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);
 }
 
 /*
@@ -2777,6 +2796,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;
@@ -2784,13 +2804,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)
@@ -2805,13 +2826,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)
@@ -2826,7 +2848,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 eee2c7655274484f648d67ee07edd6d73dfd6caf..82f7505ca27cde1644360ad00c668b181d0b1ec0 100644 (file)
@@ -174,7 +174,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 */
@@ -185,11 +189,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,