]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - libxfs/xfs_dir2_block.c
xfs: convert to SPDX license tags
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_dir2_block.c
index cede01f545cbeec7cfc22df26afb636f2d9deba4..d1ffdb391aaf7417b1cf3a0e414f6edf7613d021 100644 (file)
@@ -1,23 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
  * Copyright (c) 2013 Red Hat, Inc.
  * All Rights Reserved.
- *
- * 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.  See the
- * GNU General Public License for more details.
- *
- * 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 "libxfs_priv.h"
+#include "xfs_fs.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_mount.h"
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_inode.h"
+#include "xfs_trans.h"
+#include "xfs_bmap.h"
+#include "xfs_dir2.h"
+#include "xfs_dir2_priv.h"
+#include "xfs_trace.h"
+#include "xfs_cksum.h"
 
 /*
  * Local function prototypes.
@@ -41,7 +42,7 @@ xfs_dir_startup(void)
        xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2);
 }
 
-static bool
+static xfs_failaddr_t
 xfs_dir3_block_verify(
        struct xfs_buf          *bp)
 {
@@ -50,18 +51,18 @@ xfs_dir3_block_verify(
 
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                if (hdr3->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC))
-                       return false;
-               if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid))
-                       return false;
+                       return __this_address;
+               if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
+                       return __this_address;
                if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
-                       return false;
+                       return __this_address;
+               if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
+                       return __this_address;
        } else {
                if (hdr3->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
-                       return false;
+                       return __this_address;
        }
-       if (__xfs_dir3_data_check(NULL, bp))
-               return false;
-       return true;
+       return __xfs_dir3_data_check(NULL, bp);
 }
 
 static void
@@ -69,15 +70,16 @@ xfs_dir3_block_read_verify(
        struct xfs_buf  *bp)
 {
        struct xfs_mount        *mp = bp->b_target->bt_mount;
+       xfs_failaddr_t          fa;
 
        if (xfs_sb_version_hascrc(&mp->m_sb) &&
             !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
-               xfs_buf_ioerror(bp, EFSBADCRC);
-       else if (!xfs_dir3_block_verify(bp))
-               xfs_buf_ioerror(bp, EFSCORRUPTED);
-
-       if (bp->b_error)
-               xfs_verifier_error(bp);
+               xfs_verifier_error(bp, -EFSBADCRC, __this_address);
+       else {
+               fa = xfs_dir3_block_verify(bp);
+               if (fa)
+                       xfs_verifier_error(bp, -EFSCORRUPTED, fa);
+       }
 }
 
 static void
@@ -85,12 +87,13 @@ xfs_dir3_block_write_verify(
        struct xfs_buf  *bp)
 {
        struct xfs_mount        *mp = bp->b_target->bt_mount;
-       struct xfs_buf_log_item *bip = bp->b_fspriv;
+       struct xfs_buf_log_item *bip = bp->b_log_item;
        struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
+       xfs_failaddr_t          fa;
 
-       if (!xfs_dir3_block_verify(bp)) {
-               xfs_buf_ioerror(bp, EFSCORRUPTED);
-               xfs_verifier_error(bp);
+       fa = xfs_dir3_block_verify(bp);
+       if (fa) {
+               xfs_verifier_error(bp, -EFSCORRUPTED, fa);
                return;
        }
 
@@ -104,8 +107,10 @@ xfs_dir3_block_write_verify(
 }
 
 const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
+       .name = "xfs_dir3_block",
        .verify_read = xfs_dir3_block_read_verify,
        .verify_write = xfs_dir3_block_write_verify,
+       .verify_struct = xfs_dir3_block_verify,
 };
 
 int
@@ -117,9 +122,9 @@ xfs_dir3_block_read(
        struct xfs_mount        *mp = dp->i_mount;
        int                     err;
 
-       err = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp,
+       err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, -1, bpp,
                                XFS_DATA_FORK, &xfs_dir3_block_buf_ops);
-       if (!err && tp)
+       if (!err && tp && *bpp)
                xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF);
        return err;
 }
@@ -141,7 +146,7 @@ xfs_dir3_block_init(
                hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
                hdr3->blkno = cpu_to_be64(bp->b_bn);
                hdr3->owner = cpu_to_be64(dp->i_ino);
-               uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid);
+               uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
                return;
 
        }
@@ -150,6 +155,7 @@ xfs_dir3_block_init(
 
 static void
 xfs_dir2_block_need_space(
+       struct xfs_inode                *dp,
        struct xfs_dir2_data_hdr        *hdr,
        struct xfs_dir2_block_tail      *btp,
        struct xfs_dir2_leaf_entry      *blp,
@@ -165,7 +171,7 @@ xfs_dir2_block_need_space(
        struct xfs_dir2_data_unused     *enddup = NULL;
 
        *compact = 0;
-       bf = xfs_dir3_data_bestfree_p(hdr);
+       bf = dp->d_ops->data_bestfree_p(hdr);
 
        /*
         * If there are stale entries we'll use one for the leaf.
@@ -261,7 +267,7 @@ out:
  */
 static void
 xfs_dir2_block_compact(
-       struct xfs_trans                *tp,
+       struct xfs_da_args              *args,
        struct xfs_buf                  *bp,
        struct xfs_dir2_data_hdr        *hdr,
        struct xfs_dir2_block_tail      *btp,
@@ -294,18 +300,17 @@ xfs_dir2_block_compact(
        *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
        *lfloghigh -= be32_to_cpu(btp->stale) - 1;
        be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
-       xfs_dir2_data_make_free(tp, bp,
+       xfs_dir2_data_make_free(args, bp,
                (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
                (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
                needlog, &needscan);
-       blp += be32_to_cpu(btp->stale) - 1;
        btp->stale = cpu_to_be32(1);
        /*
         * If we now need to rebuild the bestfree map, do so.
         * This needs to happen before the next call to use_free.
         */
        if (needscan)
-               xfs_dir2_data_freescan(tp->t_mountp, hdr, needlog);
+               xfs_dir2_data_freescan(args->dp, hdr, needlog);
 }
 
 /*
@@ -334,7 +339,6 @@ xfs_dir2_block_addname(
        int                     low;            /* low index for binary srch */
        int                     lowstale;       /* low stale index */
        int                     mid=0;          /* midpoint for binary srch */
-       xfs_mount_t             *mp;            /* filesystem mount point */
        int                     needlog;        /* need to log header */
        int                     needscan;       /* need to rescan freespace */
        __be16                  *tagp;          /* pointer to tag value */
@@ -344,27 +348,26 @@ xfs_dir2_block_addname(
 
        dp = args->dp;
        tp = args->trans;
-       mp = dp->i_mount;
 
        /* Read the (one and only) directory block into bp. */
        error = xfs_dir3_block_read(tp, dp, &bp);
        if (error)
                return error;
 
-       len = xfs_dir3_data_entsize(mp, args->namelen);
+       len = dp->d_ops->data_entsize(args->namelen);
 
        /*
         * Set up pointers to parts of the block.
         */
        hdr = bp->b_addr;
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
 
        /*
         * Find out if we can reuse stale entries or whether we need extra
         * space for entry and new leaf.
         */
-       xfs_dir2_block_need_space(hdr, btp, blp, &tagp, &dup,
+       xfs_dir2_block_need_space(dp, hdr, btp, blp, &tagp, &dup,
                                  &enddup, &compact, len);
 
        /*
@@ -373,7 +376,7 @@ xfs_dir2_block_addname(
        if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
                xfs_trans_brelse(tp, bp);
                if (!dup)
-                       return XFS_ERROR(ENOSPC);
+                       return -ENOSPC;
                return 0;
        }
 
@@ -383,7 +386,7 @@ xfs_dir2_block_addname(
        if (!dup) {
                /* Don't have a space reservation: return no-space.  */
                if (args->total == 0)
-                       return XFS_ERROR(ENOSPC);
+                       return -ENOSPC;
                /*
                 * Convert to the next larger format.
                 * Then add the new entry in that format.
@@ -400,7 +403,7 @@ xfs_dir2_block_addname(
         * If need to compact the leaf entries, do it now.
         */
        if (compact) {
-               xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog,
+               xfs_dir2_block_compact(args, bp, hdr, btp, blp, &needlog,
                                      &lfloghigh, &lfloglow);
                /* recalculate blp post-compaction */
                blp = xfs_dir2_block_leaf_p(btp);
@@ -432,15 +435,19 @@ xfs_dir2_block_addname(
         * No stale entries, will use enddup space to hold new leaf.
         */
        if (!btp->stale) {
+               xfs_dir2_data_aoff_t    aoff;
+
                /*
                 * Mark the space needed for the new leaf entry, now in use.
                 */
-               xfs_dir2_data_use_free(tp, bp, enddup,
-                       (xfs_dir2_data_aoff_t)
-                       ((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) -
-                        sizeof(*blp)),
-                       (xfs_dir2_data_aoff_t)sizeof(*blp),
-                       &needlog, &needscan);
+               aoff = (xfs_dir2_data_aoff_t)((char *)enddup - (char *)hdr +
+                               be16_to_cpu(enddup->length) - sizeof(*blp));
+               error = xfs_dir2_data_use_free(args, bp, enddup, aoff,
+                               (xfs_dir2_data_aoff_t)sizeof(*blp), &needlog,
+                               &needscan);
+               if (error)
+                       return error;
+
                /*
                 * Update the tail (entry count).
                 */
@@ -450,7 +457,7 @@ xfs_dir2_block_addname(
                 * This needs to happen before the next call to use_free.
                 */
                if (needscan) {
-                       xfs_dir2_data_freescan(mp, hdr, &needlog);
+                       xfs_dir2_data_freescan(dp, hdr, &needlog);
                        needscan = 0;
                }
                /*
@@ -516,33 +523,35 @@ xfs_dir2_block_addname(
         * Fill in the leaf entry.
         */
        blp[mid].hashval = cpu_to_be32(args->hashval);
-       blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
+       blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
                                (char *)dep - (char *)hdr));
        xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh);
        /*
         * Mark space for the data entry used.
         */
-       xfs_dir2_data_use_free(tp, bp, dup,
-               (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
-               (xfs_dir2_data_aoff_t)len, &needlog, &needscan);
+       error = xfs_dir2_data_use_free(args, bp, dup,
+                       (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
+                       (xfs_dir2_data_aoff_t)len, &needlog, &needscan);
+       if (error)
+               return error;
        /*
         * Create the new data entry.
         */
        dep->inumber = cpu_to_be64(args->inumber);
        dep->namelen = args->namelen;
        memcpy(dep->name, args->name, args->namelen);
-       xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
-       tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+       dp->d_ops->data_put_ftype(dep, args->filetype);
+       tagp = dp->d_ops->data_entry_tag_p(dep);
        *tagp = cpu_to_be16((char *)dep - (char *)hdr);
        /*
         * Clean up the bestfree array and log the header, tail, and entry.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(dp, hdr, &needlog);
        if (needlog)
-               xfs_dir2_data_log_header(tp, bp);
+               xfs_dir2_data_log_header(args, bp);
        xfs_dir2_block_log_tail(tp, bp);
-       xfs_dir2_data_log_entry(tp, bp, dep);
+       xfs_dir2_data_log_entry(args, bp, dep);
        xfs_dir3_data_check(dp, bp);
        return 0;
 }
@@ -561,7 +570,7 @@ xfs_dir2_block_log_leaf(
        xfs_dir2_leaf_entry_t   *blp;
        xfs_dir2_block_tail_t   *btp;
 
-       btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr);
+       btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr),
                (uint)((char *)&blp[last + 1] - (char *)hdr - 1));
@@ -578,7 +587,7 @@ xfs_dir2_block_log_tail(
        xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
        xfs_dir2_block_tail_t   *btp;
 
-       btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr);
+       btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr);
        xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr),
                (uint)((char *)(btp + 1) - (char *)hdr - 1));
 }
@@ -599,7 +608,6 @@ xfs_dir2_block_lookup(
        xfs_inode_t             *dp;            /* incore inode */
        int                     ent;            /* entry index */
        int                     error;          /* error return value */
-       xfs_mount_t             *mp;            /* filesystem mount point */
 
        trace_xfs_dir2_block_lookup(args);
 
@@ -610,24 +618,24 @@ xfs_dir2_block_lookup(
        if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent)))
                return error;
        dp = args->dp;
-       mp = dp->i_mount;
        hdr = bp->b_addr;
        xfs_dir3_data_check(dp, bp);
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
         * Get the offset from the leaf entry, to point to the data.
         */
        dep = (xfs_dir2_data_entry_t *)((char *)hdr +
-               xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
+                       xfs_dir2_dataptr_to_off(args->geo,
+                                               be32_to_cpu(blp[ent].address)));
        /*
         * Fill in inode number, CI name if appropriate, release the block.
         */
        args->inumber = be64_to_cpu(dep->inumber);
-       args->filetype = xfs_dir3_dirent_get_ftype(mp, dep);
+       args->filetype = dp->d_ops->data_get_ftype(dep);
        error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
        xfs_trans_brelse(args->trans, bp);
-       return XFS_ERROR(error);
+       return error;
 }
 
 /*
@@ -665,7 +673,7 @@ xfs_dir2_block_lookup_int(
 
        hdr = bp->b_addr;
        xfs_dir3_data_check(dp, bp);
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
         * Loop doing a binary search for our hash value.
@@ -683,7 +691,7 @@ xfs_dir2_block_lookup_int(
                if (low > high) {
                        ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
                        xfs_trans_brelse(tp, bp);
-                       return XFS_ERROR(ENOENT);
+                       return -ENOENT;
                }
        }
        /*
@@ -703,7 +711,7 @@ xfs_dir2_block_lookup_int(
                 * Get pointer to the entry from the leaf.
                 */
                dep = (xfs_dir2_data_entry_t *)
-                       ((char *)hdr + xfs_dir2_dataptr_to_off(mp, addr));
+                       ((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, addr));
                /*
                 * Compare name and if it's an exact match, return the index
                 * and buffer. If it's the first case-insensitive match, store
@@ -731,7 +739,7 @@ xfs_dir2_block_lookup_int(
         * No match, release the buffer and return ENOENT.
         */
        xfs_trans_brelse(tp, bp);
-       return XFS_ERROR(ENOENT);
+       return -ENOENT;
 }
 
 /*
@@ -750,7 +758,6 @@ xfs_dir2_block_removename(
        xfs_inode_t             *dp;            /* incore inode */
        int                     ent;            /* block leaf entry index */
        int                     error;          /* error return value */
-       xfs_mount_t             *mp;            /* filesystem mount point */
        int                     needlog;        /* need to log block header */
        int                     needscan;       /* need to fixup bestfree */
        xfs_dir2_sf_hdr_t       sfh;            /* shortform header */
@@ -768,22 +775,22 @@ xfs_dir2_block_removename(
        }
        dp = args->dp;
        tp = args->trans;
-       mp = dp->i_mount;
        hdr = bp->b_addr;
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
         * Point to the data entry using the leaf entry.
         */
-       dep = (xfs_dir2_data_entry_t *)
-             ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
+       dep = (xfs_dir2_data_entry_t *)((char *)hdr +
+                       xfs_dir2_dataptr_to_off(args->geo,
+                                               be32_to_cpu(blp[ent].address)));
        /*
         * Mark the data entry's space free.
         */
        needlog = needscan = 0;
-       xfs_dir2_data_make_free(tp, bp,
+       xfs_dir2_data_make_free(args, bp,
                (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
-               xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan);
+               dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
        /*
         * Fix up the block tail.
         */
@@ -798,9 +805,9 @@ xfs_dir2_block_removename(
         * Fix up bestfree, log the header if necessary.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(dp, hdr, &needlog);
        if (needlog)
-               xfs_dir2_data_log_header(tp, bp);
+               xfs_dir2_data_log_header(args, bp);
        xfs_dir3_data_check(dp, bp);
        /*
         * See if the size as a shortform is good enough.
@@ -831,7 +838,6 @@ xfs_dir2_block_replace(
        xfs_inode_t             *dp;            /* incore inode */
        int                     ent;            /* leaf entry index */
        int                     error;          /* error return value */
-       xfs_mount_t             *mp;            /* filesystem mount point */
 
        trace_xfs_dir2_block_replace(args);
 
@@ -843,22 +849,22 @@ xfs_dir2_block_replace(
                return error;
        }
        dp = args->dp;
-       mp = dp->i_mount;
        hdr = bp->b_addr;
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
         * Point to the data entry we need to change.
         */
-       dep = (xfs_dir2_data_entry_t *)
-             ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
+       dep = (xfs_dir2_data_entry_t *)((char *)hdr +
+                       xfs_dir2_dataptr_to_off(args->geo,
+                                               be32_to_cpu(blp[ent].address)));
        ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
        /*
         * Change the inode number to the new value.
         */
        dep->inumber = cpu_to_be64(args->inumber);
-       xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
-       xfs_dir2_data_log_entry(args->trans, bp, dep);
+       dp->d_ops->data_put_ftype(dep, args->filetype);
+       xfs_dir2_data_log_entry(args, bp, dep);
        xfs_dir3_data_check(dp, bp);
        return 0;
 }
@@ -916,9 +922,9 @@ xfs_dir2_leaf_to_block(
        tp = args->trans;
        mp = dp->i_mount;
        leaf = lbp->b_addr;
-       xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = xfs_dir3_leaf_ents_p(leaf);
-       ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+       dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
+       ents = dp->d_ops->leaf_ents_p(leaf);
+       ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
 
        ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
               leafhdr.magic == XFS_DIR3_LEAF1_MAGIC);
@@ -928,13 +934,13 @@ xfs_dir2_leaf_to_block(
         * been left behind during no-space-reservation operations.
         * These will show up in the leaf bests table.
         */
-       while (dp->i_d.di_size > mp->m_dirblksize) {
+       while (dp->i_d.di_size > args->geo->blksize) {
                int hdrsz;
 
-               hdrsz = xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
+               hdrsz = dp->d_ops->data_entry_offset;
                bestsp = xfs_dir2_leaf_bests_p(ltp);
                if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
-                                           mp->m_dirblksize - hdrsz) {
+                                           args->geo->blksize - hdrsz) {
                        if ((error =
                            xfs_dir2_leaf_trim_data(args, lbp,
                                    (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1))))
@@ -946,7 +952,7 @@ xfs_dir2_leaf_to_block(
         * Read the data block if we don't already have it, give up if it fails.
         */
        if (!dbp) {
-               error = xfs_dir3_data_read(tp, dp, mp->m_dirdatablk, -1, &dbp);
+               error = xfs_dir3_data_read(tp, dp, args->geo->datablk, -1, &dbp);
                if (error)
                        return error;
        }
@@ -962,7 +968,7 @@ xfs_dir2_leaf_to_block(
        /*
         * Look at the last data entry.
         */
-       tagp = (__be16 *)((char *)hdr + mp->m_dirblksize) - 1;
+       tagp = (__be16 *)((char *)hdr + args->geo->blksize) - 1;
        dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
        /*
         * If it's not free or is too short we can't do it.
@@ -981,12 +987,14 @@ xfs_dir2_leaf_to_block(
        /*
         * Use up the space at the end of the block (blp/btp).
         */
-       xfs_dir2_data_use_free(tp, dbp, dup, mp->m_dirblksize - size, size,
-               &needlog, &needscan);
+       error = xfs_dir2_data_use_free(args, dbp, dup,
+                       args->geo->blksize - size, size, &needlog, &needscan);
+       if (error)
+               return error;
        /*
         * Initialize the block tail.
         */
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        btp->count = cpu_to_be32(leafhdr.count - leafhdr.stale);
        btp->stale = 0;
        xfs_dir2_block_log_tail(tp, dbp);
@@ -1005,13 +1013,13 @@ xfs_dir2_leaf_to_block(
         * Scan the bestfree if we need it and log the data block header.
         */
        if (needscan)
-               xfs_dir2_data_freescan(mp, hdr, &needlog);
+               xfs_dir2_data_freescan(dp, hdr, &needlog);
        if (needlog)
-               xfs_dir2_data_log_header(tp, dbp);
+               xfs_dir2_data_log_header(args, dbp);
        /*
         * Pitch the old leaf block.
         */
-       error = xfs_da_shrink_inode(args, mp->m_dirleafblk, lbp);
+       error = xfs_da_shrink_inode(args, args->geo->leafblk, lbp);
        if (error)
                return error;
 
@@ -1069,7 +1077,7 @@ xfs_dir2_sf_to_block(
         */
        if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
                ASSERT(XFS_FORCED_SHUTDOWN(mp));
-               return XFS_ERROR(EIO);
+               return -EIO;
        }
 
        oldsfp = (xfs_dir2_sf_hdr_t *)ifp->if_u1.if_data;
@@ -1094,18 +1102,14 @@ xfs_dir2_sf_to_block(
         * Add block 0 to the inode.
         */
        error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno);
-       if (error) {
-               kmem_free(sfp);
-               return error;
-       }
+       if (error)
+               goto out_free;
        /*
         * Initialize the data block, then convert it to block format.
         */
        error = xfs_dir3_data_init(args, blkno, &bp);
-       if (error) {
-               kmem_free(sfp);
-               return error;
-       }
+       if (error)
+               goto out_free;
        xfs_dir3_block_init(mp, tp, bp, dp);
        hdr = bp->b_addr;
 
@@ -1118,15 +1122,17 @@ xfs_dir2_sf_to_block(
         * The whole thing is initialized to free by the init routine.
         * Say we're using the leaf and tail area.
         */
-       dup = xfs_dir3_data_unused_p(hdr);
+       dup = dp->d_ops->data_unused_p(hdr);
        needlog = needscan = 0;
-       xfs_dir2_data_use_free(tp, bp, dup, mp->m_dirblksize - i, i, &needlog,
-               &needscan);
+       error = xfs_dir2_data_use_free(args, bp, dup, args->geo->blksize - i,
+                       i, &needlog, &needscan);
+       if (error)
+               goto out_free;
        ASSERT(needscan == 0);
        /*
         * Fill in the tail.
         */
-       btp = xfs_dir2_block_tail_p(mp, hdr);
+       btp = xfs_dir2_block_tail_p(args->geo, hdr);
        btp->count = cpu_to_be32(sfp->count + 2);       /* ., .. */
        btp->stale = 0;
        blp = xfs_dir2_block_leaf_p(btp);
@@ -1134,38 +1140,40 @@ xfs_dir2_sf_to_block(
        /*
         * Remove the freespace, we'll manage it.
         */
-       xfs_dir2_data_use_free(tp, bp, dup,
-               (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
-               be16_to_cpu(dup->length), &needlog, &needscan);
+       error = xfs_dir2_data_use_free(args, bp, dup,
+                       (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
+                       be16_to_cpu(dup->length), &needlog, &needscan);
+       if (error)
+               goto out_free;
        /*
         * Create entry for .
         */
-       dep = xfs_dir3_data_dot_entry_p(mp, hdr);
+       dep = dp->d_ops->data_dot_entry_p(hdr);
        dep->inumber = cpu_to_be64(dp->i_ino);
        dep->namelen = 1;
        dep->name[0] = '.';
-       xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR);
-       tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+       dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
+       tagp = dp->d_ops->data_entry_tag_p(dep);
        *tagp = cpu_to_be16((char *)dep - (char *)hdr);
-       xfs_dir2_data_log_entry(tp, bp, dep);
+       xfs_dir2_data_log_entry(args, bp, dep);
        blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
-       blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
+       blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
                                (char *)dep - (char *)hdr));
        /*
         * Create entry for ..
         */
-       dep = xfs_dir3_data_dotdot_entry_p(mp, hdr);
-       dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));
+       dep = dp->d_ops->data_dotdot_entry_p(hdr);
+       dep->inumber = cpu_to_be64(dp->d_ops->sf_get_parent_ino(sfp));
        dep->namelen = 2;
        dep->name[0] = dep->name[1] = '.';
-       xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR);
-       tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+       dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
+       tagp = dp->d_ops->data_entry_tag_p(dep);
        *tagp = cpu_to_be16((char *)dep - (char *)hdr);
-       xfs_dir2_data_log_entry(tp, bp, dep);
+       xfs_dir2_data_log_entry(args, bp, dep);
        blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
-       blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
+       blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
                                (char *)dep - (char *)hdr));
-       offset = xfs_dir3_data_first_offset(mp);
+       offset = dp->d_ops->data_first_offset;
        /*
         * Loop over existing entries, stuff them in.
         */
@@ -1195,8 +1203,10 @@ xfs_dir2_sf_to_block(
                        dup->length = cpu_to_be16(newoffset - offset);
                        *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(
                                ((char *)dup - (char *)hdr));
-                       xfs_dir2_data_log_unused(tp, bp, dup);
-                       xfs_dir2_data_freeinsert(hdr, dup, &dummy);
+                       xfs_dir2_data_log_unused(args, bp, dup);
+                       xfs_dir2_data_freeinsert(hdr,
+                                                dp->d_ops->data_bestfree_p(hdr),
+                                                dup, &dummy);
                        offset += be16_to_cpu(dup->length);
                        continue;
                }
@@ -1204,25 +1214,24 @@ xfs_dir2_sf_to_block(
                 * Copy a real entry.
                 */
                dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset);
-               dep->inumber = cpu_to_be64(xfs_dir3_sfe_get_ino(mp, sfp, sfep));
+               dep->inumber = cpu_to_be64(dp->d_ops->sf_get_ino(sfp, sfep));
                dep->namelen = sfep->namelen;
-               xfs_dir3_dirent_put_ftype(mp, dep,
-                                       xfs_dir3_sfe_get_ftype(mp, sfp, sfep));
+               dp->d_ops->data_put_ftype(dep, dp->d_ops->sf_get_ftype(sfep));
                memcpy(dep->name, sfep->name, dep->namelen);
-               tagp = xfs_dir3_data_entry_tag_p(mp, dep);
+               tagp = dp->d_ops->data_entry_tag_p(dep);
                *tagp = cpu_to_be16((char *)dep - (char *)hdr);
-               xfs_dir2_data_log_entry(tp, bp, dep);
+               xfs_dir2_data_log_entry(args, bp, dep);
                name.name = sfep->name;
                name.len = sfep->namelen;
                blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->
                                                        hashname(&name));
-               blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
+               blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
                                                 (char *)dep - (char *)hdr));
                offset = (int)((char *)(tagp + 1) - (char *)hdr);
                if (++i == sfp->count)
                        sfep = NULL;
                else
-                       sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
+                       sfep = dp->d_ops->sf_nextentry(sfp, sfep);
        }
        /* Done with the temporary buffer */
        kmem_free(sfp);
@@ -1239,4 +1248,7 @@ xfs_dir2_sf_to_block(
        xfs_dir2_block_log_tail(tp, bp);
        xfs_dir3_data_check(dp, bp);
        return 0;
+out_free:
+       kmem_free(sfp);
+       return error;
 }