xfs: switch perag iteration from the for_each macros to a while based iterator
authorChristoph Hellwig <hch@lst.de>
Mon, 4 Nov 2024 04:18:39 +0000 (20:18 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 5 Nov 2024 21:38:28 +0000 (13:38 -0800)
The current for_each_perag* macros are a bit annoying in that they
require the caller to both provide an object and an index iterator, and
also somewhat obsfucate the underlying control flow mechanism.

Switch to open coded while loops using new xfs_perag_next{,_from,_range}
helpers that return the next pag structure to iterate on based on the
previous one or NULL for the loop start.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
17 files changed:
fs/xfs/libxfs/xfs_ag.h
fs/xfs/libxfs/xfs_sb.c
fs/xfs/libxfs/xfs_types.c
fs/xfs/scrub/bmap.c
fs/xfs/scrub/bmap_repair.c
fs/xfs/scrub/fscounters.c
fs/xfs/scrub/health.c
fs/xfs/scrub/inode_repair.c
fs/xfs/xfs_discard.c
fs/xfs/xfs_extent_busy.c
fs/xfs/xfs_fsmap.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_health.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_iwalk.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_reflink.c

index 69b934ad2c4aad6ee5a63ab9b913d6ce0f945bf9..80969682dc4746ef886ddd0eace4d2df797e114d 100644 (file)
@@ -208,6 +208,34 @@ xfs_perag_rele(
        xfs_group_rele(pag_group(pag));
 }
 
+static inline struct xfs_perag *
+xfs_perag_next_range(
+       struct xfs_mount        *mp,
+       struct xfs_perag        *pag,
+       xfs_agnumber_t          start_agno,
+       xfs_agnumber_t          end_agno)
+{
+       return to_perag(xfs_group_next_range(mp, pag ? pag_group(pag) : NULL,
+                       start_agno, end_agno, XG_TYPE_AG));
+}
+
+static inline struct xfs_perag *
+xfs_perag_next_from(
+       struct xfs_mount        *mp,
+       struct xfs_perag        *pag,
+       xfs_agnumber_t          start_agno)
+{
+       return xfs_perag_next_range(mp, pag, start_agno, mp->m_sb.sb_agcount - 1);
+}
+
+static inline struct xfs_perag *
+xfs_perag_next(
+       struct xfs_mount        *mp,
+       struct xfs_perag        *pag)
+{
+       return xfs_perag_next_from(mp, pag, 0);
+}
+
 /*
  * Per-ag geometry infomation and validation
  */
@@ -273,40 +301,6 @@ xfs_ag_contains_log(struct xfs_mount *mp, xfs_agnumber_t agno)
               agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
 }
 
