linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / xfs / xfs_attr_leaf.c
index 444f341..fe91eac 100644 (file)
@@ -1,46 +1,26 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation.
  *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-/*
- * xfs_attr_leaf.c
- *
- * GROT: figure out how to recover gracefully when bmap returns ENOSPC.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
 #include "xfs.h"
-
-#include "xfs_macros.h"
+#include "xfs_fs.h"
 #include "xfs_types.h"
-#include "xfs_inum.h"
+#include "xfs_bit.h"
 #include "xfs_log.h"
+#include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
-#include "xfs_alloc_btree.h"
+#include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
+#include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
 #include "xfs_alloc.h"
 #include "xfs_btree.h"
-#include "xfs_attr_sf.h"
 #include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
+#include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
-#include "xfs_inode_item.h"
 #include "xfs_inode.h"
+#include "xfs_inode_item.h"
 #include "xfs_bmap.h"
-#include "xfs_da_btree.h"
 #include "xfs_attr.h"
 #include "xfs_attr_leaf.h"
 #include "xfs_error.h"
-#include "xfs_bit.h"
 
 /*
  * xfs_attr_leaf.c
@@ -79,6 +58,8 @@
 /*
  * Routines used for growing the Btree.
  */
+STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block,
+                                   xfs_dabuf_t **bpp);
 STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
                                              int freemap_index);
 STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer);
@@ -91,6 +72,16 @@ STATIC int xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
                                           int *number_entries_in_blk1,
                                           int *number_usedbytes_in_blk1);
 
+/*
+ * Routines used for shrinking the Btree.
+ */
+STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
+                                 xfs_dabuf_t *bp, int level);
+STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
+                                 xfs_dabuf_t *bp);
+STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
+                                  xfs_dablk_t blkno, int blkcnt);
+
 /*
  * Utility routines.
  */
@@ -99,16 +90,89 @@ STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
                                         xfs_attr_leafblock_t *dst_leaf,
                                         int dst_start, int move_count,
                                         xfs_mount_t *mp);
+STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
+STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context,
+                            attrnames_t *, char *name, int namelen,
+                            int valuelen);
 
 
 /*========================================================================
- * External routines when dirsize < XFS_LITINO(mp).
+ * External routines when attribute fork size < XFS_LITINO(mp).
  *========================================================================*/
 
 /*
- * Create the initial contents of a shortform attribute list.
+ * Query whether the requested number of additional bytes of extended
+ * attribute space will be able to fit inline.
+ * Returns zero if not, else the di_forkoff fork offset to be used in the
+ * literal area for attribute data once the new bytes have been added.
+ *
+ * di_forkoff must be 8 byte aligned, hence is stored as a >>3 value;
+ * special case for dev/uuid inodes, they have fixed size data forks.
  */
 int
+xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
+{
+       int offset;
+       int minforkoff; /* lower limit on valid forkoff locations */
+       int maxforkoff; /* upper limit on valid forkoff locations */
+       xfs_mount_t *mp = dp->i_mount;
+
+       offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
+
+       switch (dp->i_d.di_format) {
+       case XFS_DINODE_FMT_DEV:
+               minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
+               return (offset >= minforkoff) ? minforkoff : 0;
+       case XFS_DINODE_FMT_UUID:
+               minforkoff = roundup(sizeof(uuid_t), 8) >> 3;
+               return (offset >= minforkoff) ? minforkoff : 0;
+       }
+
+       if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
+               if (bytes <= XFS_IFORK_ASIZE(dp))
+                       return mp->m_attroffset >> 3;
+               return 0;
+       }
+
+       /* data fork btree root can have at least this many key/ptr pairs */
+       minforkoff = MAX(dp->i_df.if_bytes, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
+       minforkoff = roundup(minforkoff, 8) >> 3;
+
+       /* attr fork btree root can have at least this many key/ptr pairs */
+       maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
+       maxforkoff = maxforkoff >> 3;   /* rounded down */
+
+       if (offset >= minforkoff && offset < maxforkoff)
+               return offset;
+       if (offset >= maxforkoff)
+               return maxforkoff;
+       return 0;
+}
+
+/*
+ * Switch on the ATTR2 superblock bit (implies also FEATURES2)
+ */
+STATIC void
+xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
+{
+       unsigned long s;
+
+       if ((mp->m_flags & XFS_MOUNT_ATTR2) &&
+           !(XFS_SB_VERSION_HASATTR2(&mp->m_sb))) {
+               s = XFS_SB_LOCK(mp);
+               if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
+                       XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
+                       XFS_SB_UNLOCK(mp, s);
+                       xfs_mod_sb(tp, XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
+               } else
+                       XFS_SB_UNLOCK(mp, s);
+       }
+}
+
+/*
+ * Create the initial contents of a shortform attribute list.
+ */
+void
 xfs_attr_shortform_create(xfs_da_args_t *args)
 {
        xfs_attr_sf_hdr_t *hdr;
@@ -129,32 +193,40 @@ xfs_attr_shortform_create(xfs_da_args_t *args)
        }
        xfs_idata_realloc(dp, sizeof(*hdr), XFS_ATTR_FORK);
        hdr = (xfs_attr_sf_hdr_t *)ifp->if_u1.if_data;
