linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / xfs / xfs_da_btree.c
index 3965561..473671f 100644 (file)
@@ -1,41 +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/
+ * 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_alloc.h"
+#include "xfs_btree.h"
 #include "xfs_bmap.h"
-#include "xfs_da_btree.h"
 #include "xfs_attr.h"
 #include "xfs_attr_leaf.h"
 #include "xfs_dir_leaf.h"
@@ -64,7 +49,6 @@
 #include "xfs_dir2_block.h"
 #include "xfs_dir2_node.h"
 #include "xfs_error.h"
-#include "xfs_bit.h"
 
 /*
  * xfs_da_btree.c
@@ -113,7 +97,10 @@ STATIC void xfs_da_node_unbalance(xfs_da_state_t *state,
 STATIC uint    xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count);
 STATIC int     xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp);
 STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra);
-
+STATIC int     xfs_da_blk_unlink(xfs_da_state_t *state,
+                                 xfs_da_state_blk_t *drop_blk,
+                                 xfs_da_state_blk_t *save_blk);
+STATIC void    xfs_da_state_kill_altpath(xfs_da_state_t *state);
 
 /*========================================================================
  * Routines used for growing the Btree.
@@ -137,11 +124,11 @@ xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
                return(error);
        ASSERT(bp != NULL);
        node = bp->data;
-       INT_ZERO(node->hdr.info.forw, ARCH_CONVERT);
-       INT_ZERO(node->hdr.info.back, ARCH_CONVERT);
+       node->hdr.info.forw = 0;
+       node->hdr.info.back = 0;
        INT_SET(node->hdr.info.magic, ARCH_CONVERT, XFS_DA_NODE_MAGIC);
-       INT_ZERO(node->hdr.info.pad, ARCH_CONVERT);
-       INT_ZERO(node->hdr.count, ARCH_CONVERT);
+       node->hdr.info.pad = 0;
+       node->hdr.count = 0;
        INT_SET(node->hdr.level, ARCH_CONVERT, level);
 
        xfs_da_log_buf(tp, bp,
@@ -187,9 +174,6 @@ xfs_da_split(xfs_da_state_t *state)
                 */
                switch (oldblk->magic) {
                case XFS_ATTR_LEAF_MAGIC:
-#ifndef __KERNEL__
-                       return(ENOTTY);
-#else
                        error = xfs_attr_leaf_split(state, oldblk, newblk);
                        if ((error != 0) && (error != ENOSPC)) {
                                return(error);  /* GROT: attr is inconsistent */
@@ -215,7 +199,6 @@ xfs_da_split(xfs_da_state_t *state)
                                return(error);  /* GROT: attr inconsistent */
                        addblk = newblk;
                        break;
-#endif
                case XFS_DIR_LEAF_MAGIC:
                        ASSERT(XFS_DIR_IS_V1(state->mp));
                        error = xfs_dir_leaf_split(state, oldblk, newblk);
@@ -306,7 +289,7 @@ xfs_da_split(xfs_da_state_t *state)
         */
 
        node = oldblk->bp->data;
-       if (!INT_ISZERO(node->hdr.info.forw, ARCH_CONVERT)) {
+       if (node->hdr.info.forw) {
                if (INT_GET(node->hdr.info.forw, ARCH_CONVERT) == addblk->blkno) {
                        bp = addblk->bp;
                } else {
@@ -446,7 +429,8 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
        /*
         * With V2 the extra block is data or freespace.
         */
-       useextra = state->extravalid && XFS_DIR_IS_V1(state->mp);
+       useextra = state->extravalid && (XFS_DIR_IS_V1(state->mp) ||
+                       state->args->whichfork == XFS_ATTR_FORK);
        newcount = 1 + useextra;
        /*
         * Do we have to split the node?
@@ -703,18 +687,12 @@ xfs_da_join(xfs_da_state_t *state)
                 */
                switch (drop_blk->magic) {
                case XFS_ATTR_LEAF_MAGIC:
-#ifndef __KERNEL__
-                       error = ENOTTY;
-#else
                        error = xfs_attr_leaf_toosmall(state, &action);
-#endif
                        if (error)
                                return(error);
                        if (action == 0)
                                return(0);
-#ifdef __KERNEL__
                        xfs_attr_leaf_unbalance(state, drop_blk, save_blk);
-#endif
                        break;
                case XFS_DIR_LEAF_MAGIC:
                        ASSERT(XFS_DIR_IS_V1(state->mp));
@@ -791,8 +769,8 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
        ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC);
        oldroot = root_blk->bp->data;
        ASSERT(INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
-       ASSERT(INT_ISZERO(oldroot->hdr.info.forw, ARCH_CONVERT));
-       ASSERT(INT_ISZERO(oldroot->hdr.info.back, ARCH_CONVERT));
+       ASSERT(!oldroot->hdr.info.forw);
+       ASSERT(!oldroot->hdr.info.back);
 
        /*
         * If the root has more than one child, then don't do anything.
@@ -818,8 +796,8 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
        } else {
                ASSERT(INT_GET(blkinfo->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
        }
-       ASSERT(INT_ISZERO(blkinfo->forw, ARCH_CONVERT));
-       ASSERT(INT_ISZERO(blkinfo->back, ARCH_CONVERT));
+       ASSERT(!blkinfo->forw);
+       ASSERT(!blkinfo->back);
        memcpy(root_blk->bp->data, bp->data, state->blocksize);
        xfs_da_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1);
        error = xfs_da_shrink_inode(args, child, bp);
@@ -871,7 +849,7 @@ xfs_da_node_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);
@@ -970,13 +948,11 @@ xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path)
        level = path->active-1;
        blk = &path->blk[ level ];
        switch (blk->magic) {
-#ifdef __KERNEL__
        case XFS_ATTR_LEAF_MAGIC:
                lasthash = xfs_attr_leaf_lasthash(blk->bp, &count);
                if (count == 0)
                        return;
                break;
-#endif
        case XFS_DIR_LEAF_MAGIC:
                ASSERT(XFS_DIR_IS_V1(state->mp));
                lasthash = xfs_dir_leaf_lasthash(blk->bp, &count);
@@ -1217,12 +1193,10 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
                                blkno = INT_GET(btree->before, ARCH_CONVERT);
                        }
                }
-#ifdef __KERNEL__
                else if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC) {
                        blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
                        break;
                }
-#endif
                else if (INT_GET(curr->magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC) {
                        blk->hashval = xfs_dir_leaf_lasthash(blk->bp, NULL);
                        break;
@@ -1249,13 +1223,11 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
                        retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
                                                        &blk->index, state);
                }
-#ifdef __KERNEL__
                else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
                        retval = xfs_attr_leaf_lookup_int(blk->bp, args);
                        blk->index = args->index;
                        args->blkno = blk->blkno;
                }
-#endif
                if (((retval == ENOENT) || (retval == ENOATTR)) &&
                    (blk->hashval == args->hashval)) {
                        error = xfs_da_path_shift(state, &state->path, 1, 1,
@@ -1265,12 +1237,10 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
                        if (retval == 0) {
                                continue;
                        }
-#ifdef __KERNEL__
                        else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
                                /* path_shift() gives ENOENT */
                                retval = XFS_ERROR(ENOATTR);
                        }
-#endif
                }
                break;
        }
@@ -1309,11 +1279,9 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
        ASSERT(old_blk->magic == new_blk->magic);
 
        switch (old_blk->magic) {
-#ifdef __KERNEL__
        case XFS_ATTR_LEAF_MAGIC:
                before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp);
                break;
-#endif
        case XFS_DIR_LEAF_MAGIC:
                ASSERT(XFS_DIR_IS_V1(state->mp));
                before = xfs_dir_leaf_order(old_blk->bp, new_blk->bp);
@@ -1416,7 +1384,7 @@ xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count)
        ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
        if (count)
                *count = INT_GET(node->hdr.count, ARCH_CONVERT);
-       if (INT_ISZERO(node->hdr.count, ARCH_CONVERT))
+       if (!node->hdr.count)
                return(0);
        return(INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT));
 }
