xfs: clean up XFS_MIN_FREELIST macros
We no longer calculate the minimum freelist size from the on-disk
AGF, so we don't need the macros used for this. That means the
nested macros can be cleaned up, and turn this into an actual
function so the logic is clear and concise. This will make it much
easier to add support for the rmap btree when the time comes.
This also gets rid of the XFS_AG_MAXLEVELS macro used by these
freelist macros as it is simply a wrapper around a single variable.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c
index 69a15ba..0d9b4c3 100644
--- a/libxfs/xfs_alloc.c
+++ b/libxfs/xfs_alloc.c
@@ -1866,6 +1866,23 @@
return pag->pagf_flcount > 0 || pag->pagf_longest > 0;
}
+unsigned int
+xfs_alloc_min_freelist(
+ struct xfs_mount *mp,
+ struct xfs_perag *pag)
+{
+ unsigned int min_free;
+
+ /* space needed by-bno freespace btree */
+ min_free = min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_BNOi] + 1,
+ mp->m_ag_maxlevels);
+ /* space needed by-size freespace btree */
+ min_free += min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_CNTi] + 1,
+ mp->m_ag_maxlevels);
+
+ return min_free;
+}
+
/*
* Check if the operation we are fixing up the freelist for should go ahead or
* not. If we are freeing blocks, we always allow it, otherwise the allocation
@@ -1940,7 +1957,7 @@
goto out_agbp_relse;
}
- need = XFS_MIN_FREELIST_PAG(pag, mp);
+ need = xfs_alloc_min_freelist(mp, pag);
if (!xfs_alloc_space_available(args, need, flags))
goto out_agbp_relse;
@@ -1959,9 +1976,8 @@
}
}
-
/* If there isn't enough total space or single-extent, reject it. */
- need = XFS_MIN_FREELIST_PAG(pag, mp);
+ need = xfs_alloc_min_freelist(mp, pag);
if (!xfs_alloc_space_available(args, need, flags))
goto out_agbp_relse;
diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h
index c76b55c..071b28b 100644
--- a/libxfs/xfs_alloc.h
+++ b/libxfs/xfs_alloc.h
@@ -132,6 +132,8 @@
xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_mount *mp,
struct xfs_perag *pag, xfs_extlen_t need);
+unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp,
+ struct xfs_perag *pag);
/*
* Compute and fill in value of m_ag_maxlevels.
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 4638537..97822df 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -3514,7 +3514,7 @@
}
longest = xfs_alloc_longest_free_extent(mp, pag,
- XFS_MIN_FREELIST_PAG(pag, mp));
+ xfs_alloc_min_freelist(mp, pag));
if (*blen < longest)
*blen = longest;
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 1699b8f..68d4175 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -766,19 +766,6 @@
#define XFS_AGFL_CRC_OFF offsetof(struct xfs_agfl, agfl_crc)
-
-#define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels)
-#define XFS_MIN_FREELIST_RAW(bl,cl,mp) \
- (MIN(bl + 1, XFS_AG_MAXLEVELS(mp)) + MIN(cl + 1, XFS_AG_MAXLEVELS(mp)))
-#define XFS_MIN_FREELIST(a,mp) \
- (XFS_MIN_FREELIST_RAW( \
- be32_to_cpu((a)->agf_levels[XFS_BTNUM_BNOi]), \
- be32_to_cpu((a)->agf_levels[XFS_BTNUM_CNTi]), mp))
-#define XFS_MIN_FREELIST_PAG(pag,mp) \
- (XFS_MIN_FREELIST_RAW( \
- (unsigned int)(pag)->pagf_levels[XFS_BTNUM_BNOi], \
- (unsigned int)(pag)->pagf_levels[XFS_BTNUM_CNTi], mp))
-
#define XFS_AGB_TO_FSB(mp,agno,agbno) \
(((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno))
#define XFS_FSB_TO_AGNO(mp,fsbno) \
diff --git a/libxfs/xfs_trans_resv.h b/libxfs/xfs_trans_resv.h
index 2d5bdfc..7978150 100644
--- a/libxfs/xfs_trans_resv.h
+++ b/libxfs/xfs_trans_resv.h
@@ -73,9 +73,9 @@
* 2 trees * (2 blocks/level * max depth - 1) * block size
*/
#define XFS_ALLOCFREE_LOG_RES(mp,nx) \
- ((nx) * (2 * XFS_FSB_TO_B((mp), 2 * XFS_AG_MAXLEVELS(mp) - 1)))
+ ((nx) * (2 * XFS_FSB_TO_B((mp), 2 * (mp)->m_ag_maxlevels - 1)))
#define XFS_ALLOCFREE_LOG_COUNT(mp,nx) \
- ((nx) * (2 * (2 * XFS_AG_MAXLEVELS(mp) - 1)))
+ ((nx) * (2 * (2 * (mp)->m_ag_maxlevels - 1)))
/*
* Per-directory log reservation for any directory change.
diff --git a/libxfs/xfs_trans_space.h b/libxfs/xfs_trans_space.h
index bf9c457..41e0428 100644
--- a/libxfs/xfs_trans_space.h
+++ b/libxfs/xfs_trans_space.h
@@ -67,7 +67,7 @@
#define XFS_DIOSTRAT_SPACE_RES(mp, v) \
(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + (v))
#define XFS_GROWFS_SPACE_RES(mp) \
- (2 * XFS_AG_MAXLEVELS(mp))
+ (2 * (mp)->m_ag_maxlevels)
#define XFS_GROWFSRT_SPACE_RES(mp,b) \
((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK))
#define XFS_LINK_SPACE_RES(mp,nl) \
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 83f7749..f3901be 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2761,6 +2761,7 @@
for (agno = 0; agno < agcount; agno++) {
struct xfs_agfl *agfl;
int bucket;
+ struct xfs_perag *pag = xfs_perag_get(mp, agno);
/*
* Superblock.
@@ -2792,6 +2793,8 @@
agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1);
agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
+ pag->pagf_levels[XFS_BTNUM_BNOi] = 1;
+ pag->pagf_levels[XFS_BTNUM_CNTi] = 1;
agf->agf_flfirst = 0;
agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1);
agf->agf_flcount = 0;
@@ -2806,8 +2809,8 @@
agf->agf_longest = cpu_to_be32(agsize -
XFS_FSB_TO_AGBNO(mp, logstart) - logblocks);
}
- if (XFS_MIN_FREELIST(agf, mp) > worst_freelist)
- worst_freelist = XFS_MIN_FREELIST(agf, mp);
+ if (xfs_alloc_min_freelist(mp, pag) > worst_freelist)
+ worst_freelist = xfs_alloc_min_freelist(mp, pag);
libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
/*
@@ -2979,8 +2982,10 @@
/*
* Free INO btree root block
*/
- if (!finobt)
+ if (!finobt) {
+ xfs_perag_put(pag);
continue;
+ }
buf = libxfs_getbuf(mp->m_ddev_targp,
XFS_AGB_TO_DADDR(mp, agno, XFS_FIBT_BLOCK(mp)),
@@ -2995,6 +3000,7 @@
xfs_btree_init_block(mp, buf, XFS_FIBT_MAGIC, 0, 0,
agno, 0);
libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
+ xfs_perag_put(pag);
}
/*
diff --git a/repair/phase5.c b/repair/phase5.c
index 7372734..b5a53b1 100644
--- a/repair/phase5.c
+++ b/repair/phase5.c
@@ -1510,7 +1510,8 @@
args.agno = agno;
args.alignment = 1;
args.pag = xfs_perag_get(mp,agno);
- libxfs_trans_reserve(tp, &tres, XFS_MIN_FREELIST(agf, mp), 0);
+ libxfs_trans_reserve(tp, &tres,
+ xfs_alloc_min_freelist(mp, args.pag), 0);
error = libxfs_alloc_fix_freelist(&args, 0);
xfs_perag_put(args.pag);
if (error) {
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index 11a6069..9b0b99f 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -404,11 +404,16 @@
* and by size), the inode allocation btree root, the free inode
* allocation btree root (if enabled) and some number of blocks to
* prefill the agfl.
+ *
+ * Because the current shape of the btrees may differ from the current
+ * shape, we open code the mkfs freelist block count here. mkfs creates
+ * single level trees, so the calculation is pertty straight forward for
+ * the two trees that use the AGFL.
*/
bnobt_root = howmany(4 * mp->m_sb.sb_sectsize, mp->m_sb.sb_blocksize);
bcntbt_root = bnobt_root + 1;
inobt_root = bnobt_root + 2;
- fino_bno = inobt_root + XFS_MIN_FREELIST_RAW(1, 1, mp) + 1;
+ fino_bno = inobt_root + (2 * min(2, mp->m_ag_maxlevels)) + 1;
if (xfs_sb_version_hasfinobt(&mp->m_sb))
fino_bno++;