Merge branch 'for-2.6.33' of git://git.kernel.dk/linux-2.6-block
[safe/jmp/linux-2.6] / fs / xfs / xfs_dir2_sf.c
index 95e703d..e89734e 100644 (file)
@@ -1,33 +1,19 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003,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_fs.h"
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
+#include "xfs_ag.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
-#include "xfs_dir_leaf.h"
 #include "xfs_error.h"
 #include "xfs_dir2_data.h"
 #include "xfs_dir2_leaf.h"
@@ -100,26 +84,26 @@ xfs_dir2_block_sfsize(
        int                     isdotdot;       /* entry is ".." */
        xfs_mount_t             *mp;            /* mount structure pointer */
        int                     namelen;        /* total name bytes */
-       xfs_ino_t               parent;         /* parent inode number */
+       xfs_ino_t               parent = 0;     /* parent inode number */
        int                     size=0;         /* total computed size */
 
        mp = dp->i_mount;
 
        count = i8count = namelen = 0;
-       btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
-       blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+       btp = xfs_dir2_block_tail_p(mp, block);
+       blp = xfs_dir2_block_leaf_p(btp);
 
        /*
         * Iterate over the block's data entries by using the leaf pointers.
         */
-       for (i = 0; i < INT_GET(btp->count, ARCH_CONVERT); i++) {
-               if ((addr = INT_GET(blp[i].address, ARCH_CONVERT)) == XFS_DIR2_NULL_DATAPTR)
+       for (i = 0; i < be32_to_cpu(btp->count); i++) {
+               if ((addr = be32_to_cpu(blp[i].address)) == XFS_DIR2_NULL_DATAPTR)
                        continue;
                /*
                 * Calculate the pointer to the entry at hand.
                 */
                dep = (xfs_dir2_data_entry_t *)
-                     ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
+                     ((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
                /*
                 * Detect . and .., so we can special-case them.
                 * . is not included in sf directories.
@@ -131,17 +115,17 @@ xfs_dir2_block_sfsize(
                        dep->name[0] == '.' && dep->name[1] == '.';
 #if XFS_BIG_INUMS
                if (!isdot)
-                       i8count += INT_GET(dep->inumber, ARCH_CONVERT) > XFS_DIR2_MAX_SHORT_INUM;
+                       i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM;
 #endif
                if (!isdot && !isdotdot) {
                        count++;
                        namelen += dep->namelen;
                } else if (isdotdot)
-                       parent = INT_GET(dep->inumber, ARCH_CONVERT);
+                       parent = be64_to_cpu(dep->inumber);
                /*
                 * Calculate the new size, see if we should give up yet.
                 */
-               size = XFS_DIR2_SF_HDR_SIZE(i8count) +          /* header */
+               size = xfs_dir2_sf_hdr_size(i8count) +          /* header */
                       count +                                  /* namelen */
                       count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */
                       namelen +                                /* name */
@@ -156,7 +140,7 @@ xfs_dir2_block_sfsize(
         */
        sfhp->count = count;
        sfhp->i8count = i8count;
-       XFS_DIR2_SF_PUT_INUMBER((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
+       xfs_dir2_sf_put_inumber((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
        return size;
 }
 
@@ -216,15 +200,15 @@ xfs_dir2_block_to_sf(
         * Copy the header into the newly allocate local space.
         */
        sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-       memcpy(sfp, sfhp, XFS_DIR2_SF_HDR_SIZE(sfhp->i8count));
+       memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count));
        dp->i_d.di_size = size;
        /*
         * Set up to loop over the block's entries.
         */
-       btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+       btp = xfs_dir2_block_tail_p(mp, block);
        ptr = (char *)block->u;
-       endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
-       sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+       endptr = (char *)xfs_dir2_block_leaf_p(btp);
+       sfep = xfs_dir2_sf_firstentry(sfp);
        /*
         * Loop over the active and unused entries.
         * Stop when we reach the leaf/tail portion of the block.
@@ -234,8 +218,8 @@ xfs_dir2_block_to_sf(
                 * If it's unused, just skip over it.
                 */
                dup = (xfs_dir2_data_unused_t *)ptr;
-               if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) {
-                       ptr += INT_GET(dup->length, ARCH_CONVERT);
+               if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
+                       ptr += be16_to_cpu(dup->length);
                        continue;
                }
                dep = (xfs_dir2_data_entry_t *)ptr;
@@ -243,35 +227,35 @@ xfs_dir2_block_to_sf(
                 * Skip .
                 */
                if (dep->namelen == 1 && dep->name[0] == '.')
-                       ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) == dp->i_ino);
+                       ASSERT(be64_to_cpu(dep->inumber) == dp->i_ino);
                /*
                 * Skip .., but make sure the inode number is right.
                 */
                else if (dep->namelen == 2 &&
                         dep->name[0] == '.' && dep->name[1] == '.')
-                       ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) ==
-                              XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
+                       ASSERT(be64_to_cpu(dep->inumber) ==
+                              xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent));
                /*
                 * Normal entry, copy it into shortform.
                 */
                else {
                        sfep->namelen = dep->namelen;
-                       XFS_DIR2_SF_PUT_OFFSET(sfep,
+                       xfs_dir2_sf_put_offset(sfep,
                                (xfs_dir2_data_aoff_t)
                                ((char *)dep - (char *)block));
                        memcpy(sfep->name, dep->name, dep->namelen);
-                       temp=INT_GET(dep->inumber, ARCH_CONVERT);
-                       XFS_DIR2_SF_PUT_INUMBER(sfp, &temp,
-                               XFS_DIR2_SF_INUMBERP(sfep));
-                       sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+                       temp = be64_to_cpu(dep->inumber);
+                       xfs_dir2_sf_put_inumber(sfp, &temp,
+                               xfs_dir2_sf_inumberp(sfep));
+                       sfep = xfs_dir2_sf_nextentry(sfp, sfep);
                }
-               ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+               ptr += xfs_dir2_data_entsize(dep->namelen);
        }
        ASSERT((char *)sfep - (char *)sfp == size);
        xfs_dir2_sf_check(args);
 out:
        xfs_trans_log_inode(args->trans, dp, logflags);
-       kmem_free(block, mp->m_dirblksize);
+       kmem_free(block);
        return error;
 }
 
@@ -291,11 +275,11 @@ xfs_dir2_sf_addname(
        int                     incr_isize;     /* total change in size */
        int                     new_isize;      /* di_size after adding name */
        int                     objchange;      /* changing to 8-byte inodes */
-       xfs_dir2_data_aoff_t    offset;         /* offset for new entry */
+       xfs_dir2_data_aoff_t    offset = 0;     /* offset for new entry */
        int                     old_isize;      /* di_size before adding name */
        int                     pick;           /* which algorithm to use */
        xfs_dir2_sf_t           *sfp;           /* shortform structure */
-       xfs_dir2_sf_entry_t     *sfep;          /* shortform entry */
+       xfs_dir2_sf_entry_t     *sfep = NULL;   /* shortform entry */
 
        xfs_dir2_trace_args("sf_addname", args);
        ASSERT(xfs_dir2_sf_lookup(args) == ENOENT);
@@ -311,11 +295,11 @@ xfs_dir2_sf_addname(
        ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
        ASSERT(dp->i_df.if_u1.if_data != NULL);
        sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-       ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+       ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
        /*
         * Compute entry (and change in) size.
         */
-       add_entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
+       add_entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
        incr_isize = add_entsize;
        objchange = 0;
 #if XFS_BIG_INUMS
@@ -348,7 +332,7 @@ xfs_dir2_sf_addname(
                /*
                 * Just checking or no space reservation, it doesn't fit.
                 */
-               if (args->justcheck || args->total == 0)
+               if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
                        return XFS_ERROR(ENOSPC);
                /*
                 * Convert to block form then add the name.
@@ -361,7 +345,7 @@ xfs_dir2_sf_addname(
        /*
         * Just checking, it fits.
         */
-       if (args->justcheck)
+       if (args->op_flags & XFS_DA_OP_JUSTCHECK)
                return 0;
        /*
         * Do it the easy way - just add it at the end.
@@ -409,7 +393,7 @@ xfs_dir2_sf_addname_easy(
        /*
         * Grow the in-inode space.
         */
-       xfs_idata_realloc(dp, XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen),
+       xfs_idata_realloc(dp, xfs_dir2_sf_entsize_byname(sfp, args->namelen),
                XFS_DATA_FORK);
        /*
         * Need to set up again due to realloc of the inode data.
@@ -420,10 +404,10 @@ xfs_dir2_sf_addname_easy(
         * Fill in the new entry.
         */
        sfep->namelen = args->namelen;
-       XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
+       xfs_dir2_sf_put_offset(sfep, offset);
        memcpy(sfep->name, args->name, sfep->namelen);
-       XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
-               XFS_DIR2_SF_INUMBERP(sfep));
+       xfs_dir2_sf_put_inumber(sfp, &args->inumber,
+               xfs_dir2_sf_inumberp(sfep));
        /*
         * Update the header and inode.
         */
@@ -480,14 +464,14 @@ xfs_dir2_sf_addname_hard(
         * If it's going to end up at the end then oldsfep will point there.
         */
        for (offset = XFS_DIR2_DATA_FIRST_OFFSET,
-             oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp),
-             add_datasize = XFS_DIR2_DATA_ENTSIZE(args->namelen),
+             oldsfep = xfs_dir2_sf_firstentry(oldsfp),
+             add_datasize = xfs_dir2_data_entsize(args->namelen),
              eof = (char *)oldsfep == &buf[old_isize];
             !eof;
-            offset = new_offset + XFS_DIR2_DATA_ENTSIZE(oldsfep->namelen),
-             oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep),
+            offset = new_offset + xfs_dir2_data_entsize(oldsfep->namelen),
+             oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep),
              eof = (char *)oldsfep == &buf[old_isize]) {
-               new_offset = XFS_DIR2_SF_GET_OFFSET(oldsfep);
+               new_offset = xfs_dir2_sf_get_offset(oldsfep);
                if (offset + add_datasize <= new_offset)
                        break;
        }
@@ -512,10 +496,10 @@ xfs_dir2_sf_addname_hard(
         * Fill in the new entry, and update the header counts.
         */
        sfep->namelen = args->namelen;
-       XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
+       xfs_dir2_sf_put_offset(sfep, offset);
        memcpy(sfep->name, args->name, sfep->namelen);
-       XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
-               XFS_DIR2_SF_INUMBERP(sfep));
+       xfs_dir2_sf_put_inumber(sfp, &args->inumber,
+               xfs_dir2_sf_inumberp(sfep));
        sfp->hdr.count++;
 #if XFS_BIG_INUMS
        if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
@@ -525,10 +509,10 @@ xfs_dir2_sf_addname_hard(
         * If there's more left to copy, do that.
         */
        if (!eof) {
-               sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+               sfep = xfs_dir2_sf_nextentry(sfp, sfep);
                memcpy(sfep, oldsfep, old_isize - nbytes);
        }
-       kmem_free(buf, old_isize);
+       kmem_free(buf);
        dp->i_d.di_size = new_isize;
        xfs_dir2_sf_check(args);
 }
@@ -561,9 +545,9 @@ xfs_dir2_sf_addname_pick(
        mp = dp->i_mount;
 
        sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-       size = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+       size = xfs_dir2_data_entsize(args->namelen);
        offset = XFS_DIR2_DATA_FIRST_OFFSET;
-       sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+       sfep = xfs_dir2_sf_firstentry(sfp);
        holefit = 0;
        /*
         * Loop over sf entries.
@@ -572,10 +556,10 @@ xfs_dir2_sf_addname_pick(
         */
        for (i = 0; i < sfp->hdr.count; i++) {
                if (!holefit)
-                       holefit = offset + size <= XFS_DIR2_SF_GET_OFFSET(sfep);
-               offset = XFS_DIR2_SF_GET_OFFSET(sfep) +
-                        XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
-               sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+                       holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
+               offset = xfs_dir2_sf_get_offset(sfep) +
+                        xfs_dir2_data_entsize(sfep->namelen);
+               sfep = xfs_dir2_sf_nextentry(sfp, sfep);
        }
        /*
         * Calculate data bytes used excluding the new entry, if this
@@ -634,18 +618,18 @@ xfs_dir2_sf_check(
 
        sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
        offset = XFS_DIR2_DATA_FIRST_OFFSET;
-       ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+       ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
        i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
 
-       for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+       for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
             i < sfp->hdr.count;
-            i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
-               ASSERT(XFS_DIR2_SF_GET_OFFSET(sfep) >= offset);
-               ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
+            i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
+               ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
+               ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
                i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
                offset =
-                       XFS_DIR2_SF_GET_OFFSET(sfep) +
-                       XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
+                       xfs_dir2_sf_get_offset(sfep) +
+                       xfs_dir2_data_entsize(sfep->namelen);
        }
        ASSERT(i8count == sfp->hdr.i8count);
        ASSERT(XFS_BIG_INUMS || i8count == 0);
@@ -688,7 +672,7 @@ xfs_dir2_sf_create(
        ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
        ASSERT(dp->i_df.if_bytes == 0);
        i8count = pino > XFS_DIR2_MAX_SHORT_INUM;
-       size = XFS_DIR2_SF_HDR_SIZE(i8count);
+       size = xfs_dir2_sf_hdr_size(i8count);
        /*
         * Make a buffer for the data.
         */
@@ -701,7 +685,7 @@ xfs_dir2_sf_create(
        /*
         * Now can put in the inode number, since i8count is set.
         */
-       XFS_DIR2_SF_PUT_INUMBER(sfp, &pino, &sfp->hdr.parent);
+       xfs_dir2_sf_put_inumber(sfp, &pino, &sfp->hdr.parent);
        sfp->hdr.count = 0;
        dp->i_d.di_size = size;
        xfs_dir2_sf_check(args);
@@ -712,19 +696,18 @@ xfs_dir2_sf_create(
 int                                            /* error */
 xfs_dir2_sf_getdents(
        xfs_inode_t             *dp,            /* incore directory inode */
-       uio_t                   *uio,           /* caller's buffer control */
-       int                     *eofp,          /* eof reached? (out) */
-       xfs_dirent_t            *dbp,           /* caller's buffer */
-       xfs_dir2_put_t          put)            /* abi's formatting function */
+       void                    *dirent,
+       xfs_off_t               *offset,
+       filldir_t               filldir)
 {
-       int                     error;          /* error return value */
        int                     i;              /* shortform entry number */
        xfs_mount_t             *mp;            /* filesystem mount point */
        xfs_dir2_dataptr_t      off;            /* current entry's offset */
-       xfs_dir2_put_args_t     p;              /* arg package for put rtn */
        xfs_dir2_sf_entry_t     *sfep;          /* shortform directory entry */
        xfs_dir2_sf_t           *sfp;           /* shortform structure */
-       xfs_off_t                       dir_offset;
+       xfs_dir2_dataptr_t      dot_offset;
+       xfs_dir2_dataptr_t      dotdot_offset;
+       xfs_ino_t               ino;
 
        mp = dp->i_mount;
 
@@ -737,120 +720,75 @@ xfs_dir2_sf_getdents(
                return XFS_ERROR(EIO);
        }
 
-       dir_offset = uio->uio_offset;
-
        ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
        ASSERT(dp->i_df.if_u1.if_data != NULL);
 
        sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
 
-       ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+       ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
 
        /*
         * If the block number in the offset is out of range, we're done.
         */
-       if (XFS_DIR2_DATAPTR_TO_DB(mp, dir_offset) > mp->m_dirdatablk) {
-               *eofp = 1;
+       if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk)
                return 0;
-       }
 
        /*
-        * Set up putargs structure.
+        * Precalculate offsets for . and .. as we will always need them.
+        *
+        * XXX(hch): the second argument is sometimes 0 and sometimes
+        * mp->m_dirdatablk.
         */
-       p.dbp = dbp;
-       p.put = put;
-       p.uio = uio;
+       dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+                                            XFS_DIR2_DATA_DOT_OFFSET);
+       dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+                                               XFS_DIR2_DATA_DOTDOT_OFFSET);
+
        /*
         * Put . entry unless we're starting past it.
         */
-       if (dir_offset <=
-                   XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-                                              XFS_DIR2_DATA_DOT_OFFSET)) {
-               p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, 0,
-                                               XFS_DIR2_DATA_DOTDOT_OFFSET);
-               p.ino = dp->i_ino;
-#if XFS_BIG_INUMS
-               p.ino += mp->m_inoadd;
-#endif
-               p.name = ".";
-               p.namelen = 1;
-
-               error = p.put(&p);
-
-               if (!p.done) {
-                       uio->uio_offset =
-                               XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-                                               XFS_DIR2_DATA_DOT_OFFSET);
-                       return error;
+       if (*offset <= dot_offset) {
+               if (filldir(dirent, ".", 1, dot_offset & 0x7fffffff, dp->i_ino, DT_DIR)) {
+                       *offset = dot_offset & 0x7fffffff;
+                       return 0;
                }
        }
 
        /*
         * Put .. entry unless we're starting past it.
         */
-       if (dir_offset <=
-                   XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-                                              XFS_DIR2_DATA_DOTDOT_OFFSET)) {
-               p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-                                               XFS_DIR2_DATA_FIRST_OFFSET);
-               p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
-#if XFS_BIG_INUMS
-               p.ino += mp->m_inoadd;
-#endif
-               p.name = "..";
-               p.namelen = 2;
-
-               error = p.put(&p);
-
-               if (!p.done) {
-                       uio->uio_offset =
-                               XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-                                       XFS_DIR2_DATA_DOTDOT_OFFSET);
-                       return error;
+       if (*offset <= dotdot_offset) {
+               ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
+               if (filldir(dirent, "..", 2, dotdot_offset & 0x7fffffff, ino, DT_DIR)) {
+                       *offset = dotdot_offset & 0x7fffffff;
+                       return 0;
                }
        }
 
        /*
         * Loop while there are more entries and put'ing works.
         */
-       for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
-                    i < sfp->hdr.count;
-                            i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
-
-               off = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-                               XFS_DIR2_SF_GET_OFFSET(sfep));
+       sfep = xfs_dir2_sf_firstentry(sfp);
+       for (i = 0; i < sfp->hdr.count; i++) {
+               off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+                               xfs_dir2_sf_get_offset(sfep));
 
