xfs: factor out xfs_da_grow_inode_int
authorChristoph Hellwig <hch@lst.de>
Wed, 13 Jul 2011 11:43:49 +0000 (13:43 +0200)
committerChristoph Hellwig <hch@lst.de>
Wed, 13 Jul 2011 11:43:49 +0000 (13:43 +0200)
xfs_da_grow_inode and xfs_dir2_grow_inode are mostly duplicate code.  Factor
the meat of those two functions into a new common helper.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Alex Elder <aelder@sgi.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_da_btree.h
fs/xfs/xfs_dir2.c

index a58a6410c58de018db2a2e845effeda2c43b4c28..73b048f7eb71f0d112cae5584428b43802f4dba9 100644 (file)
@@ -1543,79 +1543,62 @@ const struct xfs_nameops xfs_default_nameops = {
        .compname       = xfs_da_compname
 };
 
-/*
- * Add a block to the btree ahead of the file.
- * Return the new block number to the caller.
- */
 int
-xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
+xfs_da_grow_inode_int(
+       struct xfs_da_args      *args,
+       xfs_fileoff_t           *bno,
+       int                     count)
 {
-       xfs_fileoff_t bno, b;
-       xfs_bmbt_irec_t map;
-       xfs_bmbt_irec_t *mapp;
-       xfs_inode_t *dp;
-       int nmap, error, w, count, c, got, i, mapi;
-       xfs_trans_t *tp;
-       xfs_mount_t *mp;
-       xfs_drfsbno_t   nblks;
+       struct xfs_trans        *tp = args->trans;
+       struct xfs_inode        *dp = args->dp;
+       int                     w = args->whichfork;
+       xfs_drfsbno_t           nblks = dp->i_d.di_nblocks;
+       struct xfs_bmbt_irec    map, *mapp;
+       int                     nmap, error, got, i, mapi;
 
-       dp = args->dp;
-       mp = dp->i_mount;
-       w = args->whichfork;
-       tp = args->trans;
-       nblks = dp->i_d.di_nblocks;
-
-       /*
-        * For new directories adjust the file offset and block count.
-        */
-       if (w == XFS_DATA_FORK) {
-               bno = mp->m_dirleafblk;
-               count = mp->m_dirblkfsbs;
-       } else {
-               bno = 0;
-               count = 1;
-       }
        /*
         * Find a spot in the file space to put the new block.
         */
-       if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w)))
+       error = xfs_bmap_first_unused(tp, dp, count, bno, w);
+       if (error)
                return error;
-       if (w == XFS_DATA_FORK)
-               ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk);
+
        /*
         * Try mapping it in one filesystem block.
         */
        nmap = 1;
        ASSERT(args->firstblock != NULL);
