]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libxfs: port xfs_set_inode_alloc from the kernel
authorDarrick J. Wong <djwong@kernel.org>
Fri, 1 Oct 2021 18:00:34 +0000 (14:00 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Fri, 1 Oct 2021 18:00:34 +0000 (14:00 -0400)
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.

(sandeen: Note that this is in effect simply syncing up several
kernel commits in this code which was not shared via libxfs.)

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/init.c

index 2c54546bcdda132429586362d2103ce4e7aeb061..17fc11023c19652dbe8f7099335e1bee2d8582fc 100644 (file)
@@ -484,18 +484,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;
 
        /*
@@ -524,55 +608,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;