-/*
- * Perag iteration APIs
- */
-static inline struct xfs_perag *
-xfs_perag_next(
-       struct xfs_perag        *pag,
-       xfs_agnumber_t          *agno,
-       xfs_agnumber_t          end_agno)
-{
-       struct xfs_mount        *mp = pag_mount(pag);
-
-       *agno = pag_agno(pag) + 1;
-       xfs_perag_rele(pag);
-       while (*agno <= end_agno) {
-               pag = xfs_perag_grab(mp, *agno);
-               if (pag)
-                       return pag;
-               (*agno)++;
-       }
-       return NULL;
-}
-
-#define for_each_perag_range(mp, agno, end_agno, pag) \
-       for ((pag) = xfs_perag_grab((mp), (agno)); \
-               (pag) != NULL; \
-               (pag) = xfs_perag_next((pag), &(agno), (end_agno)))
-
-#define for_each_perag_from(mp, agno, pag) \
-       for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag))
-
-#define for_each_perag(mp, agno, pag) \
-       (agno) = 0; \
-       for_each_perag_from((mp), (agno), (pag))
-
 static inline struct xfs_perag *
 xfs_perag_next_wrap(
        struct xfs_perag        *pag,
index d2012fbf07aa651f964cbefac30e881707d2daba..061c8c961d5bc9b473b31dc9aeb8447199eafc6a 100644 (file)
@@ -1109,14 +1109,13 @@ int
 xfs_update_secondary_sbs(
        struct xfs_mount        *mp)
 {
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno = 1;
+       struct xfs_perag        *pag = NULL;
        int                     saved_error = 0;
        int                     error = 0;
        LIST_HEAD               (buffer_list);
 
        /* update secondary superblocks. */
-       for_each_perag_from(mp, agno, pag) {
+       while ((pag = xfs_perag_next_from(mp, pag, 1))) {
                struct xfs_buf          *bp;
 
                error = xfs_buf_get(mp->m_ddev_targp,
@@ -1146,7 +1145,7 @@ xfs_update_secondary_sbs(
                xfs_buf_relse(bp);
 
                /* don't hold too many buffers at once */
-               if (agno % 16)
+               if (pag_agno(pag) % 16)
                        continue;
 
                error = xfs_buf_delwri_submit(&buffer_list);
@@ -1160,12 +1159,8 @@ xfs_update_secondary_sbs(
                }
        }
        error = xfs_buf_delwri_submit(&buffer_list);
-       if (error) {
-               xfs_warn(mp,
-               "write error %d updating a secondary superblock near ag %d",
-                       error, agno);
-       }
-
+       if (error)
+               xfs_warn(mp, "error %d writing secondary superblocks", error);
        return saved_error ? saved_error : error;
 }
 
index c299b16c9365fab61b98e13bebc38607d9768f87..c91db4f51407437342696e8e114d6b5248a8ac48 100644 (file)
@@ -170,13 +170,12 @@ xfs_icount_range(
        unsigned long long      *max)
 {
        unsigned long long      nr_inos = 0;
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag = NULL;
 
        /* root, rtbitmap, rtsum all live in the first chunk */
        *min = XFS_INODES_PER_CHUNK;
 
-       for_each_perag(mp, agno, pag)
+       while ((pag = xfs_perag_next(mp, pag)))
                nr_inos += pag->agino_max - pag->agino_min + 1;
        *max = nr_inos;
 }
index a43912227dd478ae9afc54f8164c6465585d276f..fb022b403716b14ac62e5ace23600b626555b304 100644 (file)
@@ -760,11 +760,10 @@ xchk_bmap_check_rmaps(
        struct xfs_scrub        *sc,
        int                     whichfork)
 {
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag = NULL;
        int                     error;
 
-       for_each_perag(sc->mp, agno, pag) {
+       while ((pag = xfs_perag_next(sc->mp, pag))) {
                error = xchk_bmap_check_ag_rmaps(sc, whichfork, pag);
                if (error ||
                    (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
index dc8fdd2da174ed303dc23f17c79e4e6e73805585..be408e50484b5404c56a85a1803420bb167d4b07 100644 (file)
@@ -407,12 +407,11 @@ xrep_bmap_find_mappings(
        struct xrep_bmap        *rb)
 {
        struct xfs_scrub        *sc = rb->sc;
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag = NULL;
        int                     error = 0;
 
        /* Iterate the rmaps for extents. */
-       for_each_perag(sc->mp, agno, pag) {
+       while ((pag = xfs_perag_next(sc->mp, pag))) {
                error = xrep_bmap_scan_ag(rb, pag);
                if (error) {
                        xfs_perag_rele(pag);
index 1d3e98346933e1100d951af3ce77618b1d00aa0f..28db0c83819c20416239d46700cfaa58cae9c09c 100644 (file)
@@ -74,10 +74,9 @@ xchk_fscount_warmup(
        struct xfs_buf          *agi_bp = NULL;
        struct xfs_buf          *agf_bp = NULL;
        struct xfs_perag        *pag = NULL;
-       xfs_agnumber_t          agno;
        int                     error = 0;
 
-       for_each_perag(mp, agno, pag) {
+       while ((pag = xfs_perag_next(mp, pag))) {
                if (xchk_should_terminate(sc, &error))
                        break;
                if (xfs_perag_initialised_agi(pag) &&
@@ -295,9 +294,8 @@ xchk_fscount_aggregate_agcounts(
        struct xchk_fscounters  *fsc)
 {
        struct xfs_mount        *mp = sc->mp;
-       struct xfs_perag        *pag;
+       struct xfs_perag        *pag = NULL;
        uint64_t                delayed;
-       xfs_agnumber_t          agno;
        int                     tries = 8;
        int                     error = 0;
 
@@ -306,7 +304,7 @@ retry:
        fsc->ifree = 0;
        fsc->fdblocks = 0;
 
-       for_each_perag(mp, agno, pag) {
+       while ((pag = xfs_perag_next(mp, pag))) {
                if (xchk_should_terminate(sc, &error))
                        break;
 
@@ -327,7 +325,7 @@ retry:
                if (xfs_has_lazysbcount(sc->mp)) {
                        fsc->fdblocks += pag->pagf_btreeblks;
                } else {
-                       error = xchk_fscount_btreeblks(sc, fsc, agno);
+                       error = xchk_fscount_btreeblks(sc, fsc, pag_agno(pag));
                        if (error)
                                break;
                }
index b712a8bd34f5435b87c448c0c2b8d399ec2236bf..112dd05e5551d3c1e39630f2ca3a36af56c98408 100644 (file)
@@ -160,12 +160,11 @@ STATIC void
 xchk_mark_all_healthy(
        struct xfs_mount        *mp)
 {
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag = NULL;
 
        xfs_fs_mark_healthy(mp, XFS_SICK_FS_INDIRECT);
        xfs_rt_mark_healthy(mp, XFS_SICK_RT_INDIRECT);
-       for_each_perag(mp, agno, pag)
+       while ((pag = xfs_perag_next(mp, pag)))
                xfs_ag_mark_healthy(pag, XFS_SICK_AG_INDIRECT);
 }
 
@@ -294,9 +293,7 @@ xchk_health_record(
        struct xfs_scrub        *sc)
 {
        struct xfs_mount        *mp = sc->mp;
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
-
+       struct xfs_perag        *pag = NULL;
        unsigned int            sick;
        unsigned int            checked;
 
@@ -308,7 +305,7 @@ xchk_health_record(
        if (sick & XFS_SICK_RT_PRIMARY)
                xchk_set_corrupt(sc);
 
-       for_each_perag(mp, agno, pag) {
+       while ((pag = xfs_perag_next(mp, pag))) {
                xfs_ag_measure_sickness(pag, &sick, &checked);
                if (sick & XFS_SICK_AG_PRIMARY)
                        xchk_set_corrupt(sc);
index 3e45b9b72312abaf49f0edc0617f784c8c004b7e..5da9e1a387a8bbc70416751ab8eeeaa3124ea352 100644 (file)
@@ -761,14 +761,13 @@ STATIC int
 xrep_dinode_count_rmaps(
        struct xrep_inode       *ri)
 {
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag = NULL;
        int                     error;
 
        if (!xfs_has_rmapbt(ri->sc->mp) || xfs_has_realtime(ri->sc->mp))
                return -EOPNOTSUPP;
 
-       for_each_perag(ri->sc->mp, agno, pag) {
+       while ((pag = xfs_perag_next(ri->sc->mp, pag))) {
                error = xrep_dinode_count_ag_rmaps(ri, pag);
                if (error) {
                        xfs_perag_rele(pag);
index dfd6edcebb6ea48f432a68c34e3575124cc1f937..739ec69c44281cf6c68102bafb737f7ecee8c935 100644 (file)
@@ -387,8 +387,8 @@ xfs_trim_datadev_extents(
 {
        xfs_agnumber_t          start_agno, end_agno;
        xfs_agblock_t           start_agbno, end_agbno;
+       struct xfs_perag        *pag = NULL;
        xfs_daddr_t             ddev_end;
-       struct xfs_perag        *pag;
        int                     last_error = 0, error;
 
        ddev_end = min_t(xfs_daddr_t, end,
@@ -399,10 +399,10 @@ xfs_trim_datadev_extents(
        end_agno = xfs_daddr_to_agno(mp, ddev_end);
        end_agbno = xfs_daddr_to_agbno(mp, ddev_end);
 
-       for_each_perag_range(mp, start_agno, end_agno, pag) {
+       while ((pag = xfs_perag_next_range(mp, pag, start_agno, end_agno))) {
                xfs_agblock_t   agend = pag->block_count;
 
-               if (start_agno == end_agno)
+               if (pag_agno(pag) == end_agno)
                        agend = end_agbno;
                error = xfs_trim_perag_extents(pag, start_agbno, agend, minlen);
                if (error)
index 79b0f833c511e3ddc557f885f01dca16d1c934ac..3d5a57d7ac5e1417e50c624ea29da13767a6d0e0 100644 (file)
@@ -629,11 +629,10 @@ void
 xfs_extent_busy_wait_all(
        struct xfs_mount        *mp)
 {
-       struct xfs_perag        *pag;
+       struct xfs_perag        *pag = NULL;
        DEFINE_WAIT             (wait);
-       xfs_agnumber_t          agno;
 
-       for_each_perag(mp, agno, pag) {
+       while ((pag = xfs_perag_next(mp, pag))) {
                do {
                        prepare_to_wait(&pag->pagb_wait, &wait, TASK_KILLABLE);
                        if  (RB_EMPTY_ROOT(&pag->pagb_tree))
index 918e1c38a15592cb7d26d8d09f591678d0cb3a4d..a26fb054346b68441c518e3c203525a033ee404c 100644 (file)
@@ -460,11 +460,11 @@ __xfs_getfsmap_datadev(
        void                            *priv)
 {
        struct xfs_mount                *mp = tp->t_mountp;
-       struct xfs_perag                *pag;
+       struct xfs_perag                *pag = NULL;
        struct xfs_btree_cur            *bt_cur = NULL;
        xfs_fsblock_t                   start_fsb;
        xfs_fsblock_t                   end_fsb;
-       xfs_agnumber_t                  start_ag, end_ag, ag;
+       xfs_agnumber_t                  start_ag, end_ag;
        uint64_t                        eofs;
        int                             error = 0;
 
@@ -512,8 +512,7 @@ __xfs_getfsmap_datadev(
        start_ag = XFS_FSB_TO_AGNO(mp, start_fsb);
        end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
 
-       ag = start_ag;
-       for_each_perag_range(mp, ag, end_ag, pag) {
+       while ((pag = xfs_perag_next_range(mp, pag, start_ag, end_ag))) {
                /*
                 * Set the AG high key from the fsmap high key if this
                 * is the last AG that we're querying.
index b247d895c276d2b436eafe16c1d8611422c531b7..82812a458cf10f6bcc8270aafcbee74dcc956de9 100644 (file)
@@ -528,13 +528,12 @@ int
 xfs_fs_reserve_ag_blocks(
        struct xfs_mount        *mp)
 {
-       xfs_agnumber_t          agno;
-       struct xfs_perag        *pag;
+       struct xfs_perag        *pag = NULL;
        int                     error = 0;
        int                     err2;
 
        mp->m_finobt_nores = false;
-       for_each_perag(mp, agno, pag) {
+       while ((pag = xfs_perag_next(mp, pag))) {
                err2 = xfs_ag_resv_init(pag, NULL);
                if (err2 && !error)
                        error = err2;
@@ -556,9 +555,8 @@ void
 xfs_fs_unreserve_ag_blocks(
        struct xfs_mount        *mp)
 {
-       xfs_agnumber_t          agno;
-       struct xfs_perag        *pag;
+       struct xfs_perag        *pag = NULL;
 
-       for_each_perag(mp, agno, pag)
+       while ((pag = xfs_perag_next(mp, pag)))
                xfs_ag_resv_free(pag);
 }
index d6492128582a3e4158f72e942091d6e06109e380..ff5aca875ab0d0cb93316dae065989c6dc02bc66 100644 (file)
@@ -28,8 +28,7 @@ void
 xfs_health_unmount(
        struct xfs_mount        *mp)
 {
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag = NULL;
        unsigned int            sick = 0;
        unsigned int            checked = 0;
        bool                    warn = false;
@@ -38,7 +37,7 @@ xfs_health_unmount(
                return;
 
        /* Measure AG corruption levels. */
-       for_each_perag(mp, agno, pag) {
+       while ((pag = xfs_perag_next(mp, pag))) {
                xfs_ag_measure_sickness(pag, &sick, &checked);
                if (sick) {
                        trace_xfs_ag_unfixed_corruption(pag, sick);
index 0a930fc116f5756c76c728913f24d8959e0a1f44..383c245482027b6df94c23ea03c90acc4ddef93d 100644 (file)
@@ -1383,13 +1383,12 @@ void
 xfs_blockgc_stop(
        struct xfs_mount        *mp)
 {
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag = NULL;
 
        if (!xfs_clear_blockgc_enabled(mp))
                return;
 
-       for_each_perag(mp, agno, pag)
+       while ((pag = xfs_perag_next(mp, pag)))
                cancel_delayed_work_sync(&pag->pag_blockgc_work);
        trace_xfs_blockgc_stop(mp, __return_address);
 }
index ec2d56f1840fc6637beb6f4d1ad317a0ef9dcfd0..7db3ece370b1003bc1cb1a2f75a0b645b406140d 100644 (file)
@@ -540,23 +540,25 @@ xfs_iwalk_args(
        unsigned int            flags)
 {
        struct xfs_mount        *mp = iwag->mp;
-       xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, iwag->startino);
+       xfs_agnumber_t          start_agno;
        int                     error;
 
-       ASSERT(agno < mp->m_sb.sb_agcount);
+       start_agno = XFS_INO_TO_AGNO(iwag->mp, iwag->startino);
+       ASSERT(start_agno < iwag->mp->m_sb.sb_agcount);
        ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
 
        error = xfs_iwalk_alloc(iwag);
        if (error)
                return error;
 
-       for_each_perag_from(mp, agno, iwag->pag) {
+       while ((iwag->pag = xfs_perag_next_from(mp, iwag->pag, start_agno))) {
                error = xfs_iwalk_ag(iwag);
                if (error || (flags & XFS_IWALK_SAME_AG)) {
                        xfs_perag_rele(iwag->pag);
                        break;
                }
-               iwag->startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
+               iwag->startino =
+                       XFS_AGINO_TO_INO(mp, pag_agno(iwag->pag) + 1, 0);
        }
 
        xfs_iwalk_free(iwag);
@@ -644,19 +646,19 @@ xfs_iwalk_threaded(
        bool                    polled,
        void                    *data)
 {
+       xfs_agnumber_t          start_agno = XFS_INO_TO_AGNO(mp, startino);
        struct xfs_pwork_ctl    pctl;
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, startino);
+       struct xfs_perag        *pag = NULL;
        int                     error;
 
-       ASSERT(agno < mp->m_sb.sb_agcount);
+       ASSERT(start_agno < mp->m_sb.sb_agcount);
        ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
 
        error = xfs_pwork_init(mp, &pctl, xfs_iwalk_ag_work, "xfs_iwalk");
        if (error)
                return error;
 
-       for_each_perag_from(mp, agno, pag) {
+       while ((pag = xfs_perag_next_from(mp, pag, start_agno))) {
                struct xfs_iwalk_ag     *iwag;
 
                if (xfs_pwork_ctl_want_abort(&pctl))
index a285d2d1f68c15bde11113de5cf7d9c2f8bcce18..55e412a821483e34406eb50a38c873be3e5016b9 100644 (file)
@@ -2845,10 +2845,9 @@ static void
 xlog_recover_process_iunlinks(
        struct xlog     *log)
 {
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag = NULL;
 
-       for_each_perag(log->l_mp, agno, pag)
+       while ((pag = xfs_perag_next(log->l_mp, pag)))
                xlog_recover_iunlink_ag(pag);
 }
 
index 2e82b5b6ed52d2d011c78b4b63d6ae05251c35d7..b11769c009effc4147d0f1301cf00d3c373f9c83 100644 (file)
@@ -894,14 +894,13 @@ int
 xfs_reflink_recover_cow(
        struct xfs_mount        *mp)
 {
-       struct xfs_perag        *pag;
-       xfs_agnumber_t          agno;
+       struct xfs_perag        *pag = NULL;
        int                     error = 0;
 
        if (!xfs_has_reflink(mp))
                return 0;
 
-       for_each_perag(mp, agno, pag) {
+       while ((pag = xfs_perag_next(mp, pag))) {
                error = xfs_refcount_recover_cow_leftovers(mp, pag);
                if (error) {
                        xfs_perag_rele(pag);