xfs: fix overflow in xfs_growfs_data_private
[safe/jmp/linux-2.6] / fs / xfs / xfs_fsops.c
index eadc159..cbd451b 100644 (file)
@@ -77,36 +77,38 @@ xfs_fs_geometry(
        if (new_version >= 3) {
                geo->version = XFS_FSOP_GEOM_VERSION;
                geo->flags =
-                       (XFS_SB_VERSION_HASATTR(&mp->m_sb) ?
+                       (xfs_sb_version_hasattr(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_ATTR : 0) |
-                       (XFS_SB_VERSION_HASNLINK(&mp->m_sb) ?
+                       (xfs_sb_version_hasnlink(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_NLINK : 0) |
-                       (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) ?
+                       (xfs_sb_version_hasquota(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_QUOTA : 0) |
-                       (XFS_SB_VERSION_HASALIGN(&mp->m_sb) ?
+                       (xfs_sb_version_hasalign(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_IALIGN : 0) |
-                       (XFS_SB_VERSION_HASDALIGN(&mp->m_sb) ?
+                       (xfs_sb_version_hasdalign(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_DALIGN : 0) |
-                       (XFS_SB_VERSION_HASSHARED(&mp->m_sb) ?
+                       (xfs_sb_version_hasshared(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_SHARED : 0) |
-                       (XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) ?
+                       (xfs_sb_version_hasextflgbit(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_EXTFLG : 0) |
-                       (XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ?
+                       (xfs_sb_version_hasdirv2(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) |
-                       (XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
+                       (xfs_sb_version_hassector(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_SECTOR : 0) |
+                       (xfs_sb_version_hasasciici(&mp->m_sb) ?
+                               XFS_FSOP_GEOM_FLAGS_DIRV2CI : 0) |
                        (xfs_sb_version_haslazysbcount(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) |
-                       (XFS_SB_VERSION_HASATTR2(&mp->m_sb) ?
+                       (xfs_sb_version_hasattr2(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_ATTR2 : 0);
-               geo->logsectsize = XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
+               geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ?
                                mp->m_sb.sb_logsectsize : BBSIZE;
                geo->rtsectsize = mp->m_sb.sb_blocksize;
                geo->dirblocksize = mp->m_dirblksize;
        }
        if (new_version >= 4) {
                geo->flags |=
-                       (XFS_SB_VERSION_HASLOGV2(&mp->m_sb) ?
+                       (xfs_sb_version_haslogv2(&mp->m_sb) ?
                                XFS_FSOP_GEOM_FLAGS_LOGV2 : 0);
                geo->logsunit = mp->m_sb.sb_logsunit;
        }
@@ -124,7 +126,7 @@ xfs_growfs_data_private(
        xfs_extlen_t            agsize;
        xfs_extlen_t            tmpsize;
        xfs_alloc_rec_t         *arec;
-       xfs_btree_sblock_t      *block;
+       struct xfs_btree_block  *block;
        xfs_buf_t               *bp;
        int                     bucket;
        int                     dpct;
@@ -158,7 +160,7 @@ 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);
        }
@@ -249,14 +251,14 @@ xfs_growfs_data_private(
                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);
-               block = XFS_BUF_TO_SBLOCK(bp);
+               block = XFS_BUF_TO_BLOCK(bp);
                memset(block, 0, mp->m_sb.sb_blocksize);
                block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
                block->bb_level = 0;
                block->bb_numrecs = cpu_to_be16(1);
-               block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
-               block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
-               arec = XFS_BTREE_REC_ADDR(xfs_alloc, block, 1);
+               block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
+               block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+               arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
                arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
                arec->ar_blockcount = cpu_to_be32(
                        agsize - be32_to_cpu(arec->ar_startblock));
@@ -270,14 +272,14 @@ xfs_growfs_data_private(
                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);
-               block = XFS_BUF_TO_SBLOCK(bp);
+               block = XFS_BUF_TO_BLOCK(bp);
                memset(block, 0, mp->m_sb.sb_blocksize);
                block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
                block->bb_level = 0;
                block->bb_numrecs = cpu_to_be16(1);
-               block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
-               block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
-               arec = XFS_BTREE_REC_ADDR(xfs_alloc, block, 1);
+               block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
+               block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+               arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
                arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
                arec->ar_blockcount = cpu_to_be32(
                        agsize - be32_to_cpu(arec->ar_startblock));
@@ -292,13 +294,13 @@ xfs_growfs_data_private(
                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);
-               block = XFS_BUF_TO_SBLOCK(bp);
+               block = XFS_BUF_TO_BLOCK(bp);
                memset(block, 0, mp->m_sb.sb_blocksize);
                block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
                block->bb_level = 0;
                block->bb_numrecs = 0;
-               block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
-               block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+               block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
+               block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
                error = xfs_bwrite(mp, bp);
                if (error) {
                        goto error0;
@@ -433,6 +435,9 @@ xfs_growfs_data(
        xfs_growfs_data_t       *in)
 {
        int error;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return XFS_ERROR(EPERM);
        if (!mutex_trylock(&mp->m_growlock))
                return XFS_ERROR(EWOULDBLOCK);
        error = xfs_growfs_data_private(mp, in);
@@ -446,6 +451,9 @@ xfs_growfs_log(
        xfs_growfs_log_t        *in)
 {
        int error;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return XFS_ERROR(EPERM);
        if (!mutex_trylock(&mp->m_growlock))
                return XFS_ERROR(EWOULDBLOCK);
        error = xfs_growfs_log_private(mp, in);
@@ -462,7 +470,7 @@ xfs_fs_counts(
        xfs_mount_t             *mp,
        xfs_fsop_counts_t       *cnt)
 {
-       xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
+       xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
        spin_lock(&mp->m_sb_lock);
        cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
        cnt->freertx = mp->m_sb.sb_frextents;
@@ -524,7 +532,7 @@ xfs_reserve_blocks(
         */
 retry:
        spin_lock(&mp->m_sb_lock);
-       xfs_icsb_sync_counters_flags(mp, XFS_ICSB_SB_LOCKED);
+       xfs_icsb_sync_counters_locked(mp, 0);
 
        /*
         * If our previous reservation was larger than the current value,
@@ -552,11 +560,8 @@ retry:
                        mp->m_resblks += free;
                        mp->m_resblks_avail += free;
                        fdblks_delta = -free;
-                       mp->m_sb.sb_fdblocks = XFS_ALLOC_SET_ASIDE(mp);
                } else {
                        fdblks_delta = -delta;
-                       mp->m_sb.sb_fdblocks =
-                               lcounter + XFS_ALLOC_SET_ASIDE(mp);
                        mp->m_resblks = request;
                        mp->m_resblks_avail += delta;
                }
@@ -571,7 +576,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
@@ -587,21 +592,22 @@ out:
                if (error == ENOSPC)
                        goto retry;
        }
-
        return 0;
 }
 
-void
+int
 xfs_fs_log_dummy(
        xfs_mount_t     *mp)
 {
        xfs_trans_t     *tp;
        xfs_inode_t     *ip;
+       int             error;
 
        tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
-       if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) {
+       error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
+       if (error) {
                xfs_trans_cancel(tp, 0);
-               return;
+               return error;
        }
 
        ip = mp->m_rootip;
@@ -611,9 +617,10 @@ xfs_fs_log_dummy(
        xfs_trans_ihold(tp, ip);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        xfs_trans_set_sync(tp);
-       xfs_trans_commit(tp, 0);
+       error = xfs_trans_commit(tp, 0);
 
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
+       return error;
 }
 
 int
@@ -629,7 +636,7 @@ xfs_fs_goingdown(
                        xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
                        thaw_bdev(sb->s_bdev, sb);
                }
-       
+
                break;
        }
        case XFS_FSOP_GOING_FLAGS_LOGFLUSH: