]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xfs: give xfs_extfree_intent its own perag reference
authorDarrick J. Wong <djwong@kernel.org>
Wed, 12 Apr 2023 01:59:54 +0000 (18:59 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 28 Mar 2025 20:59:02 +0000 (21:59 +0100)
commit f6b384631e1e3482c24e35b53adbd3da50e47e8f upstream.

Give the xfs_extfree_intent an passive reference to the perag structure
data.  This reference will be used to enable scrub intent draining
functionality in subsequent patches.  The space being freed must already
be allocated, so we need to able to run even if the AG is being offlined
or shrunk.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com>
Acked-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_alloc.h
fs/xfs/xfs_extfree_item.c

index e44f3f5c6d27f075ae8b2af2e1ef2ebaaf3a32cd..c08265f19136898a4287c5204d5603eacac36727 100644 (file)
@@ -2511,6 +2511,7 @@ xfs_defer_agfl_block(
 
        trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
 
+       xfs_extent_free_get_group(mp, xefi);
        xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &xefi->xefi_list);
        return 0;
 }
@@ -2529,8 +2530,8 @@ __xfs_free_extent_later(
        bool                            skip_discard)
 {
        struct xfs_extent_free_item     *xefi;
-#ifdef DEBUG
        struct xfs_mount                *mp = tp->t_mountp;
+#ifdef DEBUG
        xfs_agnumber_t                  agno;
        xfs_agblock_t                   agbno;
 
@@ -2569,9 +2570,11 @@ __xfs_free_extent_later(
        } else {
                xefi->xefi_owner = XFS_RMAP_OWN_NULL;
        }
-       trace_xfs_bmap_free_defer(tp->t_mountp,
+       trace_xfs_bmap_free_defer(mp,
                        XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
                        XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len);
+
+       xfs_extent_free_get_group(mp, xefi);
        xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &xefi->xefi_list);
        return 0;
 }
index bbedb18651def7b4de9783af4363c5126551937c..2dd93d62150f5fb0c4782c6f72eb0c1b43a93233 100644 (file)
@@ -226,10 +226,14 @@ struct xfs_extent_free_item {
        uint64_t                xefi_owner;
        xfs_fsblock_t           xefi_startblock;/* starting fs block number */
        xfs_extlen_t            xefi_blockcount;/* number of blocks in extent */
+       struct xfs_perag        *xefi_pag;
        unsigned int            xefi_flags;
        enum xfs_ag_resv_type   xefi_agresv;
 };
 
+void xfs_extent_free_get_group(struct xfs_mount *mp,
+               struct xfs_extent_free_item *xefi);
+
 #define XFS_EFI_SKIP_DISCARD   (1U << 0) /* don't issue discard */
 #define XFS_EFI_ATTR_FORK      (1U << 1) /* freeing attr fork block */
 #define XFS_EFI_BMBT_BLOCK     (1U << 2) /* freeing bmap btree block */
index 3ed25c352269216eddf15c6382fccfa411eebe2d..be9f279a5c75bbf978f520bc1b6f7a5bb20ed4f3 100644 (file)
@@ -350,10 +350,7 @@ xfs_trans_free_extent(
        struct xfs_owner_info           oinfo = { };
        struct xfs_mount                *mp = tp->t_mountp;
        struct xfs_extent               *extp;
-       struct xfs_perag                *pag;
        uint                            next_extent;
-       xfs_agnumber_t                  agno = XFS_FSB_TO_AGNO(mp,
-                                                       xefi->xefi_startblock);
        xfs_agblock_t                   agbno = XFS_FSB_TO_AGBNO(mp,
                                                        xefi->xefi_startblock);
        int                             error;
@@ -364,14 +361,12 @@ xfs_trans_free_extent(
        if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK)
                oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
 
-       trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno,
-                       xefi->xefi_blockcount);
+       trace_xfs_bmap_free_deferred(tp->t_mountp, xefi->xefi_pag->pag_agno, 0,
+                       agbno, xefi->xefi_blockcount);
 
-       pag = xfs_perag_get(mp, agno);
-       error = __xfs_free_extent(tp, pag, agbno, xefi->xefi_blockcount,
-                       &oinfo, xefi->xefi_agresv,
+       error = __xfs_free_extent(tp, xefi->xefi_pag, agbno,
+                       xefi->xefi_blockcount, &oinfo, xefi->xefi_agresv,
                        xefi->xefi_flags & XFS_EFI_SKIP_DISCARD);
-       xfs_perag_put(pag);
 
        /*
         * Mark the transaction dirty, even on error. This ensures the
@@ -400,14 +395,13 @@ xfs_extent_free_diff_items(
        const struct list_head          *a,
        const struct list_head          *b)
 {
-       struct xfs_mount                *mp = priv;
        struct xfs_extent_free_item     *ra;
        struct xfs_extent_free_item     *rb;
 
        ra = container_of(a, struct xfs_extent_free_item, xefi_list);
        rb = container_of(b, struct xfs_extent_free_item, xefi_list);
-       return  XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) -
-               XFS_FSB_TO_AGNO(mp, rb->xefi_startblock);
+
+       return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno;
 }
 
 /* Log a free extent to the intent item. */
@@ -466,6 +460,26 @@ xfs_extent_free_create_done(
        return &xfs_trans_get_efd(tp, EFI_ITEM(intent), count)->efd_item;
 }
 
+/* Take a passive ref to the AG containing the space we're freeing. */
+void
+xfs_extent_free_get_group(
+       struct xfs_mount                *mp,
+       struct xfs_extent_free_item     *xefi)
+{
+       xfs_agnumber_t                  agno;
+
+       agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
+       xefi->xefi_pag = xfs_perag_get(mp, agno);
+}
+
+/* Release a passive AG ref after some freeing work. */
+static inline void
+xfs_extent_free_put_group(
+       struct xfs_extent_free_item     *xefi)
+{
+       xfs_perag_put(xefi->xefi_pag);
+}
+
 /* Process a free extent. */
 STATIC int
 xfs_extent_free_finish_item(
@@ -480,6 +494,8 @@ xfs_extent_free_finish_item(
        xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
 
        error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi);
+
+       xfs_extent_free_put_group(xefi);
        kmem_cache_free(xfs_extfree_item_cache, xefi);
        return error;
 }
@@ -500,6 +516,8 @@ xfs_extent_free_cancel_item(
        struct xfs_extent_free_item     *xefi;
 
        xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
+
+       xfs_extent_free_put_group(xefi);
        kmem_cache_free(xfs_extfree_item_cache, xefi);
 }
 
@@ -530,24 +548,21 @@ xfs_agfl_free_finish_item(
        struct xfs_extent               *extp;
        struct xfs_buf                  *agbp;
        int                             error;
-       xfs_agnumber_t                  agno;
        xfs_agblock_t                   agbno;
        uint                            next_extent;
-       struct xfs_perag                *pag;
 
        xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
        ASSERT(xefi->xefi_blockcount == 1);
-       agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
        agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);
        oinfo.oi_owner = xefi->xefi_owner;
 
-       trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, xefi->xefi_blockcount);
+       trace_xfs_agfl_free_deferred(mp, xefi->xefi_pag->pag_agno, 0, agbno,
+                       xefi->xefi_blockcount);
 
-       pag = xfs_perag_get(mp, agno);
-       error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
+       error = xfs_alloc_read_agf(xefi->xefi_pag, tp, 0, &agbp);
        if (!error)
-               error = xfs_free_agfl_block(tp, agno, agbno, agbp, &oinfo);
-       xfs_perag_put(pag);
+               error = xfs_free_agfl_block(tp, xefi->xefi_pag->pag_agno,
+                               agbno, agbp, &oinfo);
 
        /*
         * Mark the transaction dirty, even on error. This ensures the
@@ -566,6 +581,7 @@ xfs_agfl_free_finish_item(
        extp->ext_len = xefi->xefi_blockcount;
        efdp->efd_next_extent++;
 
+       xfs_extent_free_put_group(xefi);
        kmem_cache_free(xfs_extfree_item_cache, xefi);
        return error;
 }
@@ -639,7 +655,9 @@ xfs_efi_item_recover(
                fake.xefi_startblock = extp->ext_start;
                fake.xefi_blockcount = extp->ext_len;
 
+               xfs_extent_free_get_group(mp, &fake);
                error = xfs_trans_free_extent(tp, efdp, &fake);
+               xfs_extent_free_put_group(&fake);
                if (error == -EFSCORRUPTED)
                        XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
                                        extp, sizeof(*extp));