xfs: create traced helper to get extra perag references
authorDarrick J. Wong <djwong@kernel.org>
Wed, 12 Apr 2023 01:59:55 +0000 (18:59 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 12 Apr 2023 01:59:55 +0000 (18:59 -0700)
There are a few places in the XFS codebase where a caller has either an
active or a passive reference to a perag structure and wants to give
a passive reference to some other piece of code.  Btree cursor creation
and inode walks are good examples of this.  Replace the open-coded logic
with a helper to do this.

The new function adds a few safeguards -- it checks that there's at
least one reference to the perag structure passed in, and it records the
refcount bump in the ftrace information.  This makes it much easier to
debug perag refcounting problems.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/libxfs/xfs_ag.c
fs/xfs/libxfs/xfs_ag.h
fs/xfs/libxfs/xfs_alloc_btree.c
fs/xfs/libxfs/xfs_ialloc_btree.c
fs/xfs/libxfs/xfs_refcount_btree.c
fs/xfs/libxfs/xfs_rmap_btree.c
fs/xfs/xfs_iunlink_item.c
fs/xfs/xfs_iwalk.c
fs/xfs/xfs_trace.h

index ae45f54..2d89100 100644 (file)
@@ -81,6 +81,19 @@ xfs_perag_get_tag(
        return pag;
 }
 
+/* Get a passive reference to the given perag. */
+struct xfs_perag *
+xfs_perag_hold(
+       struct xfs_perag        *pag)
+{
+       ASSERT(atomic_read(&pag->pag_ref) > 0 ||
+              atomic_read(&pag->pag_active_ref) > 0);
+
+       trace_xfs_perag_hold(pag, _RET_IP_);
+       atomic_inc(&pag->pag_ref);
+       return pag;
+}
+
 void
 xfs_perag_put(
        struct xfs_perag        *pag)
index 5e18536..8092eab 100644 (file)
@@ -134,6 +134,7 @@ void xfs_free_perag(struct xfs_mount *mp);
 struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
 struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
                unsigned int tag);
+struct xfs_perag *xfs_perag_hold(struct xfs_perag *pag);
 void xfs_perag_put(struct xfs_perag *pag);
 
 /* Active AG references */
index 0f29c7b..8e8416c 100644 (file)
@@ -492,9 +492,7 @@ xfs_allocbt_init_common(
                cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtb_2);
        }
 
-       /* take a reference for the cursor */
-       atomic_inc(&pag->pag_ref);
-       cur->bc_ag.pag = pag;
+       cur->bc_ag.pag = xfs_perag_hold(pag);
 
        if (xfs_has_crc(mp))
                cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
index 1d2af50..ad6c521 100644 (file)
@@ -450,9 +450,7 @@ xfs_inobt_init_common(
        if (xfs_has_crc(mp))
                cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
 
-       /* take a reference for the cursor */
-       atomic_inc(&pag->pag_ref);
-       cur->bc_ag.pag = pag;
+       cur->bc_ag.pag = xfs_perag_hold(pag);
        return cur;
 }
 
index 749e837..03d2b01 100644 (file)
@@ -340,10 +340,7 @@ xfs_refcountbt_init_common(
 
        cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
 
-       /* take a reference for the cursor */
-       atomic_inc(&pag->pag_ref);
-       cur->bc_ag.pag = pag;
-
+       cur->bc_ag.pag = xfs_perag_hold(pag);
        cur->bc_ag.refc.nr_ops = 0;
        cur->bc_ag.refc.shape_changes = 0;
        cur->bc_ops = &xfs_refcountbt_ops;
index d328568..56d074b 100644 (file)
@@ -460,10 +460,7 @@ xfs_rmapbt_init_common(
        cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_rmap_2);
        cur->bc_ops = &xfs_rmapbt_ops;
 
-       /* take a reference for the cursor */
-       atomic_inc(&pag->pag_ref);
-       cur->bc_ag.pag = pag;
-
+       cur->bc_ag.pag = xfs_perag_hold(pag);
        return cur;
 }
 
index 43005ce..2ddccb1 100644 (file)
@@ -168,9 +168,7 @@ xfs_iunlink_log_inode(
        iup->ip = ip;
        iup->next_agino = next_agino;
        iup->old_agino = ip->i_next_unlinked;
-
-       atomic_inc(&pag->pag_ref);
-       iup->pag = pag;
+       iup->pag = xfs_perag_hold(pag);
 
        xfs_trans_add_item(tp, &iup->item);
        tp->t_flags |= XFS_TRANS_DIRTY;
index 21be93b..b3275e8 100644 (file)
@@ -667,11 +667,10 @@ xfs_iwalk_threaded(
                iwag->mp = mp;
 
                /*
-                * perag is being handed off to async work, so take another
+                * perag is being handed off to async work, so take a passive
                 * reference for the async work to release.
                 */
-               atomic_inc(&pag->pag_ref);
-               iwag->pag = pag;
+               iwag->pag = xfs_perag_hold(pag);
                iwag->iwalk_fn = iwalk_fn;
                iwag->data = data;
                iwag->startino = startino;
index 9c0006c..db09bb7 100644 (file)
@@ -190,6 +190,7 @@ DEFINE_EVENT(xfs_perag_class, name, \
        TP_ARGS(pag, caller_ip))
 DEFINE_PERAG_REF_EVENT(xfs_perag_get);
 DEFINE_PERAG_REF_EVENT(xfs_perag_get_tag);
+DEFINE_PERAG_REF_EVENT(xfs_perag_hold);
 DEFINE_PERAG_REF_EVENT(xfs_perag_put);
 DEFINE_PERAG_REF_EVENT(xfs_perag_grab);
 DEFINE_PERAG_REF_EVENT(xfs_perag_grab_tag);