hwmon: add TI ads7871 a/d converter driver
[safe/jmp/linux-2.6] / fs / xfs / xfs_fsops.c
index 84583cf..37a6f62 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
@@ -126,7 +127,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;
@@ -160,25 +161,20 @@ 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;
+
+       /* allocate the new per-ag structures */
        if (nagcount > oagcount) {
-               xfs_filestream_flush(mp);
-               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));
-               mp->m_flags |= XFS_MOUNT_32BITINODES;
-               nagimax = xfs_initialize_perag(mp, nagcount);
-               up_write(&mp->m_peraglock);
+               error = xfs_initialize_perag(mp, nagcount, &nagimax);
+               if (error)
+                       return error;
        }
+
        tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
        tp->t_flags |= XFS_TRANS_RESERVE;
        if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp),
@@ -187,14 +183,19 @@ xfs_growfs_data_private(
                return error;
        }
 
+       /*
+        * Write new AG headers to disk. Non-transactional, but written
+        * synchronously so they are completed prior to the growfs transaction
+        * being logged.
+        */
        nfree = 0;
        for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
                /*
                 * 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 +226,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,16 +250,17 @@ 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);
-               block = XFS_BUF_TO_SBLOCK(bp);
+                                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);
                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,16 +272,17 @@ 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);
-               block = XFS_BUF_TO_SBLOCK(bp);
+                                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);
                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,15 +295,16 @@ 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);
-               block = XFS_BUF_TO_SBLOCK(bp);
+                                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);
                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;
@@ -336,6 +340,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.
@@ -346,6 +351,12 @@ xfs_growfs_data_private(
                        goto error0;
                }
        }
+
+       /*
+        * Update changed superblock fields transactionally. These are not
+        * seen by the rest of the world until the transaction commit applies
+        * them atomically to the superblock.
+        */
        if (nagcount > oagcount)
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, nagcount - oagcount);
        if (nb > mp->m_sb.sb_dblocks)
@@ -356,9 +367,9 @@ xfs_growfs_data_private(
        if (dpct)
                xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct);
        error = xfs_trans_commit(tp, 0);
-       if (error) {
+       if (error)
                return error;
-       }
+
        /* New allocation groups fully initialized, so update mount struct */
        if (nagimax)
                mp->m_maxagi = nagimax;
@@ -368,6 +379,8 @@ xfs_growfs_data_private(
                mp->m_maxicount = icount << mp->m_sb.sb_inopblog;
        } else
                mp->m_maxicount = 0;
+
+       /* update secondary superblocks. */
        for (agno = 1; agno < nagcount; agno++) {
                error = xfs_read_buf(mp, mp->m_ddev_targp,
                                  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
@@ -435,6 +448,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);
@@ -448,6 +464,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);
@@ -570,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
@@ -589,17 +608,19 @@ out:
        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)) {
+       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);
-               return;
+               return error;
        }
 
        ip = mp->m_rootip;
@@ -609,9 +630,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