@@ -1424,7 +1392,7 @@ xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count)
 /*
  * Unlink a block from a doubly linked list of blocks.
  */
-int                                                    /* error */
+STATIC int                                             /* error */
 xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
                                 xfs_da_state_blk_t *save_blk)
 {
@@ -1584,12 +1552,10 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
                        ASSERT(level == path->active-1);
                        blk->index = 0;
                        switch(blk->magic) {
-#ifdef __KERNEL__
                        case XFS_ATTR_LEAF_MAGIC:
                                blk->hashval = xfs_attr_leaf_lasthash(blk->bp,
                                                                      NULL);
                                break;
-#endif
                        case XFS_DIR_LEAF_MAGIC:
                                ASSERT(XFS_DIR_IS_V1(state->mp));
                                blk->hashval = xfs_dir_leaf_lasthash(blk->bp,
@@ -1623,45 +1589,31 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
  * This is implemented with some source-level loop unrolling.
  */
 xfs_dahash_t
-xfs_da_hashname(uchar_t *name, int namelen)
+xfs_da_hashname(const uchar_t *name, int namelen)
 {
        xfs_dahash_t hash;
 
-#define        ROTL(x,y)       (((x) << (y)) | ((x) >> (32 - (y))))
-#ifdef SLOWVERSION
-       /*
-        * This is the old one-byte-at-a-time version.
-        */
-       for (hash = 0; namelen > 0; namelen--) {
-               hash = *name++ ^ ROTL(hash, 7);
-       }
-       return(hash);
-#else
        /*
         * Do four characters at a time as long as we can.
         */
-       for (hash = 0; namelen >= 4; namelen -= 4, name += 4) {
+       for (hash = 0; namelen >= 4; namelen -= 4, name += 4)
                hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^
-                      (name[3] << 0) ^ ROTL(hash, 7 * 4);
-       }
+                      (name[3] << 0) ^ rol32(hash, 7 * 4);
+
        /*
         * Now do the rest of the characters.
         */
        switch (namelen) {
        case 3:
                return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^
-                      ROTL(hash, 7 * 3);
+                      rol32(hash, 7 * 3);
        case 2:
-               return (name[0] << 7) ^ (name[1] << 0) ^ ROTL(hash, 7 * 2);
+               return (name[0] << 7) ^ (name[1] << 0) ^ rol32(hash, 7 * 2);
        case 1:
-               return (name[0] << 0) ^ ROTL(hash, 7 * 1);
-       case 0:
+               return (name[0] << 0) ^ rol32(hash, 7 * 1);
+       default: /* case 0: */
                return hash;
        }
-       /* NOTREACHED */
-#endif
-#undef ROTL
-       return 0; /* keep gcc happy */
 }
 
 /*
@@ -2092,7 +2044,7 @@ xfs_da_do_buf(
        int             caller,
        inst_t          *ra)
 {
-       xfs_buf_t       *bp = 0;
+       xfs_buf_t       *bp = NULL;
        xfs_buf_t       **bplist;
        int             error=0;
        int             i;
@@ -2166,9 +2118,9 @@ xfs_da_do_buf(
                                        cmn_err(CE_ALERT,
                                                "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n",
                                                i,
-                                               mapp[i].br_startoff,
-                                               mapp[i].br_startblock,
-                                               mapp[i].br_blockcount,
+                                               (long long)mapp[i].br_startoff,
+                                               (long long)mapp[i].br_startblock,
+                                               (long long)mapp[i].br_blockcount,
                                                mapp[i].br_state);
                                }
                        }
@@ -2199,20 +2151,16 @@ xfs_da_do_buf(
                        error = bp ? XFS_BUF_GETERROR(bp) : XFS_ERROR(EIO);
                        break;
                case 1:
-#ifndef __KERNEL__
                case 2:
-#endif
                        bp = NULL;
                        error = xfs_trans_read_buf(mp, trans, mp->m_ddev_targp,
                                mappedbno, nmapped, 0, &bp);
                        break;
-#ifdef __KERNEL__
                case 3:
                        xfs_baread(mp->m_ddev_targp, mappedbno, nmapped);
                        error = 0;
                        bp = NULL;
                        break;
-#endif
                }
                if (error) {
                        if (bp)
@@ -2383,7 +2331,7 @@ xfs_da_state_alloc(void)
 /*
  * Kill the altpath contents of a da-state structure.
  */
-void
+STATIC void
 xfs_da_state_kill_altpath(xfs_da_state_t *state)
 {
        int     i;