-       if ((error = xfs_bmapi(tp, dp, bno, count,
+       error = xfs_bmapi(tp, dp, *bno, count,
                        xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|
                        XFS_BMAPI_CONTIG,
                        args->firstblock, args->total, &map, &nmap,
-                       args->flist))) {
+                       args->flist);
+       if (error)
                return error;
-       }
+
        ASSERT(nmap <= 1);
        if (nmap == 1) {
                mapp = &map;
                mapi = 1;
-       }
-       /*
-        * If we didn't get it and the block might work if fragmented,
-        * try without the CONTIG flag.  Loop until we get it all.
-        */
-       else if (nmap == 0 && count > 1) {
+       } else if (nmap == 0 && count > 1) {
+               xfs_fileoff_t           b;
+               int                     c;
+
+               /*
+                * If we didn't get it and the block might work if fragmented,
+                * try without the CONTIG flag.  Loop until we get it all.
+                */
                mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
-               for (b = bno, mapi = 0; b < bno + count; ) {
+               for (b = *bno, mapi = 0; b < *bno + count; ) {
                        nmap = MIN(XFS_BMAP_MAX_NMAP, count);
-                       c = (int)(bno + count - b);
-                       if ((error = xfs_bmapi(tp, dp, b, c,
+                       c = (int)(*bno + count - b);
+                       error = xfs_bmapi(tp, dp, b, c,
                                        xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|
                                        XFS_BMAPI_METADATA,
                                        args->firstblock, args->total,
-                                       &mapp[mapi], &nmap, args->flist))) {
-                               kmem_free(mapp);
-                               return error;
-                       }
+                                       &mapp[mapi], &nmap, args->flist);
+                       if (error)
+                               goto out_free_map;
                        if (nmap < 1)
                                break;
                        mapi += nmap;
@@ -1626,24 +1609,53 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
                mapi = 0;
                mapp = NULL;
        }
+
        /*
         * Count the blocks we got, make sure it matches the total.
         */
        for (i = 0, got = 0; i < mapi; i++)
                got += mapp[i].br_blockcount;
-       if (got != count || mapp[0].br_startoff != bno ||
+       if (got != count || mapp[0].br_startoff != *bno ||
            mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
-           bno + count) {
-               if (mapp != &map)
-                       kmem_free(mapp);
-               return XFS_ERROR(ENOSPC);
+           *bno + count) {
+               error = XFS_ERROR(ENOSPC);
+               goto out_free_map;
        }
-       if (mapp != &map)
-               kmem_free(mapp);
+
        /* account for newly allocated blocks in reserved blocks total */
        args->total -= dp->i_d.di_nblocks - nblks;
-       *new_blkno = (xfs_dablk_t)bno;
-       return 0;
+
+out_free_map:
+       if (mapp != &map)
+               kmem_free(mapp);
+       return error;
+}
+
+/*
+ * Add a block to the btree ahead of the file.
+ * Return the new block number to the caller.
+ */
+int
+xfs_da_grow_inode(
+       struct xfs_da_args      *args,
+       xfs_dablk_t             *new_blkno)
+{
+       xfs_fileoff_t           bno;
+       int                     count;
+       int                     error;
+
+       if (args->whichfork == XFS_DATA_FORK) {
+               bno = args->dp->i_mount->m_dirleafblk;
+               count = args->dp->i_mount->m_dirblkfsbs;
+       } else {
+               bno = 0;
+               count = 1;
+       }
+
+       error = xfs_da_grow_inode_int(args, &bno, count);
+       if (!error)
+               *new_blkno = (xfs_dablk_t)bno;
+       return error;
 }
 
 /*
index fe9f5a8c1d2a56794e083465ff54280cb49450d5..7b0a6ea59a0470d5ab3624f9d8152c4dc83f97e1 100644 (file)
@@ -248,6 +248,8 @@ int xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
  * Utility routines.
  */
 int    xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno);
+int    xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno,
+                             int count);
 int    xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp,
                              xfs_dablk_t bno, xfs_daddr_t mappedbno,
                              xfs_dabuf_t **bp, int whichfork);
