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 ae45f546ed86fdadf16d363b6315813a52284fd7..2d8910046ed9595512163997c734d59cead2e320 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 5e18536dfdcecce70572565cac837b20e59b4131..8092eaba977d4c004d1abbe04f80df9781d69c4b 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 0f29c7b1b39f32fc4fa87812a5fff553b2699f42..8e8416c14cec7bf7d6a067b05be94abbb457f881 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 1d2af50ac95b01d9637ee272cf890b717401935f..ad6c521f05ebd11ae2f5aea3b33e6489811b0a41 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 749e837de98d5ee8695f1ee028b89ad41b86f13f..03d2b01487a15e62a646979a6a2c8a78ec6c126b 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 d3285684bb5eb34e8371c1542b1cd0e07bf4e6d6..56d074b426609e3edf8e3abf975364b40831e581 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 43005ce8bd48a1f3c11193ba9a2a09ffed40f6e0..2ddccb172fa013a90e15f4ecba88f9020e2abdcd 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 21be93bf006dd60438abb181003759f09f6aff53..b3275e8d47b6057f8a2a776e6bddd3ec2f8a5600 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 9c0006c55fec3c869d2484106eba463c581a6fcd..db09bb77176584fae32d2307e82a8c24ae907f4d 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);