xfs: Don't flush stale inodes
[safe/jmp/linux-2.6] / fs / xfs / xfs_dir2_node.c
index e29b7c6..ce6e355 100644 (file)
@@ -37,8 +37,8 @@
 #include "xfs_dir2_leaf.h"
 #include "xfs_dir2_block.h"
 #include "xfs_dir2_node.h"
-#include "xfs_dir2_trace.h"
 #include "xfs_error.h"
+#include "xfs_trace.h"
 
 /*
  * Function declarations.
@@ -123,7 +123,8 @@ xfs_dir2_leaf_to_node(
        __be16                  *to;            /* pointer to freespace entry */
        xfs_trans_t             *tp;            /* transaction pointer */
 
-       xfs_dir2_trace_args_b("leaf_to_node", args, lbp);
+       trace_xfs_dir2_leaf_to_node(args);
+
        dp = args->dp;
        mp = dp->i_mount;
        tp = args->trans;
@@ -196,7 +197,8 @@ xfs_dir2_leafn_add(
        xfs_mount_t             *mp;            /* filesystem mount point */
        xfs_trans_t             *tp;            /* transaction pointer */
 
-       xfs_dir2_trace_args_sb("leafn_add", args, index, bp);
+       trace_xfs_dir2_leafn_add(args, index);
+
        dp = args->dp;
        mp = dp->i_mount;
        tp = args->trans;
@@ -226,7 +228,7 @@ xfs_dir2_leafn_add(
        ASSERT(index == be16_to_cpu(leaf->hdr.count) ||
               be32_to_cpu(leaf->ents[index].hashval) >= args->hashval);
 
-       if (args->justcheck)
+       if (args->op_flags & XFS_DA_OP_JUSTCHECK)
                return 0;
 
        /*
@@ -515,7 +517,7 @@ xfs_dir2_leafn_lookup_for_addname(
        /* Didn't find any space */
        fi = -1;
 out:
-       ASSERT(args->oknoent);
+       ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
        if (curbp) {
                /* Giving back a free block. */
                state->extravalid = 1;
@@ -549,13 +551,13 @@ xfs_dir2_leafn_lookup_for_entry(
        xfs_dir2_data_entry_t   *dep;           /* data block entry */
        xfs_inode_t             *dp;            /* incore directory inode */
        int                     error;          /* error return value */
-       int                     di;             /* data entry index */
        int                     index;          /* leaf entry index */
        xfs_dir2_leaf_t         *leaf;          /* leaf structure */
        xfs_dir2_leaf_entry_t   *lep;           /* leaf entry */
        xfs_mount_t             *mp;            /* filesystem mount point */
        xfs_dir2_db_t           newdb;          /* new data block number */
        xfs_trans_t             *tp;            /* transaction pointer */
+       enum xfs_dacmp          cmp;            /* comparison result */
 
        dp = args->dp;
        tp = args->trans;
@@ -600,17 +602,27 @@ xfs_dir2_leafn_lookup_for_entry(
                 */
                if (newdb != curdb) {
                        /*
-                        * If we had a block before, drop it.
+                        * If we had a block before that we aren't saving
+                        * for a CI name, drop it
                         */
-                       if (curbp)
+                       if (curbp && (args->cmpresult == XFS_CMP_DIFFERENT ||
+                                               curdb != state->extrablk.blkno))
                                xfs_da_brelse(tp, curbp);
                        /*
-                        * Read the data block.
+                        * If needing the block that is saved with a CI match,
+                        * use it otherwise read in the new data block.
                         */
-                       error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp,
-                                       newdb), -1, &curbp, XFS_DATA_FORK);
-                       if (error)
-                               return error;
+                       if (args->cmpresult != XFS_CMP_DIFFERENT &&
+                                       newdb == state->extrablk.blkno) {
+                               ASSERT(state->extravalid);
+                               curbp = state->extrablk.bp;
+                       } else {
+                               error = xfs_da_read_buf(tp, dp,
+                                               xfs_dir2_db_to_da(mp, newdb),
+                                               -1, &curbp, XFS_DATA_FORK);
+                               if (error)
+                                       return error;
+                       }
                        xfs_dir2_data_check(dp, curbp);
                        curdb = newdb;
                }
@@ -620,36 +632,49 @@ xfs_dir2_leafn_lookup_for_entry(
                dep = (xfs_dir2_data_entry_t *)((char *)curbp->data +
                        xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
                /*
-                * Compare the entry, return it if it matches.
+                * Compare the entry and if it's an exact match, return
+                * EEXIST immediately. If it's the first case-insensitive
+                * match, store the block & inode number and continue looking.
                 */
-               if (dep->namelen == args->namelen && memcmp(dep->name,
-                                       args->name, args->namelen) == 0) {
+               cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
+               if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
+                       /* If there is a CI match block, drop it */
+                       if (args->cmpresult != XFS_CMP_DIFFERENT &&
+                                               curdb != state->extrablk.blkno)
+                               xfs_da_brelse(tp, state->extrablk.bp);
+                       args->cmpresult = cmp;
                        args->inumber = be64_to_cpu(dep->inumber);
-                       di = (int)((char *)dep - (char *)curbp->data);
-                       error = EEXIST;
-                       goto out;
+                       *indexp = index;
+                       state->extravalid = 1;
+                       state->extrablk.bp = curbp;
+                       state->extrablk.blkno = curdb;
+                       state->extrablk.index = (int)((char *)dep -
+                                                       (char *)curbp->data);
+                       state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
+                       if (cmp == XFS_CMP_EXACT)
+                               return XFS_ERROR(EEXIST);
                }
        }
-       /* Didn't find a match. */
-       error = ENOENT;
-       di = -1;
-       ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent);
-out:
+       ASSERT(index == be16_to_cpu(leaf->hdr.count) ||
+                                       (args->op_flags & XFS_DA_OP_OKNOENT));
        if (curbp) {
-               /* Giving back a data block. */
-               state->extravalid = 1;
-               state->extrablk.bp = curbp;
-               state->extrablk.index = di;
-               state->extrablk.blkno = curdb;
-               state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
+               if (args->cmpresult == XFS_CMP_DIFFERENT) {
+                       /* Giving back last used data block. */
+                       state->extravalid = 1;
+                       state->extrablk.bp = curbp;
+                       state->extrablk.index = -1;
+                       state->extrablk.blkno = curdb;
+                       state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
+               } else {
+                       /* If the curbp is not the CI match block, drop it */
+                       if (state->extrablk.bp != curbp)
+                               xfs_da_brelse(tp, curbp);
+               }
        } else {
                state->extravalid = 0;
        }
-       /*
-        * Return the index, that will be the insertion point.
-        */
        *indexp = index;
-       return XFS_ERROR(error);
+       return XFS_ERROR(ENOENT);
 }
 
 /*
@@ -664,7 +689,7 @@ xfs_dir2_leafn_lookup_int(
        int                     *indexp,        /* out: leaf entry index */
        xfs_da_state_t          *state)         /* state to fill in */
 {
-       if (args->addname)
+       if (args->op_flags & XFS_DA_OP_ADDNAME)
                return xfs_dir2_leafn_lookup_for_addname(bp, args, indexp,
                                                        state);
        return xfs_dir2_leafn_lookup_for_entry(bp, args, indexp, state);
@@ -688,8 +713,8 @@ xfs_dir2_leafn_moveents(
        int             stale;                  /* count stale leaves copied */
        xfs_trans_t     *tp;                    /* transaction pointer */
 
-       xfs_dir2_trace_args_bibii("leafn_moveents", args, bp_s, start_s, bp_d,
-               start_d, count);
+       trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count);
+
        /*
         * Silently return if nothing to do.
         */
@@ -910,7 +935,8 @@ xfs_dir2_leafn_remove(
        int                     needscan;       /* need to rescan data frees */
        xfs_trans_t             *tp;            /* transaction pointer */
 
-       xfs_dir2_trace_args_sb("leafn_remove", args, index, bp);
+       trace_xfs_dir2_leafn_remove(args, index);
+
        dp = args->dp;
        tp = args->trans;
        mp = dp->i_mount;
@@ -1081,7 +1107,7 @@ xfs_dir2_leafn_remove(
        }
        xfs_dir2_leafn_check(dp, bp);
        /*
-        * Return indication of whether this leaf block is emtpy enough
+        * Return indication of whether this leaf block is empty enough
         * to justify trying to join it with a neighbor.
         */
        *rval =
@@ -1340,7 +1366,8 @@ xfs_dir2_node_addname(
        int                     rval;           /* sub-return value */
        xfs_da_state_t          *state;         /* btree cursor */
 
-       xfs_dir2_trace_args("node_addname", args);
+       trace_xfs_dir2_node_addname(args);
+
        /*
         * Allocate and initialize the state (btree cursor).
         */
@@ -1378,7 +1405,7 @@ xfs_dir2_node_addname(
                /*
                 * It worked, fix the hash values up the btree.
                 */
-               if (!args->justcheck)
+               if (!(args->op_flags & XFS_DA_OP_JUSTCHECK))
                        xfs_da_fixhashpath(state, &state->path);
        } else {
                /*
@@ -1561,7 +1588,8 @@ xfs_dir2_node_addname_int(
                /*
                 * Not allowed to allocate, return failure.
                 */
-               if (args->justcheck || args->total == 0) {
+               if ((args->op_flags & XFS_DA_OP_JUSTCHECK) ||
+                                                       args->total == 0) {
                        /*
                         * Drop the freespace buffer unless it came from our
                         * caller.
@@ -1707,7 +1735,7 @@ xfs_dir2_node_addname_int(
                /*
                 * If just checking, we succeeded.
                 */
-               if (args->justcheck) {
+               if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
                        if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
                                xfs_da_buf_done(fbp);
                        return 0;
@@ -1798,7 +1826,8 @@ xfs_dir2_node_lookup(
        int             rval;                   /* operation return value */
        xfs_da_state_t  *state;                 /* btree cursor */
 
-       xfs_dir2_trace_args("node_lookup", args);
+       trace_xfs_dir2_node_lookup(args);
+
        /*
         * Allocate and initialize the btree cursor.
         */
@@ -1813,6 +1842,14 @@ xfs_dir2_node_lookup(
        error = xfs_da_node_lookup_int(state, &rval);
        if (error)
                rval = error;
+       else if (rval == ENOENT && args->cmpresult == XFS_CMP_CASE) {
+               /* If a CI match, dup the actual name and return EEXIST */
+               xfs_dir2_data_entry_t   *dep;
+
+               dep = (xfs_dir2_data_entry_t *)((char *)state->extrablk.bp->
+                                               data + state->extrablk.index);
+               rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
+       }
        /*
         * Release the btree blocks and leaf block.
         */
@@ -1843,7 +1880,8 @@ xfs_dir2_node_removename(
        int                     rval;           /* operation return value */
        xfs_da_state_t          *state;         /* btree cursor */
 
-       xfs_dir2_trace_args("node_removename", args);
+       trace_xfs_dir2_node_removename(args);
+
        /*
         * Allocate and initialize the btree cursor.
         */
@@ -1856,9 +1894,8 @@ xfs_dir2_node_removename(
         * Look up the entry we're deleting, set up the cursor.
         */
        error = xfs_da_node_lookup_int(state, &rval);
-       if (error) {
+       if (error)
                rval = error;
-       }
        /*
         * Didn't find it, upper layer screwed up.
         */
@@ -1875,9 +1912,8 @@ xfs_dir2_node_removename(
         */
        error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
                &state->extrablk, &rval);
-       if (error) {
+       if (error)
                return error;
-       }
        /*
         * Fix the hash values up the btree.
         */
@@ -1914,7 +1950,8 @@ xfs_dir2_node_replace(
        int                     rval;           /* internal return value */
        xfs_da_state_t          *state;         /* btree cursor */
 
-       xfs_dir2_trace_args("node_replace", args);
+       trace_xfs_dir2_node_replace(args);
+
        /*
         * Allocate and initialize the btree cursor.
         */