index 6effbeb24e5aa7e0efa9ec566b31dae6e2a1fd7b..4580ce00aeb4afefee164bb570dc3414c31c16c2 100644 (file)
@@ -497,129 +497,34 @@ xfs_dir_canenter(
 
 /*
  * Add a block to the directory.
- * This routine is for data and free blocks, not leaf/node blocks
- * which are handled by xfs_da_grow_inode.
+ *
+ * This routine is for data and free blocks, not leaf/node blocks which are
+ * handled by xfs_da_grow_inode.
  */
 int
 xfs_dir2_grow_inode(
-       xfs_da_args_t   *args,
-       int             space,          /* v2 dir's space XFS_DIR2_xxx_SPACE */
-       xfs_dir2_db_t   *dbp)           /* out: block number added */
+       struct xfs_da_args      *args,
+       int                     space,  /* v2 dir's space XFS_DIR2_xxx_SPACE */
+       xfs_dir2_db_t           *dbp)   /* out: block number added */
 {
-       xfs_fileoff_t   bno;            /* directory offset of new block */
-       int             count;          /* count of filesystem blocks */
-       xfs_inode_t     *dp;            /* incore directory inode */
-       int             error;
-       int             got;            /* blocks actually mapped */
-       int             i;
-       xfs_bmbt_irec_t map;            /* single structure for bmap */
-       int             mapi;           /* mapping index */
-       xfs_bmbt_irec_t *mapp;          /* bmap mapping structure(s) */
-       xfs_mount_t     *mp;
-       int             nmap;           /* number of bmap entries */
-       xfs_trans_t     *tp;
-       xfs_drfsbno_t   nblks;
+       struct xfs_inode        *dp = args->dp;
+       struct xfs_mount        *mp = dp->i_mount;
+       xfs_fileoff_t           bno;    /* directory offset of new block */
+       int                     count;  /* count of filesystem blocks */
+       int                     error;
 
        trace_xfs_dir2_grow_inode(args, space);
 
-       dp = args->dp;
-       tp = args->trans;
-       mp = dp->i_mount;
-       nblks = dp->i_d.di_nblocks;
        /*
         * Set lowest possible block in the space requested.
         */
        bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
        count = mp->m_dirblkfsbs;
-       /*
-        * Find the first hole for our block.
-        */
-       if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))
-               return error;
-       nmap = 1;
-       ASSERT(args->firstblock != NULL);
-       /*
-        * Try mapping the new block contiguously (one extent).
-        */
-       if ((error = xfs_bmapi(tp, dp, bno, count,
-                       XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
-                       args->firstblock, args->total, &map, &nmap,
-                       args->flist)))
-               return error;
-       ASSERT(nmap <= 1);
-       if (nmap == 1) {
-               mapp = &map;
-               mapi = 1;
-       }
-       /*
-        * Didn't work and this is a multiple-fsb directory block.
-        * Try again with contiguous flag turned on.
-        */
-       else if (nmap == 0 && count > 1) {
-               xfs_fileoff_t   b;      /* current file offset */
 
-               /*
-                * Space for maximum number of mappings.
-                */
-               mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
-               /*
-                * Iterate until we get to the end of our block.
-                */
-               for (b = bno, mapi = 0; b < bno + count; ) {
-                       int     c;      /* current fsb count */
-
-                       /*
-                        * Can't map more than MAX_NMAP at once.
-                        */
-                       nmap = MIN(XFS_BMAP_MAX_NMAP, count);
-                       c = (int)(bno + count - b);
-                       if ((error = xfs_bmapi(tp, dp, b, c,
-                                       XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
-                                       args->firstblock, args->total,
-                                       &mapp[mapi], &nmap, args->flist))) {
-                               kmem_free(mapp);
-                               return error;
-                       }
-                       if (nmap < 1)
-                               break;
-                       /*
-                        * Add this bunch into our table, go to the next offset.
-                        */
-                       mapi += nmap;
-                       b = mapp[mapi - 1].br_startoff +
-                           mapp[mapi - 1].br_blockcount;
-               }
-       }
-       /*
-        * Didn't work.
-        */
-       else {
-               mapi = 0;
-               mapp = NULL;
-       }
-       /*
-        * See how many fsb's we got.
-        */
-       for (i = 0, got = 0; i < mapi; i++)
-               got += mapp[i].br_blockcount;
-       /*
-        * Didn't get enough fsb's, or the first/last block's are wrong.
-        */
-       if (got != count || mapp[0].br_startoff != bno ||
-           mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
-           bno + count) {
-               if (mapp != &map)
-                       kmem_free(mapp);
-               return XFS_ERROR(ENOSPC);
-       }
-       /*
-        * Done with the temporary mapping table.
-        */
-       if (mapp != &map)
-               kmem_free(mapp);
+       error = xfs_da_grow_inode_int(args, &bno, count);
+       if (error)
+               return error;
 
-       /* account for newly allocated blocks in reserved blocks total */
-       args->total -= dp->i_d.di_nblocks - nblks;
        *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
 
        /*
@@ -631,7 +536,7 @@ xfs_dir2_grow_inode(
                size = XFS_FSB_TO_B(mp, bno + count);
                if (size > dp->i_d.di_size) {
                        dp->i_d.di_size = size;
-                       xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
+                       xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
                }
        }
        return 0;