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 06afa1b..e89734e 100644 (file)
 #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"
@@ -92,8 +90,8 @@ xfs_dir2_block_sfsize(
        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.
@@ -105,7 +103,7 @@ xfs_dir2_block_sfsize(
                 * 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.
@@ -127,7 +125,7 @@ xfs_dir2_block_sfsize(
                /*
                 * 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 */
@@ -142,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;
 }
 
@@ -202,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.
@@ -236,28 +234,28 @@ xfs_dir2_block_to_sf(
                else if (dep->namelen == 2 &&
                         dep->name[0] == '.' && dep->name[1] == '.')
                        ASSERT(be64_to_cpu(dep->inumber) ==
-                              XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
+                              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 = be64_to_cpu(dep->inumber);
-                       XFS_DIR2_SF_PUT_INUMBER(sfp, &temp,
-                               XFS_DIR2_SF_INUMBERP(sfep));
-                       sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+                       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;
 }
 
@@ -297,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
@@ -334,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.
@@ -347,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.
@@ -395,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.
@@ -406,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.
         */
@@ -466,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;
        }
@@ -498,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)
@@ -511,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);
 }
@@ -547,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.
@@ -558,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
@@ -620,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);
@@ -674,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.
         */
@@ -687,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);
@@ -698,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;
 
@@ -723,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;
 }
 
@@ -850,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);
@@ -868,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);
        }
        /*
@@ -881,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);
 }
 
 /*
@@ -937,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.
@@ -1030,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.
@@ -1070,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;
                        }
                }
@@ -1099,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);
@@ -1192,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);
 }
@@ -1269,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);
 }