linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / xfs / xfs_ialloc.c
index 33164a8..8f3fae1 100644 (file)
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
+#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
+#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -134,8 +136,10 @@ 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 = 0;  /* inode allocation at stripe unit */
+       int             isaligned;      /* inode allocation at stripe unit */
                                        /* boundary */
+       xfs_dinode_core_t dic;          /* a dinode_core to copy to new */
+                                       /* inodes */
 
        args.tp = tp;
        args.mp = tp->t_mountp;
@@ -150,75 +154,46 @@ xfs_ialloc_ag_alloc(
                return XFS_ERROR(ENOSPC);
        args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp);
        /*
-        * 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);
-       newino = be32_to_cpu(agi->agi_newino);
-       args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
-                       XFS_IALLOC_BLOCKS(args.mp);
-       if (likely(newino != NULLAGINO &&
-                 (args.agbno < be32_to_cpu(agi->agi_length)))) {
-               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;
+        * 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;
-               /*
-                * 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;
-       }
+       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;
 
        /*
         * If stripe alignment is turned on, then try again with cluster
@@ -275,6 +250,10 @@ xfs_ialloc_ag_alloc(
        else
                version = XFS_DINODE_VERSION_1;
 
+       memset(&dic, 0, sizeof(xfs_dinode_core_t));
+       INT_SET(dic.di_magic, ARCH_CONVERT, XFS_DINODE_MAGIC);
+       INT_SET(dic.di_version, ARCH_CONVERT, version);
+
        for (j = 0; j < nbufs; j++) {
                /*
                 * Get the block.
@@ -287,13 +266,12 @@ xfs_ialloc_ag_alloc(
                ASSERT(fbuf);
                ASSERT(!XFS_BUF_GETERROR(fbuf));
                /*
-                * Set initial values for the inodes in this buffer.
+                * Loop over the inodes in this buffer.
                 */
-               xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog);
+
                for (i = 0; i < ninodes; i++) {
                        free = XFS_MAKE_IPTR(args.mp, fbuf, i);
-                       INT_SET(free->di_core.di_magic, ARCH_CONVERT, XFS_DINODE_MAGIC);
-                       INT_SET(free->di_core.di_version, ARCH_CONVERT, version);
+                       memcpy(&(free->di_core), &dic, sizeof(xfs_dinode_core_t));
                        INT_SET(free->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
                        xfs_ialloc_log_di(tp, fbuf, i,
                                XFS_DI_CORE_BITS | XFS_DI_NEXT_UNLINKED);
@@ -1050,7 +1028,7 @@ xfs_difree(
        rec.ir_freecount++;
 
        /*
-        * When an inode cluster is free, it becomes eligible for removal
+        * When an inode cluster is free, it becomes elgible for removal
         */
        if ((mp->m_flags & XFS_MOUNT_IDELETE) &&
            (rec.ir_freecount == XFS_IALLOC_INODES(mp))) {
@@ -1172,9 +1150,6 @@ xfs_dilocate(
        if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
            ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
 #ifdef DEBUG
-               /* no diagnostics for bulkstat, ino comes from userspace */
-               if (flags & XFS_IMAP_BULKSTAT)
-                       return XFS_ERROR(EINVAL);
                if (agno >= mp->m_sb.sb_agcount) {
                        xfs_fs_cmn_err(CE_ALERT, mp,
                                        "xfs_dilocate: agno (%d) >= "