-       INT_ZERO(hdr->count, ARCH_CONVERT);
+       hdr->count = 0;
        INT_SET(hdr->totsize, ARCH_CONVERT, sizeof(*hdr));
        xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA);
-       return(0);
 }
 
 /*
  * Add a name/value pair to the shortform attribute list.
  * Overflow from the inode has already been checked for.
  */
-int
-xfs_attr_shortform_add(xfs_da_args_t *args)
+void
+xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
 {
        xfs_attr_shortform_t *sf;
        xfs_attr_sf_entry_t *sfe;
        int i, offset, size;
+       xfs_mount_t *mp;
        xfs_inode_t *dp;
        xfs_ifork_t *ifp;
 
        dp = args->dp;
+       mp = dp->i_mount;
+       dp->i_d.di_forkoff = forkoff;
+       dp->i_df.if_ext_max =
+               XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
+       dp->i_afp->if_ext_max =
+               XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
+
        ifp = dp->i_afp;
        ASSERT(ifp->if_flags & XFS_IFINLINE);
        sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
        sfe = &sf->list[0];
        for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT);
                                sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) {
+#ifdef DEBUG
                if (sfe->namelen != args->namelen)
                        continue;
                if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
@@ -165,7 +237,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args)
                if (((args->flags & ATTR_ROOT) != 0) !=
                    ((sfe->flags & XFS_ATTR_ROOT) != 0))
                        continue;
-               return(XFS_ERROR(EEXIST));
+               ASSERT(0);
+#endif
        }
 
        offset = (char *)sfe - (char *)sf;
@@ -184,11 +257,11 @@ xfs_attr_shortform_add(xfs_da_args_t *args)
        INT_MOD(sf->hdr.totsize, ARCH_CONVERT, size);
        xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA);
 
-       return(0);
+       xfs_sbversion_add_attr2(mp, args->trans);
 }
 
 /*
- * Remove a name from the shortform attribute list structure.
+ * Remove an attribute from the shortform attribute list structure.
  */
 int
 xfs_attr_shortform_remove(xfs_da_args_t *args)
@@ -196,17 +269,16 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
        xfs_attr_shortform_t *sf;
        xfs_attr_sf_entry_t *sfe;
        int base, size=0, end, totsize, i;
+       xfs_mount_t *mp;
        xfs_inode_t *dp;
 
-       /*
-        * Remove the attribute.
-        */
        dp = args->dp;
+       mp = dp->i_mount;
        base = sizeof(xfs_attr_sf_hdr_t);
        sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
        sfe = &sf->list[0];
-       for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT);
-                               sfe = XFS_ATTR_SF_NEXTENTRY(sfe),
+       end = INT_GET(sf->hdr.count, ARCH_CONVERT);
+       for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe),
                                        base += size, i++) {
                size = XFS_ATTR_SF_ENTSIZE(sfe);
                if (sfe->namelen != args->namelen)
@@ -221,19 +293,53 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
                        continue;
                break;
        }
-       if (i == INT_GET(sf->hdr.count, ARCH_CONVERT))
+       if (i == end)
                return(XFS_ERROR(ENOATTR));
 
+       /*
+        * Fix up the attribute fork data, covering the hole
+        */
        end = base + size;
        totsize = INT_GET(sf->hdr.totsize, ARCH_CONVERT);
-       if (end != totsize) {
-               memmove(&((char *)sf)[base], &((char *)sf)[end],
-                                                       totsize - end);
-       }
+       if (end != totsize)
+               memmove(&((char *)sf)[base], &((char *)sf)[end], totsize - end);
        INT_MOD(sf->hdr.count, ARCH_CONVERT, -1);
        INT_MOD(sf->hdr.totsize, ARCH_CONVERT, -size);
-       xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
-       xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA);
+
+       /*
+        * Fix up the start offset of the attribute fork
+        */
+       totsize -= size;
+       if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname &&
+           (mp->m_flags & XFS_MOUNT_ATTR2)) {
+               /*
+                * Last attribute now removed, revert to original
+                * inode format making all literal area available
+                * to the data fork once more.
+                */
+               xfs_idestroy_fork(dp, XFS_ATTR_FORK);
+               dp->i_d.di_forkoff = 0;
+               dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
+               ASSERT(dp->i_d.di_anextents == 0);
+               ASSERT(dp->i_afp == NULL);
+               dp->i_df.if_ext_max =
+                       XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
+               xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
+       } else {
+               xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
+               dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
+               ASSERT(dp->i_d.di_forkoff);
+               ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname ||
+                       !(mp->m_flags & XFS_MOUNT_ATTR2));
+               dp->i_afp->if_ext_max =
+                       XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
+               dp->i_df.if_ext_max =
+                       XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
+               xfs_trans_log_inode(args->trans, dp,
+                                       XFS_ILOG_CORE | XFS_ILOG_ADATA);
+       }
+
+       xfs_sbversion_add_attr2(mp, args->trans);
 
        return(0);
 }
@@ -443,7 +549,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
        ASSERT(dp->i_afp != NULL);
        sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
        ASSERT(sf != NULL);
-       if (INT_ISZERO(sf->hdr.count, ARCH_CONVERT))
+       if (!sf->hdr.count)
                return(0);
        cursor = context->cursor;
        ASSERT(cursor != NULL);
@@ -545,7 +651,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
        /*
         * Sort the entries on hash then entno.
         */
-       qsort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare);
+       xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare);
 
        /*
         * Re-find our place IN THE SORTED LIST.
@@ -633,14 +739,17 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp)
                                + name_loc->namelen
                                + INT_GET(name_loc->valuelen, ARCH_CONVERT);
        }
-       return( bytes < XFS_IFORK_ASIZE(dp) );
+       if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
+           (bytes == sizeof(struct xfs_attr_sf_hdr)))
+               return(-1);
+       return(xfs_attr_shortform_bytesfit(dp, bytes));
 }
 
 /*
  * Convert a leaf attribute list to shortform attribute list
  */
 int
-xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args)
+xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
 {
        xfs_attr_leafblock_t *leaf;
        xfs_attr_leaf_entry_t *entry;
@@ -667,9 +776,27 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args)
        error = xfs_da_shrink_inode(args, 0, bp);
        if (error)
                goto out;
-       error = xfs_attr_shortform_create(args);
-       if (error)
+
+       if (forkoff == -1) {
+               ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
+
+               /*
+                * Last attribute was removed, revert to original
+                * inode format making all literal area available
+                * to the data fork once more.
+                */
+               xfs_idestroy_fork(dp, XFS_ATTR_FORK);
+               dp->i_d.di_forkoff = 0;
+               dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
+               ASSERT(dp->i_d.di_anextents == 0);
+               ASSERT(dp->i_afp == NULL);
+               dp->i_df.if_ext_max =
+                       XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
+               xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
                goto out;
+       }
+
+       xfs_attr_shortform_create(args);
 
        /*
         * Copy the attributes
@@ -686,7 +813,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args)
        for (i = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); entry++, i++) {
                if (entry->flags & XFS_ATTR_INCOMPLETE)
                        continue;       /* don't copy partial entries */
-               if (INT_ISZERO(entry->nameidx, ARCH_CONVERT))
+               if (!entry->nameidx)
                        continue;
                ASSERT(entry->flags & XFS_ATTR_LOCAL);
                name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
@@ -697,7 +824,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args)
                nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT);
                nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
                              ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
-               xfs_attr_shortform_add(&nargs);
+               xfs_attr_shortform_add(&nargs, forkoff);
        }
        error = 0;
 
@@ -774,7 +901,7 @@ out:
  * Create the initial contents of a leaf attribute list
  * or a leaf in a node attribute list.
  */
-int
+STATIC int
 xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
 {
        xfs_attr_leafblock_t *leaf;
@@ -795,7 +922,7 @@ xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
        hdr = &leaf->hdr;
        INT_SET(hdr->info.magic, ARCH_CONVERT, XFS_ATTR_LEAF_MAGIC);
        INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount));
-       if (INT_ISZERO(hdr->firstused, ARCH_CONVERT)) {
+       if (!hdr->firstused) {
                INT_SET(hdr->firstused, ARCH_CONVERT,
                        XFS_LBSIZE(dp->i_mount) - XFS_ATTR_LEAF_NAME_ALIGN);
        }
@@ -882,7 +1009,7 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
        ASSERT((args->index >= 0)
                && (args->index <= INT_GET(leaf->hdr.count, ARCH_CONVERT)));
        hdr = &leaf->hdr;
-       entsize = xfs_attr_leaf_newentsize(args,
+       entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
                           args->trans->t_mountp->m_sb.sb_blocksize, NULL);
 
        /*
@@ -898,7 +1025,7 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
                        sum += INT_GET(map->size, ARCH_CONVERT);
                        continue;
                }
-               if (INT_ISZERO(map->size, ARCH_CONVERT))
+               if (!map->size)
                        continue;       /* no space in this map */
                tmp = entsize;
                if (INT_GET(map->base, ARCH_CONVERT)
@@ -979,13 +1106,14 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
        mp = args->trans->t_mountp;
        ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp));
        ASSERT((INT_GET(map->base, ARCH_CONVERT) & 0x3) == 0);
-       ASSERT(INT_GET(map->size, ARCH_CONVERT)
-                               >= xfs_attr_leaf_newentsize(args,
-                                            mp->m_sb.sb_blocksize, NULL));
+       ASSERT(INT_GET(map->size, ARCH_CONVERT) >=
+               xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
+                                        mp->m_sb.sb_blocksize, NULL));
        ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp));
        ASSERT((INT_GET(map->size, ARCH_CONVERT) & 0x3) == 0);
        INT_MOD(map->size, ARCH_CONVERT,
-               -xfs_attr_leaf_newentsize(args, mp->m_sb.sb_blocksize, &tmp));
+               -xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
+                                         mp->m_sb.sb_blocksize, &tmp));
        INT_SET(entry->nameidx, ARCH_CONVERT,
                                        INT_GET(map->base, ARCH_CONVERT)
                                      + INT_GET(map->size, ARCH_CONVERT));
@@ -1031,8 +1159,8 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
                memcpy((char *)name_rmt->name, args->name, args->namelen);
                entry->flags |= XFS_ATTR_INCOMPLETE;
                /* just in case */
-               INT_ZERO(name_rmt->valuelen, ARCH_CONVERT);
-               INT_ZERO(name_rmt->valueblk, ARCH_CONVERT);
+               name_rmt->valuelen = 0;
+               name_rmt->valueblk = 0;
                args->rmtblkno = 1;
                args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen);
        }
@@ -1097,12 +1225,12 @@ xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp)
        hdr_d->info = hdr_s->info;      /* struct copy */
        INT_SET(hdr_d->firstused, ARCH_CONVERT, XFS_LBSIZE(mp));
        /* handle truncation gracefully */
-       if (INT_ISZERO(hdr_d->firstused, ARCH_CONVERT)) {
+       if (!hdr_d->firstused) {
                INT_SET(hdr_d->firstused, ARCH_CONVERT,
                                XFS_LBSIZE(mp) - XFS_ATTR_LEAF_NAME_ALIGN);
        }
-       INT_ZERO(hdr_d->usedbytes, ARCH_CONVERT);
-       INT_ZERO(hdr_d->count, ARCH_CONVERT);
+       hdr_d->usedbytes = 0;
+       hdr_d->count = 0;
        hdr_d->holes = 0;
        INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT,
                                        sizeof(xfs_attr_leaf_hdr_t));
@@ -1341,8 +1469,10 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
        half  = (max+1) * sizeof(*entry);
        half += INT_GET(hdr1->usedbytes, ARCH_CONVERT)
                                + INT_GET(hdr2->usedbytes, ARCH_CONVERT)
-                               + xfs_attr_leaf_newentsize(state->args,
-                                                    state->blocksize, NULL);
+                               + xfs_attr_leaf_newentsize(
+                                               state->args->namelen,
+                                               state->args->valuelen,
+                                               state->blocksize, NULL);
        half /= 2;
        lastdelta = state->blocksize;
        entry = &leaf1->entries[0];
@@ -1354,9 +1484,10 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
                 */
                if (count == blk1->index) {
                        tmp = totallen + sizeof(*entry) +
-                               xfs_attr_leaf_newentsize(state->args,
-                                                        state->blocksize,
-                                                        NULL);
+                               xfs_attr_leaf_newentsize(
+                                               state->args->namelen,
+                                               state->args->valuelen,
+                                               state->blocksize, NULL);
                        if (XFS_ATTR_ABS(half - tmp) > lastdelta)
                                break;
                        lastdelta = XFS_ATTR_ABS(half - tmp);
@@ -1392,9 +1523,10 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
        totallen -= count * sizeof(*entry);
        if (foundit) {
                totallen -= sizeof(*entry) +
-                               xfs_attr_leaf_newentsize(state->args,
-                                                        state->blocksize,
-                                                        NULL);
+                               xfs_attr_leaf_newentsize(
+                                               state->args->namelen,
+                                               state->args->valuelen,
+                                               state->blocksize, NULL);
        }
 
        *countarg = count;
@@ -1456,7 +1588,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
                 * Make altpath point to the block we want to keep and
                 * path point to the block we want to drop (this one).
                 */
-               forward = (!INT_ISZERO(info->forw, ARCH_CONVERT));
+               forward = info->forw;
                memcpy(&state->altpath, &state->path, sizeof(state->path));
                error = xfs_da_path_shift(state, &state->altpath, forward,
                                                 0, &retval);
@@ -1617,8 +1749,8 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
                        INT_MOD(map->size, ARCH_CONVERT,
                                INT_GET(hdr->freemap[after].size,
                                                        ARCH_CONVERT));
-                       INT_ZERO(hdr->freemap[after].base, ARCH_CONVERT);
-                       INT_ZERO(hdr->freemap[after].size, ARCH_CONVERT);
+                       hdr->freemap[after].base = 0;
+                       hdr->freemap[after].size = 0;
                } else if (before >= 0) {
                        map = &hdr->freemap[before];
                        INT_MOD(map->size, ARCH_CONVERT, entsize);
@@ -1686,7 +1818,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
                                tmp = INT_GET(entry->nameidx, ARCH_CONVERT);
                }
                INT_SET(hdr->firstused, ARCH_CONVERT, tmp);
-               if (INT_ISZERO(hdr->firstused, ARCH_CONVERT)) {
+               if (!hdr->firstused) {
                        INT_SET(hdr->firstused, ARCH_CONVERT,
                                        tmp - XFS_ATTR_LEAF_NAME_ALIGN);
                }
@@ -1772,13 +1904,13 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
                tmp_leaf = (xfs_attr_leafblock_t *)tmpbuffer;
                tmp_hdr = &tmp_leaf->hdr;
                tmp_hdr->info = save_hdr->info; /* struct copy */
-               INT_ZERO(tmp_hdr->count, ARCH_CONVERT);
+               tmp_hdr->count = 0;
                INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize);
-               if (INT_ISZERO(tmp_hdr->firstused, ARCH_CONVERT)) {
+               if (!tmp_hdr->firstused) {
                        INT_SET(tmp_hdr->firstused, ARCH_CONVERT,
                                state->blocksize - XFS_ATTR_LEAF_NAME_ALIGN);
                }
-               INT_ZERO(tmp_hdr->usedbytes, ARCH_CONVERT);
+               tmp_hdr->usedbytes = 0;
                if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) {
                        xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, 0,
                                (int)INT_GET(drop_hdr->count, ARCH_CONVERT),
@@ -1860,8 +1992,8 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
                else
                        break;
        }
-       ASSERT((probe >= 0) && \
-              ((INT_ISZERO(leaf->hdr.count, ARCH_CONVERT))
+       ASSERT((probe >= 0) && 
+              (!leaf->hdr.count
               || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT))));
        ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT)
                                                        == hashval));
@@ -2151,10 +2283,10 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s,
        INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT,
                                INT_GET(hdr_d->firstused, ARCH_CONVERT)
                              - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
-       INT_ZERO(hdr_d->freemap[1].base, ARCH_CONVERT);
-       INT_ZERO(hdr_d->freemap[2].base, ARCH_CONVERT);
-       INT_ZERO(hdr_d->freemap[1].size, ARCH_CONVERT);
-       INT_ZERO(hdr_d->freemap[2].size, ARCH_CONVERT);
+       hdr_d->freemap[1].base = 0;
+       hdr_d->freemap[2].base = 0;
+       hdr_d->freemap[1].size = 0;
+       hdr_d->freemap[2].size = 0;
        hdr_s->holes = 1;       /* leaf may not be compact */
 }
 
@@ -2199,7 +2331,7 @@ xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count)
                                                == XFS_ATTR_LEAF_MAGIC);
        if (count)
                *count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
-       if (INT_ISZERO(leaf->hdr.count, ARCH_CONVERT))
+       if (!leaf->hdr.count)
                return(0);
        return(INT_GET(leaf->entries[INT_GET(leaf->hdr.count,
                                ARCH_CONVERT)-1].hashval, ARCH_CONVERT));
@@ -2209,7 +2341,7 @@ xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count)
  * Calculate the number of bytes used to store the indicated attribute
  * (whether local or remote only calculate bytes in this block).
  */
-int
+STATIC int
 xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
 {
        xfs_attr_leaf_name_local_t *name_loc;
@@ -2237,17 +2369,17 @@ xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
  * a "local" or a "remote" attribute.
  */
 int
-xfs_attr_leaf_newentsize(xfs_da_args_t *args, int blocksize, int *local)
+xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local)
 {
        int size;
 
-       size = XFS_ATTR_LEAF_ENTSIZE_LOCAL(args->namelen, args->valuelen);
+       size = XFS_ATTR_LEAF_ENTSIZE_LOCAL(namelen, valuelen);
        if (size < XFS_ATTR_LEAF_ENTSIZE_LOCAL_MAX(blocksize)) {
                if (local) {
                        *local = 1;
                }
        } else {
-               size = XFS_ATTR_LEAF_ENTSIZE_REMOTE(args->namelen);
+               size = XFS_ATTR_LEAF_ENTSIZE_REMOTE(namelen);
                if (local) {
                        *local = 0;
                }
@@ -2380,7 +2512,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
  * we may be reading them directly out of a user buffer.
  */
 /*ARGSUSED*/
-int
+STATIC int
 xfs_attr_put_listent(xfs_attr_list_context_t *context,
                     attrnames_t *namesp, char *name, int namelen, int valuelen)
 {
@@ -2543,8 +2675,8 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
                        XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
        if ((entry->flags & XFS_ATTR_LOCAL) == 0) {
                name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index);
-               INT_ZERO(name_rmt->valueblk, ARCH_CONVERT);
-               INT_ZERO(name_rmt->valuelen, ARCH_CONVERT);
+               name_rmt->valueblk = 0;
+               name_rmt->valuelen = 0;
                xfs_da_log_buf(args->trans, bp,
                         XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
        }
@@ -2661,8 +2793,8 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
                          XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2)));
        if ((entry2->flags & XFS_ATTR_LOCAL) == 0) {
                name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf2, args->index2);
-               INT_ZERO(name_rmt->valueblk, ARCH_CONVERT);
-               INT_ZERO(name_rmt->valuelen, ARCH_CONVERT);
+               name_rmt->valueblk = 0;
+               name_rmt->valuelen = 0;
                xfs_da_log_buf(args->trans, bp2,
                         XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt)));
        }
@@ -2740,7 +2872,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
  * Recurse (gasp!) through the attribute nodes until we find leaves.
  * We're doing a depth-first traversal in order to invalidate everything.
  */
-int
+STATIC int
 xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
                                   int level)
 {
@@ -2849,7 +2981,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
  * Note that we must release the lock on the buffer so that we are not
  * caught holding something that the logging code wants to flush to disk.
  */
-int
+STATIC int
 xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
 {
        xfs_attr_leafblock_t *leaf;
@@ -2871,7 +3003,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
                if (   INT_GET(entry->nameidx, ARCH_CONVERT)
                    && ((entry->flags & XFS_ATTR_LOCAL) == 0)) {
                        name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
-                       if (!INT_ISZERO(name_rmt->valueblk, ARCH_CONVERT))
+                       if (name_rmt->valueblk)
                                count++;
                }
        }
@@ -2899,7 +3031,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
                if (   INT_GET(entry->nameidx, ARCH_CONVERT)
                    && ((entry->flags & XFS_ATTR_LOCAL) == 0)) {
                        name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
-                       if (!INT_ISZERO(name_rmt->valueblk, ARCH_CONVERT)) {
+                       if (name_rmt->valueblk) {
                                /* both on-disk, don't endian flip twice */
                                lp->valueblk = name_rmt->valueblk;
                                INT_SET(lp->valuelen, ARCH_CONVERT,
@@ -2934,7 +3066,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
  * Look at all the extents for this logical region,
  * invalidate any buffers that are incore/in transactions.
  */
-int
+STATIC int
 xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
                                    xfs_dablk_t blkno, int blkcnt)
 {