-               if (dir_offset > off)
+               if (*offset > off) {
+                       sfep = xfs_dir2_sf_nextentry(sfp, sfep);
                        continue;
+               }
 
-               p.namelen = sfep->namelen;
-
-               p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
-                       XFS_DIR2_SF_GET_OFFSET(sfep) +
-                       XFS_DIR2_DATA_ENTSIZE(p.namelen));
-
-               p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
-#if XFS_BIG_INUMS
-               p.ino += mp->m_inoadd;
-#endif
-               p.name = (char *)sfep->name;
-
-               error = p.put(&p);
-
-               if (!p.done) {
-                       uio->uio_offset = off;
-                       return error;
+               ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
+               if (filldir(dirent, sfep->name, sfep->namelen,
+                           off & 0x7fffffff, ino, DT_UNKNOWN)) {
+                       *offset = off & 0x7fffffff;
+                       return 0;
                }
+               sfep = xfs_dir2_sf_nextentry(sfp, sfep);
        }
 
-       /*
-        * They all fit.
-        */
-       *eofp = 1;
-
-       uio->uio_offset =
-               XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0);
-
+       *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
+                       0x7fffffff;
        return 0;
 }
 
@@ -864,8 +802,11 @@ xfs_dir2_sf_lookup(
 {
        xfs_inode_t             *dp;            /* incore directory inode */
        int                     i;              /* entry index */
+       int                     error;
        xfs_dir2_sf_entry_t     *sfep;          /* shortform directory entry */
        xfs_dir2_sf_t           *sfp;           /* shortform structure */
+       enum xfs_dacmp          cmp;            /* comparison result */
+       xfs_dir2_sf_entry_t     *ci_sfep;       /* case-insens. entry */
 
        xfs_dir2_trace_args("sf_lookup", args);
        xfs_dir2_sf_check(args);
@@ -882,12 +823,13 @@ xfs_dir2_sf_lookup(
        ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
        ASSERT(dp->i_df.if_u1.if_data != NULL);
        sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-       ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+       ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
        /*
         * Special case for .
         */
        if (args->namelen == 1 && args->name[0] == '.') {
                args->inumber = dp->i_ino;
+               args->cmpresult = XFS_CMP_EXACT;
                return XFS_ERROR(EEXIST);
        }
        /*
@@ -895,29 +837,42 @@ xfs_dir2_sf_lookup(
         */
        if (args->namelen == 2 &&
            args->name[0] == '.' && args->name[1] == '.') {
-               args->inumber = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+               args->inumber = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
+               args->cmpresult = XFS_CMP_EXACT;
                return XFS_ERROR(EEXIST);
        }
        /*
         * Loop over all the entries trying to match ours.
         */
-       for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
-            i < sfp->hdr.count;
-            i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
-               if (sfep->namelen == args->namelen &&
-                   sfep->name[0] == args->name[0] &&
-                   memcmp(args->name, sfep->name, args->namelen) == 0) {
-                       args->inumber =
-                               XFS_DIR2_SF_GET_INUMBER(sfp,
-                                       XFS_DIR2_SF_INUMBERP(sfep));
-                       return XFS_ERROR(EEXIST);
+       ci_sfep = NULL;
+       for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count;
+                               i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
+               /*
+                * Compare name and if it's an exact match, return the inode
+                * number. If it's the first case-insensitive match, store the
+                * inode number and continue looking for an exact match.
+                */
+               cmp = dp->i_mount->m_dirnameops->compname(args, sfep->name,
+                                                               sfep->namelen);
+               if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
+                       args->cmpresult = cmp;
+                       args->inumber = xfs_dir2_sf_get_inumber(sfp,
+                                               xfs_dir2_sf_inumberp(sfep));
+                       if (cmp == XFS_CMP_EXACT)
+                               return XFS_ERROR(EEXIST);
+                       ci_sfep = sfep;
                }
        }
+       ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
        /*
-        * Didn't find it.
+        * Here, we can only be doing a lookup (not a rename or replace).
+        * If a case-insensitive match was not found, return ENOENT.
         */
-       ASSERT(args->oknoent);
-       return XFS_ERROR(ENOENT);
+       if (!ci_sfep)
+               return XFS_ERROR(ENOENT);
+       /* otherwise process the CI match as required by the caller */
+       error = xfs_dir_cilookup_result(args, ci_sfep->name, ci_sfep->namelen);
+       return XFS_ERROR(error);
 }
 
 /*
@@ -951,34 +906,31 @@ xfs_dir2_sf_removename(
        ASSERT(dp->i_df.if_bytes == oldsize);
        ASSERT(dp->i_df.if_u1.if_data != NULL);
        sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-       ASSERT(oldsize >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+       ASSERT(oldsize >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
        /*
         * Loop over the old directory entries.
         * Find the one we're deleting.
         */
-       for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
-            i < sfp->hdr.count;
-            i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
-               if (sfep->namelen == args->namelen &&
-                   sfep->name[0] == args->name[0] &&
-                   memcmp(sfep->name, args->name, args->namelen) == 0) {
-                       ASSERT(XFS_DIR2_SF_GET_INUMBER(sfp,
-                                       XFS_DIR2_SF_INUMBERP(sfep)) ==
-                               args->inumber);
+       for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count;
+                               i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
+               if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
+                                                               XFS_CMP_EXACT) {
+                       ASSERT(xfs_dir2_sf_get_inumber(sfp,
+                                               xfs_dir2_sf_inumberp(sfep)) ==
+                                                               args->inumber);
                        break;
                }
        }
        /*
         * Didn't find it.
         */
