Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux...
[safe/jmp/linux-2.6] / fs / xfs / xfs_attr.c
index 78de80e..8fe6f6b 100644 (file)
@@ -45,7 +45,6 @@
 #include "xfs_error.h"
 #include "xfs_quota.h"
 #include "xfs_trans_space.h"
-#include "xfs_acl.h"
 #include "xfs_rw.h"
 #include "xfs_vnodeops.h"
 
@@ -124,9 +123,13 @@ xfs_inode_hasattr(
  * Overall external interface routines.
  *========================================================================*/
 
-int
-xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name,
-               char *value, int *valuelenp, int flags)
+STATIC int
+xfs_attr_get_int(
+       struct xfs_inode        *ip,
+       struct xfs_name         *name,
+       char                    *value,
+       int                     *valuelenp,
+       int                     flags)
 {
        xfs_da_args_t   args;
        int             error;
@@ -189,11 +192,51 @@ xfs_attr_get(
                return error;
 
        xfs_ilock(ip, XFS_ILOCK_SHARED);
-       error = xfs_attr_fetch(ip, &xname, value, valuelenp, flags);
+       error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags);
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
        return(error);
 }
 
+/*
+ * Calculate how many blocks we need for the new attribute,
+ */
+int
+xfs_attr_calc_size(
+       struct xfs_inode        *ip,
+       int                     namelen,
+       int                     valuelen,
+       int                     *local)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       int                     size;
+       int                     nblks;
+
+       /*
+        * Determine space new attribute will use, and if it would be
+        * "local" or "remote" (note: local != inline).
+        */
+       size = xfs_attr_leaf_newentsize(namelen, valuelen,
+                                       mp->m_sb.sb_blocksize, local);
+
+       nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
+       if (*local) {
+               if (size > (mp->m_sb.sb_blocksize >> 1)) {
+                       /* Double split possible */
+                       nblks *= 2;
+               }
+       } else {
+               /*
+                * Out of line attribute, cannot double split, but
+                * make room for the attribute value itself.
+                */
+               uint    dblocks = XFS_B_TO_FSB(mp, valuelen);
+               nblks += dblocks;
+               nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
+       }
+
+       return nblks;
+}
+
 STATIC int
 xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
                char *value, int valuelen, int flags)
@@ -202,16 +245,16 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
        xfs_fsblock_t   firstblock;
        xfs_bmap_free_t flist;
        int             error, err2, committed;
-       int             local, size;
-       uint            nblks;
        xfs_mount_t     *mp = dp->i_mount;
        int             rsvd = (flags & ATTR_ROOT) != 0;
+       int             local;
 
        /*
         * Attach the dquots to the inode.
         */
-       if ((error = XFS_QM_DQATTACH(mp, dp, 0)))
-               return (error);
+       error = xfs_qm_dqattach(dp, 0);
+       if (error)
+               return error;
 
        /*
         * If the inode doesn't have an attribute fork, add one.
@@ -241,30 +284,8 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
        args.whichfork = XFS_ATTR_FORK;
        args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
 
-       /*
-        * Determine space new attribute will use, and if it would be
-        * "local" or "remote" (note: local != inline).
-        */
-       size = xfs_attr_leaf_newentsize(name->len, valuelen,
-                                       mp->m_sb.sb_blocksize, &local);
-
-       nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
-       if (local) {
-               if (size > (mp->m_sb.sb_blocksize >> 1)) {
-                       /* Double split possible */
-                       nblks <<= 1;
-               }
-       } else {
-               uint    dblocks = XFS_B_TO_FSB(mp, valuelen);
-               /* Out of line attribute, cannot double split, but make
-                * room for the attribute value itself.
-                */
-               nblks += dblocks;
-               nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
-       }
-
        /* Size is now blocks for attribute data */
