xfs: move the min and max group block numbers to xfs_group
authorDarrick J. Wong <djwong@kernel.org>
Mon, 4 Nov 2024 04:19:35 +0000 (20:19 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 5 Nov 2024 21:38:44 +0000 (13:38 -0800)
Move the min and max agblock numbers to the generic xfs_group structure
so that we can start building validators for extents within an rtgroup.
While we're at it, use check_add_overflow for the extent length
computation because that has much better overflow checking.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_ag.c
fs/xfs/libxfs/xfs_ag.h
fs/xfs/libxfs/xfs_group.h
fs/xfs/libxfs/xfs_ialloc_btree.c
fs/xfs/libxfs/xfs_rtgroup.c
fs/xfs/libxfs/xfs_rtgroup.h
fs/xfs/scrub/agheader.c
fs/xfs/scrub/agheader_repair.c
fs/xfs/scrub/repair.c
fs/xfs/xfs_discard.c
fs/xfs/xfs_rtalloc.c

index 8fe96a9..b59cb46 100644 (file)
@@ -205,9 +205,10 @@ xfs_update_last_ag_size(
 
        if (!pag)
                return -EFSCORRUPTED;
-       pag->block_count = __xfs_ag_block_count(mp, prev_agcount - 1,
-                       mp->m_sb.sb_agcount, mp->m_sb.sb_dblocks);
-       __xfs_agino_range(mp, pag->block_count, &pag->agino_min,
+       pag_group(pag)->xg_block_count = __xfs_ag_block_count(mp,
+                       prev_agcount - 1, mp->m_sb.sb_agcount,
+                       mp->m_sb.sb_dblocks);
+       __xfs_agino_range(mp, pag_group(pag)->xg_block_count, &pag->agino_min,
                        &pag->agino_max);
        xfs_perag_rele(pag);
        return 0;
@@ -241,9 +242,10 @@ xfs_perag_alloc(
        /*
         * Pre-calculated geometry
         */
-       pag->block_count = __xfs_ag_block_count(mp, index, agcount, dblocks);
-       pag->min_block = XFS_AGFL_BLOCK(mp) + 1;
-       __xfs_agino_range(mp, pag->block_count, &pag->agino_min,
+       pag_group(pag)->xg_block_count = __xfs_ag_block_count(mp, index, agcount,
+                               dblocks);
+       pag_group(pag)->xg_min_gbno = XFS_AGFL_BLOCK(mp) + 1;
+       __xfs_agino_range(mp, pag_group(pag)->xg_block_count, &pag->agino_min,
                        &pag->agino_max);
 
        error = xfs_group_insert(mp, pag_group(pag), index, XG_TYPE_AG);
@@ -852,8 +854,8 @@ xfs_ag_shrink_space(
        }
 
        /* Update perag geometry */
-       pag->block_count -= delta;
-       __xfs_agino_range(mp, pag->block_count, &pag->agino_min,
+       pag_group(pag)->xg_block_count -= delta;
+       __xfs_agino_range(mp, pag_group(pag)->xg_block_count, &pag->agino_min,
                        &pag->agino_max);
 
        xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH);
@@ -924,8 +926,8 @@ xfs_ag_extend_space(
                return error;
 
        /* Update perag geometry */
-       pag->block_count = be32_to_cpu(agf->agf_length);
-       __xfs_agino_range(mp, pag->block_count, &pag->agino_min,
+       pag_group(pag)->xg_block_count = be32_to_cpu(agf->agf_length);
+       __xfs_agino_range(mp, pag_group(pag)->xg_block_count, &pag->agino_min,
                        &pag->agino_max);
        return 0;
 }
index 9c22a76..1f24cfa 100644 (file)
@@ -61,8 +61,6 @@ struct xfs_perag {
        struct xfs_ag_resv      pag_rmapbt_resv;
 
        /* Precalculated geometry info */
-       xfs_agblock_t           block_count;
-       xfs_agblock_t           min_block;
        xfs_agino_t             agino_min;
        xfs_agino_t             agino_max;
 
@@ -220,11 +218,7 @@ void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
 static inline bool
 xfs_verify_agbno(struct xfs_perag *pag, xfs_agblock_t agbno)
 {
-       if (agbno >= pag->block_count)
-               return false;
-       if (agbno < pag->min_block)
-               return false;
-       return true;
+       return xfs_verify_gbno(pag_group(pag), agbno);
 }
 
 static inline bool
@@ -233,13 +227,7 @@ xfs_verify_agbext(
        xfs_agblock_t           agbno,
        xfs_agblock_t           len)
 {
-       if (agbno + len <= agbno)
-               return false;
-
-       if (!xfs_verify_agbno(pag, agbno))
-               return false;
-
-       return xfs_verify_agbno(pag, agbno + len - 1);
+       return xfs_verify_gbext(pag_group(pag), agbno, len);
 }
 
 /*
index 5b73622..242b056 100644 (file)
@@ -12,6 +12,10 @@ struct xfs_group {
        atomic_t                xg_ref;         /* passive reference count */
        atomic_t                xg_active_ref;  /* active reference count */
 
+       /* Precalculated geometry info */
+       uint32_t                xg_block_count; /* max usable gbno */
+       uint32_t                xg_min_gbno;    /* min usable gbno */
+
 #ifdef __KERNEL__
        /* -- kernel only structures below this line -- */
 
@@ -128,4 +132,33 @@ xfs_fsb_to_gbno(
        return fsbno & mp->m_groups[type].blkmask;
 }
 
+static inline bool
+xfs_verify_gbno(
+       struct xfs_group        *xg,
+       uint32_t                gbno)
+{
+       if (gbno >= xg->xg_block_count)
+               return false;
+       if (gbno < xg->xg_min_gbno)
+               return false;
+       return true;
+}
+
+static inline bool
+xfs_verify_gbext(
+       struct xfs_group        *xg,
+       uint32_t                gbno,
+       uint32_t                glen)
+{
+       uint32_t                end;
+
+       if (!xfs_verify_gbno(xg, gbno))
+               return false;
+       if (glen == 0 || check_add_overflow(gbno, glen - 1, &end))
+               return false;
+       if (!xfs_verify_gbno(xg, end))
+               return false;
+       return true;
+}
+
 #endif /* __LIBXFS_GROUP_H */
index 4c28deb..9b34896 100644 (file)
@@ -717,7 +717,7 @@ xfs_inobt_max_size(
        struct xfs_perag        *pag)
 {
        struct xfs_mount        *mp = pag_mount(pag);
-       xfs_agblock_t           agblocks = pag->block_count;
+       xfs_agblock_t           agblocks = pag_group(pag)->xg_block_count;
 
        /* Bail out if we're uninitialized, which can happen in mkfs. */
        if (M_IGEO(mp)->inobt_mxr[0] == 0)
index 624d8b2..e74bb05 100644 (file)
 #include "xfs_metafile.h"
 #include "xfs_metadir.h"
 
+/* Find the first usable fsblock in this rtgroup. */
+static inline uint32_t
+xfs_rtgroup_min_block(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno)
+{
+       if (xfs_has_rtsb(mp) && rgno == 0)
+               return mp->m_sb.sb_rextsize;
+
+       return 0;
+}
+
+/* Precompute this group's geometry */
+void
+xfs_rtgroup_calc_geometry(
+       struct xfs_mount        *mp,
+       struct xfs_rtgroup      *rtg,
+       xfs_rgnumber_t          rgno,
+       xfs_rgnumber_t          rgcount,
+       xfs_rtbxlen_t           rextents)
+{
+       rtg->rtg_extents = __xfs_rtgroup_extents(mp, rgno, rgcount, rextents);
+       rtg_group(rtg)->xg_block_count = rtg->rtg_extents * mp->m_sb.sb_rextsize;
+       rtg_group(rtg)->xg_min_gbno = xfs_rtgroup_min_block(mp, rgno);
+}
+
 int
 xfs_rtgroup_alloc(
        struct xfs_mount        *mp,
@@ -48,6 +74,8 @@ xfs_rtgroup_alloc(
        if (!rtg)
                return -ENOMEM;
 
+       xfs_rtgroup_calc_geometry(mp, rtg, rgno, rgcount, rextents);
+
        error = xfs_group_insert(mp, rtg_group(rtg), rgno, XG_TYPE_RTG);
        if (error)
                goto out_free_rtg;
@@ -149,6 +177,7 @@ xfs_update_last_rtgroup_size(
                return -EFSCORRUPTED;
        rtg->rtg_extents = __xfs_rtgroup_extents(mp, prev_rgcount - 1,
                        mp->m_sb.sb_rgcount, mp->m_sb.sb_rextents);
+       rtg_group(rtg)->xg_block_count = rtg->rtg_extents * mp->m_sb.sb_rextsize;
        xfs_rtgroup_rele(rtg);
        return 0;
 }
@@ -223,7 +252,7 @@ xfs_rtgroup_get_geometry(
        /* Fill out form. */
        memset(rgeo, 0, sizeof(*rgeo));
        rgeo->rg_number = rtg_rgno(rtg);
-       rgeo->rg_length = rtg->rtg_extents * rtg_mount(rtg)->m_sb.sb_rextsize;
+       rgeo->rg_length = rtg_group(rtg)->xg_block_count;
        xfs_rtgroup_geom_health(rtg, rgeo);
        return 0;
 }
index c15b232..1e51dc6 100644 (file)
@@ -199,6 +199,9 @@ int xfs_initialize_rtgroups(struct xfs_mount *mp, xfs_rgnumber_t first_rgno,
 xfs_rtxnum_t __xfs_rtgroup_extents(struct xfs_mount *mp, xfs_rgnumber_t rgno,
                xfs_rgnumber_t rgcount, xfs_rtbxlen_t rextents);
 xfs_rtxnum_t xfs_rtgroup_extents(struct xfs_mount *mp, xfs_rgnumber_t rgno);
+void xfs_rtgroup_calc_geometry(struct xfs_mount *mp, struct xfs_rtgroup *rtg,
+               xfs_rgnumber_t rgno, xfs_rgnumber_t rgcount,
+               xfs_rtbxlen_t rextents);
 
 int xfs_update_last_rtgroup_size(struct xfs_mount *mp,
                xfs_rgnumber_t prev_rgcount);
index 05f5e94..d037de6 100644 (file)
@@ -564,7 +564,7 @@ xchk_agf(
 
        /* Check the AG length */
        eoag = be32_to_cpu(agf->agf_length);
-       if (eoag != pag->block_count)
+       if (eoag != pag_group(pag)->xg_block_count)
                xchk_block_set_corrupt(sc, sc->sa.agf_bp);
 
        /* Check the AGF btree roots and levels */
@@ -944,7 +944,7 @@ xchk_agi(
 
        /* Check the AG length */
        eoag = be32_to_cpu(agi->agi_length);
-       if (eoag != pag->block_count)
+       if (eoag != pag_group(pag)->xg_block_count)
                xchk_block_set_corrupt(sc, sc->sa.agi_bp);
 
        /* Check btree roots and levels */
index 0ea04d6..0fad0ba 100644 (file)
@@ -209,7 +209,7 @@ xrep_agf_init_header(
        agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
        agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
        agf->agf_seqno = cpu_to_be32(pag_agno(pag));
-       agf->agf_length = cpu_to_be32(pag->block_count);
+       agf->agf_length = cpu_to_be32(pag_group(pag)->xg_block_count);
        agf->agf_flfirst = old_agf->agf_flfirst;
        agf->agf_fllast = old_agf->agf_fllast;
        agf->agf_flcount = old_agf->agf_flcount;
@@ -898,7 +898,7 @@ xrep_agi_init_header(
        agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
        agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
        agi->agi_seqno = cpu_to_be32(pag_agno(pag));
-       agi->agi_length = cpu_to_be32(pag->block_count);
+       agi->agi_length = cpu_to_be32(pag_group(pag)->xg_block_count);
        agi->agi_newino = cpu_to_be32(NULLAGINO);
        agi->agi_dirino = cpu_to_be32(NULLAGINO);
        if (xfs_has_crc(mp))
index 3fa0091..91c8bc0 100644 (file)
@@ -306,7 +306,7 @@ xrep_calc_ag_resblks(
        /* Now grab the block counters from the AGF. */
        error = xfs_alloc_read_agf(pag, NULL, 0, &bp);
        if (error) {
-               aglen = pag->block_count;
+               aglen = pag_group(pag)->xg_block_count;
                freelen = aglen;
                usedlen = aglen;
        } else {
@@ -326,9 +326,9 @@ xrep_calc_ag_resblks(
 
        /* If the block counts are impossible, make worst-case assumptions. */
        if (aglen == NULLAGBLOCK ||
-           aglen != pag->block_count ||
+           aglen != pag_group(pag)->xg_block_count ||
            freelen >= aglen) {
-               aglen = pag->block_count;
+               aglen = pag_group(pag)->xg_block_count;
                freelen = aglen;
                usedlen = aglen;
        }
index e71bd64..a763596 100644 (file)
@@ -337,7 +337,7 @@ xfs_trim_perag_extents(
        };
        int                     error = 0;
 
-       if (start != 0 || end != pag->block_count)
+       if (start != 0 || end != pag_group(pag)->xg_block_count)
                tcur.by_bno = true;
 
        do {
@@ -403,7 +403,7 @@ xfs_trim_datadev_extents(
        end_agbno = xfs_daddr_to_agbno(mp, ddev_end);
 
        while ((pag = xfs_perag_next_range(mp, pag, start_agno, end_agno))) {
-               xfs_agblock_t   agend = pag->block_count;
+               xfs_agblock_t   agend = pag_group(pag)->xg_block_count;
 
                if (pag_agno(pag) == end_agno)
                        agend = end_agbno;
index 4207058..8520d72 100644 (file)
@@ -878,7 +878,8 @@ xfs_growfs_rt_bmblock(
        if (!nmp)
                return -ENOMEM;
 
-       rtg->rtg_extents = xfs_rtgroup_extents(nmp, rtg_rgno(rtg));
+       xfs_rtgroup_calc_geometry(nmp, rtg, rtg_rgno(rtg),
+                       nmp->m_sb.sb_rgcount, nmp->m_sb.sb_rextents);
 
        /*
         * Recompute the growfsrt reservation from the new rsumsize, so that the
@@ -1137,7 +1138,8 @@ out_error:
        /*
         * Reset rtg_extents to the old value if adding more blocks failed.
         */
-       rtg->rtg_extents = xfs_rtgroup_extents(rtg_mount(rtg), rtg_rgno(rtg));
+       xfs_rtgroup_calc_geometry(mp, rtg, rtg_rgno(rtg), mp->m_sb.sb_rgcount,
+                       mp->m_sb.sb_rextents);
        if (old_rsum_cache) {
                kvfree(rtg->rtg_rsum_cache);
                rtg->rtg_rsum_cache = old_rsum_cache;
@@ -1519,8 +1521,6 @@ xfs_rtmount_rtg(
 {
        int                     error, i;
 
-       rtg->rtg_extents = xfs_rtgroup_extents(mp, rtg_rgno(rtg));
-
        for (i = 0; i < XFS_RTGI_MAX; i++) {
                error = xfs_rtginode_load(rtg, i, tp);
                if (error)