summaryrefslogtreecommitdiff
path: root/fs/xfs/libxfs/xfs_ag.h
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2023-02-13 01:14:53 +0300
committerDave Chinner <dchinner@redhat.com>2023-02-13 01:14:53 +0300
commit76257a15873ccce817e0c4441f6bb66fb8f8201c (patch)
treea75763d4aaabb7bb276b9b542ad88c6eb0e482c4 /fs/xfs/libxfs/xfs_ag.h
parent7ac2ff8bb3713c7cb43564c04384af2ee7cc1f8d (diff)
downloadlinux-76257a15873ccce817e0c4441f6bb66fb8f8201c.tar.xz
xfs: introduce xfs_for_each_perag_wrap()
In several places we iterate every AG from a specific start agno and wrap back to the first AG when we reach the end of the filesystem to continue searching. We don't have a primitive for this iteration yet, so add one for conversion of these algorithms to per-ag based iteration. The filestream AG select code is a mess, and this initially makes it worse. The per-ag selection needs to be driven completely into the filestream code to clean this up and it will be done in a future patch that makes the filestream allocator use active per-ag references correctly. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/libxfs/xfs_ag.h')
-rw-r--r--fs/xfs/libxfs/xfs_ag.h45
1 files changed, 44 insertions, 1 deletions
diff --git a/fs/xfs/libxfs/xfs_ag.h b/fs/xfs/libxfs/xfs_ag.h
index 187d30d9bb13..8f43b91d4cf3 100644
--- a/fs/xfs/libxfs/xfs_ag.h
+++ b/fs/xfs/libxfs/xfs_ag.h
@@ -237,7 +237,6 @@ xfs_perag_next(
#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))
@@ -249,6 +248,50 @@ xfs_perag_next(
xfs_perag_rele(pag), \
(pag) = xfs_perag_grab_tag((mp), (agno), (tag)))
+static inline struct xfs_perag *
+xfs_perag_next_wrap(
+ struct xfs_perag *pag,
+ xfs_agnumber_t *agno,
+ xfs_agnumber_t stop_agno,
+ xfs_agnumber_t wrap_agno)
+{
+ struct xfs_mount *mp = pag->pag_mount;
+
+ *agno = pag->pag_agno + 1;
+ xfs_perag_rele(pag);
+ while (*agno != stop_agno) {
+ if (*agno >= wrap_agno)
+ *agno = 0;
+ if (*agno == stop_agno)
+ break;
+
+ pag = xfs_perag_grab(mp, *agno);
+ if (pag)
+ return pag;
+ (*agno)++;
+ }
+ return NULL;
+}
+
+/*
+ * Iterate all AGs from start_agno through wrap_agno, then 0 through
+ * (start_agno - 1).
+ */
+#define for_each_perag_wrap_at(mp, start_agno, wrap_agno, agno, pag) \
+ for ((agno) = (start_agno), (pag) = xfs_perag_grab((mp), (agno)); \
+ (pag) != NULL; \
+ (pag) = xfs_perag_next_wrap((pag), &(agno), (start_agno), \
+ (wrap_agno)))
+
+/*
+ * Iterate all AGs from start_agno through to the end of the filesystem, then 0
+ * through (start_agno - 1).
+ */
+#define for_each_perag_wrap(mp, start_agno, agno, pag) \
+ for_each_perag_wrap_at((mp), (start_agno), (mp)->m_sb.sb_agcount, \
+ (agno), (pag))
+
+
struct aghdr_init_data {
/* per ag data */
xfs_agblock_t agno; /* ag to init */