Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[safe/jmp/linux-2.6] / fs / xfs / xfs_fsops.c
index 680d0e0..a13919a 100644 (file)
@@ -45,6 +45,7 @@
 #include "xfs_rtalloc.h"
 #include "xfs_rw.h"
 #include "xfs_filestream.h"
+#include "xfs_trace.h"
 
 /*
  * File system operations
@@ -160,24 +161,32 @@ xfs_growfs_data_private(
        nagcount = new + (nb_mod != 0);
        if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) {
                nagcount--;
-               nb = nagcount * mp->m_sb.sb_agblocks;
+               nb = (xfs_rfsblock_t)nagcount * mp->m_sb.sb_agblocks;
                if (nb < mp->m_sb.sb_dblocks)
                        return XFS_ERROR(EINVAL);
        }
        new = nb - mp->m_sb.sb_dblocks;
        oagcount = mp->m_sb.sb_agcount;
        if (nagcount > oagcount) {
+               void *new_perag, *old_perag;
+
                xfs_filestream_flush(mp);
+
+               new_perag = kmem_zalloc(sizeof(xfs_perag_t) * nagcount,
+                                       KM_MAYFAIL);
+               if (!new_perag)
+                       return XFS_ERROR(ENOMEM);
+
                down_write(&mp->m_peraglock);
-               mp->m_perag = kmem_realloc(mp->m_perag,
-                       sizeof(xfs_perag_t) * nagcount,
-                       sizeof(xfs_perag_t) * oagcount,
-                       KM_SLEEP);
-               memset(&mp->m_perag[oagcount], 0,
-                       (nagcount - oagcount) * sizeof(xfs_perag_t));
+               memcpy(new_perag, mp->m_perag, sizeof(xfs_perag_t) * oagcount);
+               old_perag = mp->m_perag;
+               mp->m_perag = new_perag;
+
                mp->m_flags |= XFS_MOUNT_32BITINODES;
                nagimax = xfs_initialize_perag(mp, nagcount);
                up_write(&mp->m_peraglock);
+
+               kmem_free(old_perag);
        }
        tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
        tp->t_flags |= XFS_TRANS_RESERVE;
@@ -193,8 +202,8 @@ xfs_growfs_data_private(
                 * AG freelist header block
                 */
                bp = xfs_buf_get(mp->m_ddev_targp,
-                                 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
-                                 XFS_FSS_TO_BB(mp, 1), 0);
+                                XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
+                                XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED);
                agf = XFS_BUF_TO_AGF(bp);
                memset(agf, 0, mp->m_sb.sb_sectsize);
                agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
@@ -225,8 +234,8 @@ xfs_growfs_data_private(
                 * AG inode header block
                 */
                bp = xfs_buf_get(mp->m_ddev_targp,
-                                 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
-                                 XFS_FSS_TO_BB(mp, 1), 0);
+                                XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
+                                XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED);
                agi = XFS_BUF_TO_AGI(bp);
                memset(agi, 0, mp->m_sb.sb_sectsize);
                agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
@@ -249,8 +258,9 @@ xfs_growfs_data_private(
                 * BNO btree root block
                 */
                bp = xfs_buf_get(mp->m_ddev_targp,
-                       XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
-                       BTOBB(mp->m_sb.sb_blocksize), 0);
+                                XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
+                                BTOBB(mp->m_sb.sb_blocksize),
+                                XBF_LOCK | XBF_MAPPED);
                block = XFS_BUF_TO_BLOCK(bp);
                memset(block, 0, mp->m_sb.sb_blocksize);
                block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
@@ -270,8 +280,9 @@ xfs_growfs_data_private(
                 * CNT btree root block
                 */
                bp = xfs_buf_get(mp->m_ddev_targp,
-                       XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
-                       BTOBB(mp->m_sb.sb_blocksize), 0);
+                                XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
+                                BTOBB(mp->m_sb.sb_blocksize),
+                                XBF_LOCK | XBF_MAPPED);
                block = XFS_BUF_TO_BLOCK(bp);
                memset(block, 0, mp->m_sb.sb_blocksize);
                block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
@@ -292,8 +303,9 @@ xfs_growfs_data_private(
                 * INO btree root block
                 */
                bp = xfs_buf_get(mp->m_ddev_targp,
-                       XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
-                       BTOBB(mp->m_sb.sb_blocksize), 0);
+                                XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
+                                BTOBB(mp->m_sb.sb_blocksize),
+                                XBF_LOCK | XBF_MAPPED);
                block = XFS_BUF_TO_BLOCK(bp);
                memset(block, 0, mp->m_sb.sb_blocksize);
                block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
@@ -336,6 +348,7 @@ xfs_growfs_data_private(
                be32_add_cpu(&agf->agf_length, new);
                ASSERT(be32_to_cpu(agf->agf_length) ==
                       be32_to_cpu(agi->agi_length));
+
                xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH);
                /*
                 * Free the new space.
@@ -576,7 +589,7 @@ out:
        if (fdblks_delta) {
                /*
                 * If we are putting blocks back here, m_resblks_avail is
-                * already at it's max so this will put it in the free pool.
+                * already at its max so this will put it in the free pool.
                 *
                 * If we need space, we'll either succeed in getting it
                 * from the free block count or we'll get an enospc. If
@@ -603,7 +616,7 @@ xfs_fs_log_dummy(
        xfs_inode_t     *ip;
        int             error;
 
-       tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
+       tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1, KM_SLEEP);
        error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
        if (error) {
                xfs_trans_cancel(tp, 0);