-       if (i == sfp->hdr.count) {
+       if (i == sfp->hdr.count)
                return XFS_ERROR(ENOENT);
-       }
        /*
         * Calculate sizes.
         */
        byteoff = (int)((char *)sfep - (char *)sfp);
-       entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
+       entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
        newsize = oldsize - entsize;
        /*
         * Copy the part if any after the removed entry, sliding it down.
@@ -1044,7 +996,7 @@ xfs_dir2_sf_replace(
        ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
        ASSERT(dp->i_df.if_u1.if_data != NULL);
        sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
-       ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+       ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
 #if XFS_BIG_INUMS
        /*
         * New inode number is large, and need to convert to 8-byte inodes.
@@ -1084,28 +1036,27 @@ xfs_dir2_sf_replace(
        if (args->namelen == 2 &&
            args->name[0] == '.' && args->name[1] == '.') {
 #if XFS_BIG_INUMS || defined(DEBUG)
-               ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+               ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
                ASSERT(args->inumber != ino);
 #endif
-               XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber, &sfp->hdr.parent);
+               xfs_dir2_sf_put_inumber(sfp, &args->inumber, &sfp->hdr.parent);
        }
        /*
         * Normal entry, look for the name.
         */
        else {
-               for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
-                    i < sfp->hdr.count;
-                    i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
-                       if (sfep->namelen == args->namelen &&
-                           sfep->name[0] == args->name[0] &&
-                           memcmp(args->name, sfep->name, args->namelen) == 0) {
+               for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
+                               i < sfp->hdr.count;
+                               i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
+                       if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
+                                                               XFS_CMP_EXACT) {
 #if XFS_BIG_INUMS || defined(DEBUG)
-                               ino = XFS_DIR2_SF_GET_INUMBER(sfp,
-                                       XFS_DIR2_SF_INUMBERP(sfep));
+                               ino = xfs_dir2_sf_get_inumber(sfp,
+                                       xfs_dir2_sf_inumberp(sfep));
                                ASSERT(args->inumber != ino);
 #endif
-                               XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
-                                       XFS_DIR2_SF_INUMBERP(sfep));
+                               xfs_dir2_sf_put_inumber(sfp, &args->inumber,
+                                       xfs_dir2_sf_inumberp(sfep));
                                break;
                        }
                }
