On 9/15/21 6:06 PM, Darrick J. Wong wrote:
From: Darrick J. Wong <djwong@xxxxxxxxxx>
To prepare to perag initialization code move to libxfs, port the
xfs_set_inode_alloc function from the kernel and make
libxfs_initialize_perag use it. The code isn't 1:1 identical, but
AFAICT it behaves the same way. In a future kernel release we'll
move the function into xfs_ag.c and update xfsprogs.
Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
Ok, so this is in effect syncing up:
commit 2d2194f61fddab3a9731b6e7a7ae3a4a19dd810c
Author: Carlos Maiolino <cmaiolino@xxxxxxxxxx>
Date: Thu Sep 20 10:32:38 2012 -0300
xfs: reduce code duplication handling inode32/64 options
and a few others up to about this change:
commit 12c3f05c7b592ae3bf2219392f1cbf252645cd79
Author: Eric Sandeen <sandeen@xxxxxxxxxx>
Date: Wed Mar 2 09:58:09 2016 +1100
xfs: fix up inode32/64 (re)mount handling
from the kernel. The pitfalls of having copied kernel code that's not
in libxfs. :(
The change looks legit and works fine here.
Reviewed-by: Eric Sandeen <sandeen@xxxxxxxxxx>
Thanks,
-Eric
---
libxfs/init.c | 142 ++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 89 insertions(+), 53 deletions(-)
diff --git a/libxfs/init.c b/libxfs/init.c
index 1ec83791..6223181f 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -482,18 +482,102 @@ rtmount_init(
return 0;
}
+/*
+ * Set parameters for inode allocation heuristics, taking into account
+ * filesystem size and inode32/inode64 mount options; i.e. specifically
+ * whether or not XFS_MOUNT_SMALL_INUMS is set.
+ *
+ * Inode allocation patterns are altered only if inode32 is requested
+ * (XFS_MOUNT_SMALL_INUMS), and the filesystem is sufficiently large.
+ * If altered, XFS_MOUNT_32BITINODES is set as well.
+ *
+ * An agcount independent of that in the mount structure is provided
+ * because in the growfs case, mp->m_sb.sb_agcount is not yet updated
+ * to the potentially higher ag count.
+ *
+ * Returns the maximum AG index which may contain inodes.
+ */
+xfs_agnumber_t
+xfs_set_inode_alloc(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agcount)
+{
+ xfs_agnumber_t index;
+ xfs_agnumber_t maxagi = 0;
+ xfs_sb_t *sbp = &mp->m_sb;
+ xfs_agnumber_t max_metadata;
+ xfs_agino_t agino;
+ xfs_ino_t ino;
+
+ /*
+ * Calculate how much should be reserved for inodes to meet
+ * the max inode percentage. Used only for inode32.
+ */
+ if (M_IGEO(mp)->maxicount) {
+ uint64_t icount;
+
+ icount = sbp->sb_dblocks * sbp->sb_imax_pct;
+ do_div(icount, 100);
+ icount += sbp->sb_agblocks - 1;
+ do_div(icount, sbp->sb_agblocks);
+ max_metadata = icount;
+ } else {
+ max_metadata = agcount;
+ }
+
+ /* Get the last possible inode in the filesystem */
+ agino = XFS_AGB_TO_AGINO(mp, sbp->sb_agblocks - 1);
+ ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
+
+ /*
+ * If user asked for no more than 32-bit inodes, and the fs is
+ * sufficiently large, set XFS_MOUNT_32BITINODES if we must alter
+ * the allocator to accommodate the request.
+ */
+ if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
+ mp->m_flags |= XFS_MOUNT_32BITINODES;
+ else
+ mp->m_flags &= ~XFS_MOUNT_32BITINODES;
+
+ for (index = 0; index < agcount; index++) {
+ struct xfs_perag *pag;
+
+ ino = XFS_AGINO_TO_INO(mp, index, agino);
+
+ pag = xfs_perag_get(mp, index);
+
+ if (mp->m_flags & XFS_MOUNT_32BITINODES) {
+ if (ino > XFS_MAXINUMBER_32) {
+ pag->pagi_inodeok = 0;
+ pag->pagf_metadata = 0;
+ } else {
+ pag->pagi_inodeok = 1;
+ maxagi++;
+ if (index < max_metadata)
+ pag->pagf_metadata = 1;
+ else
+ pag->pagf_metadata = 0;
+ }
+ } else {
+ pag->pagi_inodeok = 1;
+ pag->pagf_metadata = 0;
+ }
+
+ xfs_perag_put(pag);
+ }
+
+ return (mp->m_flags & XFS_MOUNT_32BITINODES) ? maxagi : agcount;
+}
+
static int
libxfs_initialize_perag(
xfs_mount_t *mp,
xfs_agnumber_t agcount,
xfs_agnumber_t *maxagi)
{
- xfs_agnumber_t index, max_metadata;
+ xfs_agnumber_t index;
xfs_agnumber_t first_initialised = 0;
xfs_perag_t *pag;
- xfs_agino_t agino;
- xfs_ino_t ino;
- xfs_sb_t *sbp = &mp->m_sb;
int error = -ENOMEM;
/*
@@ -522,55 +606,7 @@ libxfs_initialize_perag(
}
}
- /*
- * If we mount with the inode64 option, or no inode overflows
- * the legacy 32-bit address space clear the inode32 option.
- */
- agino = XFS_AGB_TO_AGINO(mp, sbp->sb_agblocks - 1);
- ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
-
- if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
- mp->m_flags |= XFS_MOUNT_32BITINODES;
- else
- mp->m_flags &= ~XFS_MOUNT_32BITINODES;
-
- if (mp->m_flags & XFS_MOUNT_32BITINODES) {
- /*
- * Calculate how much should be reserved for inodes to meet
- * the max inode percentage.
- */
- if (M_IGEO(mp)->maxicount) {
- uint64_t icount;
-
- icount = sbp->sb_dblocks * sbp->sb_imax_pct;
- do_div(icount, 100);
- icount += sbp->sb_agblocks - 1;
- do_div(icount, sbp->sb_agblocks);
- max_metadata = icount;
- } else {
- max_metadata = agcount;
- }
-
- for (index = 0; index < agcount; index++) {
- ino = XFS_AGINO_TO_INO(mp, index, agino);
- if (ino > XFS_MAXINUMBER_32) {
- index++;
- break;
- }
-
- pag = xfs_perag_get(mp, index);
- pag->pagi_inodeok = 1;
- if (index < max_metadata)
- pag->pagf_metadata = 1;
- xfs_perag_put(pag);
- }
- } else {
- for (index = 0; index < agcount; index++) {
- pag = xfs_perag_get(mp, index);
- pag->pagi_inodeok = 1;
- xfs_perag_put(pag);
- }
- }
+ index = xfs_set_inode_alloc(mp, agcount);
if (maxagi)
*maxagi = index;