-       args.total = nblks;
+       args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local);
 
        /*
         * Start our first transaction of the day.
@@ -286,18 +307,17 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
        if (rsvd)
                args.trans->t_flags |= XFS_TRANS_RESERVE;
 
-       if ((error = xfs_trans_reserve(args.trans, (uint) nblks,
-                                     XFS_ATTRSET_LOG_RES(mp, nblks),
-                                     0, XFS_TRANS_PERM_LOG_RES,
-                                     XFS_ATTRSET_LOG_COUNT))) {
+       if ((error = xfs_trans_reserve(args.trans, args.total,
+                       XFS_ATTRSET_LOG_RES(mp, args.total), 0,
+                       XFS_TRANS_PERM_LOG_RES, XFS_ATTRSET_LOG_COUNT))) {
                xfs_trans_cancel(args.trans, 0);
                return(error);
        }
        xfs_ilock(dp, XFS_ILOCK_EXCL);
 
-       error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0,
-                        rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
-                               XFS_QMOPT_RES_REGBLKS);
+       error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0,
+                               rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
+                                      XFS_QMOPT_RES_REGBLKS);
        if (error) {
                xfs_iunlock(dp, XFS_ILOCK_EXCL);
                xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
@@ -358,7 +378,7 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
                 * It won't fit in the shortform, transform to a leaf block.
                 * GROT: another possible req'mt for a double-split btree op.
                 */
-               XFS_BMAP_INIT(args.flist, args.firstblock);
+               xfs_bmap_init(args.flist, args.firstblock);
                error = xfs_attr_shortform_to_leaf(&args);
                if (!error) {
                        error = xfs_bmap_finish(&args.trans, args.flist,
@@ -384,7 +404,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
                 * Commit the leaf transformation.  We'll need another (linked)
                 * transaction to add the new attribute to the leaf.
                 */
-               if ((error = xfs_attr_rolltrans(&args.trans, dp)))
+
+               error = xfs_trans_roll(&args.trans, dp);
+               if (error)
                        goto out;
 
        }
@@ -483,8 +505,9 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
        /*
         * Attach the dquots to the inode.
         */
-       if ((error = XFS_QM_DQATTACH(mp, dp, 0)))
-               return (error);
+       error = xfs_qm_dqattach(dp, 0);
+       if (error)
+               return error;
 
        /*
         * Start our first transaction of the day.
@@ -938,7 +961,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * Commit that transaction so that the node_addname() call
                 * can manage its own transactions.
                 */
-               XFS_BMAP_INIT(args->flist, args->firstblock);
+               xfs_bmap_init(args->flist, args->firstblock);
                error = xfs_attr_leaf_to_node(args);
                if (!error) {
                        error = xfs_bmap_finish(&args->trans, args->flist,
@@ -964,7 +987,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * Commit the current trans (including the inode) and start
                 * a new one.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        return (error);
 
                /*
@@ -978,7 +1002,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
         * Commit the transaction that added the attr name so that
         * later routines can manage their own transactions.
         */
-       if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+       error = xfs_trans_roll(&args->trans, dp);
+       if (error)
                return (error);
 
        /*
@@ -1037,7 +1062,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * If the result is small enough, shrink it all into the inode.
                 */
                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
-                       XFS_BMAP_INIT(args->flist, args->firstblock);
+                       xfs_bmap_init(args->flist, args->firstblock);
                        error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
                        /* bp is gone due to xfs_da_shrink_inode */
                        if (!error) {
@@ -1067,7 +1092,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                /*
                 * Commit the remove and start the next trans in series.
                 */
-               error = xfs_attr_rolltrans(&args->trans, dp);
+               error = xfs_trans_roll(&args->trans, dp);
 
        } else if (args->rmtblkno > 0) {
                /*
@@ -1115,7 +1140,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
         * If the result is small enough, shrink it all into the inode.
         */
        if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
-               XFS_BMAP_INIT(args->flist, args->firstblock);
+               xfs_bmap_init(args->flist, args->firstblock);
                error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
                /* bp is gone due to xfs_da_shrink_inode */
                if (!error) {
@@ -1270,7 +1295,7 @@ restart:
                         * have been a b-tree.
                         */
                        xfs_da_state_free(state);
-                       XFS_BMAP_INIT(args->flist, args->firstblock);
+                       xfs_bmap_init(args->flist, args->firstblock);
                        error = xfs_attr_leaf_to_node(args);
                        if (!error) {
                                error = xfs_bmap_finish(&args->trans,
@@ -1298,7 +1323,8 @@ restart:
                         * Commit the node conversion and start the next
                         * trans in the chain.
                         */
-                       if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+                       error = xfs_trans_roll(&args->trans, dp);
+                       if (error)
                                goto out;
 
                        goto restart;
@@ -1310,7 +1336,7 @@ restart:
                 * in the index/blkno/rmtblkno/rmtblkcnt fields and
                 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
                 */
-               XFS_BMAP_INIT(args->flist, args->firstblock);
+               xfs_bmap_init(args->flist, args->firstblock);
                error = xfs_da_split(state);
                if (!error) {
                        error = xfs_bmap_finish(&args->trans, args->flist,
@@ -1349,7 +1375,8 @@ restart:
         * Commit the leaf addition or btree split and start the next
         * trans in the chain.
         */
-       if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+       error = xfs_trans_roll(&args->trans, dp);
+       if (error)
                goto out;
 
        /*
@@ -1421,7 +1448,7 @@ restart:
                 * Check to see if the tree needs to be collapsed.
                 */
                if (retval && (state->path.active > 1)) {
-                       XFS_BMAP_INIT(args->flist, args->firstblock);
+                       xfs_bmap_init(args->flist, args->firstblock);
                        error = xfs_da_join(state);
                        if (!error) {
                                error = xfs_bmap_finish(&args->trans,
@@ -1449,7 +1476,8 @@ restart:
                /*
                 * Commit and start the next trans in the chain.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        goto out;
 
        } else if (args->rmtblkno > 0) {
@@ -1556,7 +1584,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
         * Check to see if the tree needs to be collapsed.
         */
        if (retval && (state->path.active > 1)) {
-               XFS_BMAP_INIT(args->flist, args->firstblock);
+               xfs_bmap_init(args->flist, args->firstblock);
                error = xfs_da_join(state);
                if (!error) {
                        error = xfs_bmap_finish(&args->trans, args->flist,
@@ -1581,7 +1609,8 @@ xfs_attr_node_removename(xfs_da_args_t *args)
                /*
                 * Commit the Btree join operation and start a new trans.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        goto out;
        }
 
@@ -1606,7 +1635,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
                                                       == XFS_ATTR_LEAF_MAGIC);
 
                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
-                       XFS_BMAP_INIT(args->flist, args->firstblock);
+                       xfs_bmap_init(args->flist, args->firstblock);
                        error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
                        /* bp is gone due to xfs_da_shrink_inode */
                        if (!error) {
@@ -1985,7 +2014,9 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
                        dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
                        blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
                        error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno,
-                                            blkcnt, XFS_BUF_LOCK, &bp);
+                                            blkcnt,
+                                            XFS_BUF_LOCK | XBF_DONT_BLOCK,
+                                            &bp);
                        if (error)
                                return(error);
 
@@ -2045,7 +2076,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
                /*
                 * Allocate a single extent, up to the size of the value.
                 */
-               XFS_BMAP_INIT(args->flist, args->firstblock);
+               xfs_bmap_init(args->flist, args->firstblock);
                nmap = 1;
                error = xfs_bmapi(args->trans, dp, (xfs_fileoff_t)lblkno,
                                  blkcnt,
@@ -2082,7 +2113,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
                /*
                 * Start the next trans in the chain.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, dp)))
+               error = xfs_trans_roll(&args->trans, dp);
+               if (error)
                        return (error);
        }
 
@@ -2098,7 +2130,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
                /*
                 * Try to remember where we decided to put the value.
                 */
-               XFS_BMAP_INIT(args->flist, args->firstblock);
+               xfs_bmap_init(args->flist, args->firstblock);
                nmap = 1;
                error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno,
                                  args->rmtblkcnt,
@@ -2115,8 +2147,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
                dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
                blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
 
-               bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno,
-                                                       blkcnt, XFS_BUF_LOCK);
+               bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt,
+                                XFS_BUF_LOCK | XBF_DONT_BLOCK);
                ASSERT(bp);
                ASSERT(!XFS_BUF_GETERROR(bp));
 
@@ -2163,7 +2195,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
                /*
                 * Try to remember where we decided to put the value.
                 */
-               XFS_BMAP_INIT(args->flist, args->firstblock);
+               xfs_bmap_init(args->flist, args->firstblock);
                nmap = 1;
                error = xfs_bmapi(NULL, args->dp, (xfs_fileoff_t)lblkno,
                                        args->rmtblkcnt,
@@ -2204,7 +2236,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
        blkcnt = args->rmtblkcnt;
        done = 0;
        while (!done) {
-               XFS_BMAP_INIT(args->flist, args->firstblock);
+               xfs_bmap_init(args->flist, args->firstblock);
                error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
                                    XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
                                    1, args->firstblock, args->flist,
@@ -2232,7 +2264,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
                /*
                 * Close out trans and start the next one in the chain.
                 */
-               if ((error = xfs_attr_rolltrans(&args->trans, args->dp)))
+               error = xfs_trans_roll(&args->trans, args->dp);
+               if (error)
                        return (error);
        }
        return(0);