@@ -1113,7 +1064,7 @@ xfs_dir2_sf_replace(
                 * Didn't find it.
                 */
                if (i == sfp->hdr.count) {
-                       ASSERT(args->oknoent);
+                       ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
 #if XFS_BIG_INUMS
                        if (i8elevated)
                                xfs_dir2_sf_toino4(args);
@@ -1206,27 +1157,27 @@ xfs_dir2_sf_toino4(
         */
        sfp->hdr.count = oldsfp->hdr.count;
        sfp->hdr.i8count = 0;
-       ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
-       XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
+       ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
+       xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
        /*
         * Copy the entries field by field.
         */
-       for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
-                   oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
+       for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
+                   oldsfep = xfs_dir2_sf_firstentry(oldsfp);
             i < sfp->hdr.count;
-            i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
-                 oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
+            i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
+                 oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
                sfep->namelen = oldsfep->namelen;
                sfep->offset = oldsfep->offset;
                memcpy(sfep->name, oldsfep->name, sfep->namelen);
-               ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
-                       XFS_DIR2_SF_INUMBERP(oldsfep));
-               XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
+               ino = xfs_dir2_sf_get_inumber(oldsfp,
+                       xfs_dir2_sf_inumberp(oldsfep));
+               xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
        }
        /*
         * Clean up the inode.
         */
-       kmem_free(buf, oldsize);
+       kmem_free(buf);
        dp->i_d.di_size = newsize;
        xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
 }
@@ -1283,27 +1234,27 @@ xfs_dir2_sf_toino8(
         */
        sfp->hdr.count = oldsfp->hdr.count;
        sfp->hdr.i8count = 1;
-       ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
-       XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
+       ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
+       xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
        /*
         * Copy the entries field by field.
         */
-       for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
-                   oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
+       for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
+                   oldsfep = xfs_dir2_sf_firstentry(oldsfp);
             i < sfp->hdr.count;
-            i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
-                 oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
+            i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
+                 oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
                sfep->namelen = oldsfep->namelen;
                sfep->offset = oldsfep->offset;
                memcpy(sfep->name, oldsfep->name, sfep->namelen);
-               ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
-                       XFS_DIR2_SF_INUMBERP(oldsfep));
-               XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
+               ino = xfs_dir2_sf_get_inumber(oldsfp,
+                       xfs_dir2_sf_inumberp(oldsfep));
+               xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
        }
        /*
         * Clean up the inode.
         */
-       kmem_free(buf, oldsize);
+       kmem_free(buf);
        dp->i_d.di_size = newsize;
        xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
 }