[XFS] A change to inode chunk allocation to try allocating the new chunk
authorGlen Overby <overby@sgi.com>
Tue, 28 Mar 2006 23:52:28 +0000 (09:52 +1000)
committerNathan Scott <nathans@sgi.com>
Tue, 28 Mar 2006 23:52:28 +0000 (09:52 +1000)
contiguous with the most recently allocated chunk.  On a striped
filesystem, this will fill a stripe unit with inodes before allocating new
inodes in another stripe unit.

SGI-PV: 951416
SGI-Modid: xfs-linux-melb:xfs-kern:208488a

Signed-off-by: Glen Overby <overby@sgi.com>
Signed-off-by: Nathan Scott <nathans@sgi.com>
fs/xfs/xfs_ialloc.c

index 20c39a6..4eeb856 100644 (file)
@@ -136,7 +136,7 @@ xfs_ialloc_ag_alloc(
        int             ninodes;        /* num inodes per buf */
        xfs_agino_t     thisino;        /* current inode number, for loop */
        int             version;        /* inode version number to use */
-       int             isaligned;      /* inode allocation at stripe unit */
+       int             isaligned = 0;  /* inode allocation at stripe unit */
                                        /* boundary */
 
        args.tp = tp;
@@ -152,47 +152,75 @@ xfs_ialloc_ag_alloc(
                return XFS_ERROR(ENOSPC);
        args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp);
        /*
-        * Set the alignment for the allocation.
-        * If stripe alignment is turned on then align at stripe unit
-        * boundary.
-        * If the cluster size is smaller than a filesystem block
-        * then we're doing I/O for inodes in filesystem block size pieces,
-        * so don't need alignment anyway.
-        */
-       isaligned = 0;
-       if (args.mp->m_sinoalign) {
-               ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
-               args.alignment = args.mp->m_dalign;
-               isaligned = 1;
-       } else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
-           args.mp->m_sb.sb_inoalignmt >=
-           XFS_B_TO_FSBT(args.mp, XFS_INODE_CLUSTER_SIZE(args.mp)))
-               args.alignment = args.mp->m_sb.sb_inoalignmt;
-       else
-               args.alignment = 1;
+        * First try to allocate inodes contiguous with the last-allocated
+        * chunk of inodes.  If the filesystem is striped, this will fill
+        * an entire stripe unit with inodes.
+        */
        agi = XFS_BUF_TO_AGI(agbp);
-       /*
-        * Need to figure out where to allocate the inode blocks.
-        * Ideally they should be spaced out through the a.g.
-        * For now, just allocate blocks up front.
-        */
-       args.agbno = be32_to_cpu(agi->agi_root);
-       args.fsbno = XFS_AGB_TO_FSB(args.mp, be32_to_cpu(agi->agi_seqno),
-                                   args.agbno);
-       /*
-        * Allocate a fixed-size extent of inodes.
-        */
-       args.type = XFS_ALLOCTYPE_NEAR_BNO;
-       args.mod = args.total = args.wasdel = args.isfl = args.userdata =
-               args.minalignslop = 0;
-       args.prod = 1;
-       /*
-        * Allow space for the inode btree to split.
-        */
-       args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
-       if ((error = xfs_alloc_vextent(&args)))
-               return error;
+       newino = be32_to_cpu(agi->agi_newino);
+       if(likely(newino != NULLAGINO)) {
+               args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
+                               XFS_IALLOC_BLOCKS(args.mp);
+               args.fsbno = XFS_AGB_TO_FSB(args.mp,
+                               be32_to_cpu(agi->agi_seqno), args.agbno);
+               args.type = XFS_ALLOCTYPE_THIS_BNO;
+               args.mod = args.total = args.wasdel = args.isfl =
+                       args.userdata = args.minalignslop = 0;
+               args.prod = 1;
+               args.alignment = 1;
+               /*
+                * Allow space for the inode btree to split.
+                */
+               args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
+               if ((error = xfs_alloc_vextent(&args)))
+                       return error;
+       } else
+               args.fsbno = NULLFSBLOCK;
 
+       if (unlikely(args.fsbno == NULLFSBLOCK)) {
+               /*
+                * Set the alignment for the allocation.
+                * If stripe alignment is turned on then align at stripe unit
+                * boundary.
+                * If the cluster size is smaller than a filesystem block 
+                * then we're doing I/O for inodes in filesystem block size 
+                * pieces, so don't need alignment anyway.
+                */
+               isaligned = 0;
+               if (args.mp->m_sinoalign) {
+                       ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
+                       args.alignment = args.mp->m_dalign;
+                       isaligned = 1;
+               } else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
+                          args.mp->m_sb.sb_inoalignmt >= 
+                          XFS_B_TO_FSBT(args.mp,
+                               XFS_INODE_CLUSTER_SIZE(args.mp)))
+                               args.alignment = args.mp->m_sb.sb_inoalignmt;
+               else
+                       args.alignment = 1;
+               /*
+                * Need to figure out where to allocate the inode blocks.
+                * Ideally they should be spaced out through the a.g.
+                * For now, just allocate blocks up front.
+                */
+               args.agbno = be32_to_cpu(agi->agi_root);
+               args.fsbno = XFS_AGB_TO_FSB(args.mp,
+                               be32_to_cpu(agi->agi_seqno), args.agbno);
+               /*
+                * Allocate a fixed-size extent of inodes.
+                */
+               args.type = XFS_ALLOCTYPE_NEAR_BNO;
+               args.mod = args.total = args.wasdel = args.isfl =
+                       args.userdata = args.minalignslop = 0;
+               args.prod = 1;
+               /*
+                * Allow space for the inode btree to split.
+                */
+               args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
+               if ((error = xfs_alloc_vextent(&args)))
+                       return error;
+       }
        /*
         * If stripe alignment is turned on, then try again with cluster
         * alignment.