]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - repair/phase6.c
libxfs: refactor manage_zones()
[thirdparty/xfsprogs-dev.git] / repair / phase6.c
index e65fc4a0f9434d57891afd889a95e0ef440b1acd..28e633deb2cd4c0534da882f86be2907a2783b8b 100644 (file)
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of 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 "libxfs.h"
@@ -491,7 +479,7 @@ bmap_next_offset(
        xfs_fileoff_t   bno;                    /* current block */
        int             error;                  /* error return value */
        xfs_bmbt_irec_t got;                    /* current extent value */
-       xfs_ifork_t     *ifp;                   /* inode fork pointer */
+       struct xfs_ifork        *ifp;           /* inode fork pointer */
        struct xfs_iext_cursor  icur;
 
        if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
@@ -525,31 +513,30 @@ res_failed(
                do_error(_("xfs_trans_reserve returned %d\n"), err);
 }
 
-void
+static void
 mk_rbmino(xfs_mount_t *mp)
 {
        xfs_trans_t     *tp;
        xfs_inode_t     *ip;
        xfs_bmbt_irec_t *ep;
-       xfs_fsblock_t   first;
        int             i;
        int             nmap;
        int             error;
-       struct xfs_defer_ops    dfops;
        xfs_fileoff_t   bno;
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
        int             vers;
        int             times;
-       struct xfs_trans_res tres = {0};
+       uint            blocks;
 
        /*
         * first set up inode
         */
-       i = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp);
+       i = -libxfs_trans_alloc_rollable(mp, 10, &tp);
        if (i)
                res_failed(i);
 
-       error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, 0, &ip);
+       error = -libxfs_iget(mp, tp, mp->m_sb.sb_rbmino, 0, &ip,
+                       &xfs_default_ifork_ops);
        if (error) {
                do_error(
                _("couldn't iget realtime bitmap inode -- error - %d\n"),
@@ -578,7 +565,7 @@ mk_rbmino(xfs_mount_t *mp)
         * now the ifork
         */
        ip->i_df.if_flags = XFS_IFEXTENTS;
-       ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
+       ip->i_df.if_bytes = 0;
        ip->i_df.if_u1.if_root = NULL;
 
        ip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
@@ -586,28 +573,29 @@ mk_rbmino(xfs_mount_t *mp)
        /*
         * commit changes
         */
+       libxfs_trans_ijoin(tp, ip, 0);
        libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-       libxfs_trans_commit(tp);
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               do_error(_("%s: commit failed, error %d\n"), __func__, error);
 
        /*
         * then allocate blocks for file and fill with zeroes (stolen
         * from mkfs)
         */
-       error = -libxfs_trans_alloc(mp, &tres,
-               mp->m_sb.sb_rbmblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1),
-                                  0, 0, &tp);
+       blocks = mp->m_sb.sb_rbmblocks +
+                       XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
+       error = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
        if (error)
                res_failed(error);
 
        libxfs_trans_ijoin(tp, ip, 0);
        bno = 0;
-       libxfs_defer_init(&dfops, &first);
        while (bno < mp->m_sb.sb_rbmblocks) {
                nmap = XFS_BMAP_MAX_NMAP;
                error = -libxfs_bmapi_write(tp, ip, bno,
                          (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno),
-                         0, &first, mp->m_sb.sb_rbmblocks,
-                         map, &nmap, &dfops);
+                         0, mp->m_sb.sb_rbmblocks, map, &nmap);
                if (error) {
                        do_error(
                        _("couldn't allocate realtime bitmap, error = %d\n"),
@@ -620,15 +608,13 @@ mk_rbmino(xfs_mount_t *mp)
                        bno += ep->br_blockcount;
                }
        }
-       libxfs_defer_ijoin(&dfops, ip);
-       error = -libxfs_defer_finish(&tp, &dfops);
+       error = -libxfs_trans_commit(tp);
        if (error) {
                do_error(
                _("allocation of the realtime bitmap failed, error = %d\n"),
                        error);
        }
-       libxfs_trans_commit(tp);
-       IRELE(ip);
+       libxfs_irele(ip);
 }
 
 static int
@@ -638,35 +624,33 @@ fill_rbmino(xfs_mount_t *mp)
        xfs_trans_t     *tp;
        xfs_inode_t     *ip;
        xfs_rtword_t    *bmp;
-       xfs_fsblock_t   first;
        int             nmap;
        int             error;
        xfs_fileoff_t   bno;
        xfs_bmbt_irec_t map;
-       struct xfs_trans_res tres = {0};
 
        bmp = btmcompute;
        bno = 0;
 
-       error = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp);
+       error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
        if (error)
                res_failed(error);
 
-       error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, 0, &ip);
+       error = -libxfs_iget(mp, tp, mp->m_sb.sb_rbmino, 0, &ip,
+                       &xfs_default_ifork_ops);
        if (error) {
                do_error(
                _("couldn't iget realtime bitmap inode -- error - %d\n"),
                        error);
        }
 
-       first = NULLFSBLOCK;
        while (bno < mp->m_sb.sb_rbmblocks)  {
                /*
                 * fill the file one block at a time
                 */
+               libxfs_trans_ijoin(tp, ip, 0);
                nmap = 1;
-               error = -libxfs_bmapi_write(tp, ip, bno, 1, 0,
-                                       &first, 1, &map, &nmap, NULL);
+               error = -libxfs_bmapi_write(tp, ip, bno, 1, 0, 1, &map, &nmap);
                if (error || nmap != 1) {
                        do_error(
        _("couldn't map realtime bitmap block %" PRIu64 ", error = %d\n"),
@@ -687,7 +671,7 @@ _("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime bitmap inode %
                        return(1);
                }
 
-               memmove(XFS_BUF_PTR(bp), bmp, mp->m_sb.sb_blocksize);
+               memmove(bp->b_addr, bmp, mp->m_sb.sb_blocksize);
 
                libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
 
@@ -695,8 +679,10 @@ _("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime bitmap inode %
                bno++;
        }
 
-       libxfs_trans_commit(tp);
-       IRELE(ip);
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               do_error(_("%s: commit failed, error %d\n"), __func__, error);
+       libxfs_irele(ip);
        return(0);
 }
 
@@ -707,37 +693,35 @@ fill_rsumino(xfs_mount_t *mp)
        xfs_trans_t     *tp;
        xfs_inode_t     *ip;
        xfs_suminfo_t   *smp;
-       xfs_fsblock_t   first;
        int             nmap;
        int             error;
        xfs_fileoff_t   bno;
        xfs_fileoff_t   end_bno;
        xfs_bmbt_irec_t map;
-       struct xfs_trans_res tres = {0};
 
        smp = sumcompute;
        bno = 0;
        end_bno = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
 
-       error = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp);
+       error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
        if (error)
                res_failed(error);
 
-       error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, 0, &ip);
+       error = -libxfs_iget(mp, tp, mp->m_sb.sb_rsumino, 0, &ip,
+                       &xfs_default_ifork_ops);
        if (error) {
                do_error(
                _("couldn't iget realtime summary inode -- error - %d\n"),
                        error);
        }
 
-       first = NULLFSBLOCK;
        while (bno < end_bno)  {
                /*
                 * fill the file one block at a time
                 */
+               libxfs_trans_ijoin(tp, ip, 0);
                nmap = 1;
-               error = -libxfs_bmapi_write(tp, ip, bno, 1, 0,
-                                       &first, 1, &map, &nmap, NULL);
+               error = -libxfs_bmapi_write(tp, ip, bno, 1, 0, 1, &map, &nmap);
                if (error || nmap != 1) {
                        do_error(
        _("couldn't map realtime summary inode block %" PRIu64 ", error = %d\n"),
@@ -755,11 +739,11 @@ fill_rsumino(xfs_mount_t *mp)
                        do_warn(
 _("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime summary inode %" PRIu64 "\n"),
                                bno, map.br_startblock, mp->m_sb.sb_rsumino);
-                       IRELE(ip);
+                       libxfs_irele(ip);
                        return(1);
                }
 
-               memmove(XFS_BUF_PTR(bp), smp, mp->m_sb.sb_blocksize);
+               memmove(bp->b_addr, smp, mp->m_sb.sb_blocksize);
 
                libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
 
@@ -767,8 +751,10 @@ _("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime summary inode
                bno++;
        }
 
-       libxfs_trans_commit(tp);
-       IRELE(ip);
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               do_error(_("%s: commit failed, error %d\n"), __func__, error);
+       libxfs_irele(ip);
        return(0);
 }
 
@@ -778,17 +764,15 @@ mk_rsumino(xfs_mount_t *mp)
        xfs_trans_t     *tp;
        xfs_inode_t     *ip;
        xfs_bmbt_irec_t *ep;
-       xfs_fsblock_t   first;
        int             i;
        int             nmap;
        int             error;
        int             nsumblocks;
-       struct xfs_defer_ops    dfops;
        xfs_fileoff_t   bno;
        xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
        int             vers;
        int             times;
-       struct xfs_trans_res tres = {0};
+       uint            blocks;
 
        /*
         * first set up inode
@@ -797,7 +781,8 @@ mk_rsumino(xfs_mount_t *mp)
        if (i)
                res_failed(i);
 
-       error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, 0, &ip);
+       error = -libxfs_iget(mp, tp, mp->m_sb.sb_rsumino, 0, &ip,
+                       &xfs_default_ifork_ops);
        if (error) {
                do_error(
                _("couldn't iget realtime summary inode -- error - %d\n"),
@@ -826,7 +811,7 @@ mk_rsumino(xfs_mount_t *mp)
         * now the ifork
         */
        ip->i_df.if_flags = XFS_IFEXTENTS;
-       ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
+       ip->i_df.if_bytes = 0;
        ip->i_df.if_u1.if_root = NULL;
 
        ip->i_d.di_size = mp->m_rsumsize;
@@ -834,33 +819,29 @@ mk_rsumino(xfs_mount_t *mp)
        /*
         * commit changes
         */
+       libxfs_trans_ijoin(tp, ip, 0);
        libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-       libxfs_trans_commit(tp);
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               do_error(_("%s: commit failed, error %d\n"), __func__, error);
 
        /*
         * then allocate blocks for file and fill with zeroes (stolen
         * from mkfs)
         */
-       libxfs_defer_init(&dfops, &first);
-
        nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
-       tres.tr_logres = BBTOB(128);
-       tres.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT;
-       tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
-       error = -libxfs_trans_alloc(mp, &tres,
-               mp->m_sb.sb_rbmblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1),
-                                   0, 0, &tp);
+       blocks = nsumblocks + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
+       error = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
        if (error)
                res_failed(error);
 
        libxfs_trans_ijoin(tp, ip, 0);
        bno = 0;
-       libxfs_defer_init(&dfops, &first);
        while (bno < nsumblocks) {
                nmap = XFS_BMAP_MAX_NMAP;
                error = -libxfs_bmapi_write(tp, ip, bno,
                          (xfs_extlen_t)(nsumblocks - bno),
-                         0, &first, nsumblocks, map, &nmap, &dfops);
+                         0, nsumblocks, map, &nmap);
                if (error) {
                        do_error(
                _("couldn't allocate realtime summary inode, error = %d\n"),
@@ -873,15 +854,13 @@ mk_rsumino(xfs_mount_t *mp)
                        bno += ep->br_blockcount;
                }
        }
-       libxfs_defer_ijoin(&dfops, ip);
-       error = -libxfs_defer_finish(&tp, &dfops);
+       error = -libxfs_trans_commit(tp);
        if (error) {
                do_error(
        _("allocation of the realtime summary ino failed, error = %d\n"),
                        error);
        }
-       libxfs_trans_commit(tp);
-       IRELE(ip);
+       libxfs_irele(ip);
 }
 
 /*
@@ -904,7 +883,8 @@ mk_root_dir(xfs_mount_t *mp)
        if (i)
                res_failed(i);
 
-       error = -libxfs_trans_iget(mp, tp, mp->m_sb.sb_rootino, 0, 0, &ip);
+       error = -libxfs_iget(mp, tp, mp->m_sb.sb_rootino, 0, &ip,
+                       &xfs_default_ifork_ops);
        if (error) {
                do_error(_("could not iget root inode -- error - %d\n"), error);
        }
@@ -920,7 +900,7 @@ mk_root_dir(xfs_mount_t *mp)
        ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
        ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
 
-       set_nlink(VFS_I(ip), 1);        /* account for . */
+       set_nlink(VFS_I(ip), 2);        /* account for . and .. */
 
        times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
        if (ip->i_d.di_version == 3) {
@@ -929,26 +909,27 @@ mk_root_dir(xfs_mount_t *mp)
                times |= XFS_ICHGTIME_CREATE;
        }
        libxfs_trans_ichgtime(tp, ip, times);
-
+       libxfs_trans_ijoin(tp, ip, 0);
        libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
        /*
         * now the ifork
         */
        ip->i_df.if_flags = XFS_IFEXTENTS;
-       ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
+       ip->i_df.if_bytes = 0;
        ip->i_df.if_u1.if_root = NULL;
 
-
-
        /*
         * initialize the directory
         */
        ip->d_ops = mp->m_dir_inode_ops;
        libxfs_dir_init(tp, ip, ip);
 
-       libxfs_trans_commit(tp);
-       IRELE(ip);
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               do_error(_("%s: commit failed, error %d\n"), __func__, error);
+
+       libxfs_irele(ip);
 
        irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
                                XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
@@ -966,12 +947,10 @@ mk_orphanage(xfs_mount_t *mp)
        xfs_trans_t     *tp;
        xfs_inode_t     *ip;
        xfs_inode_t     *pip;
-       xfs_fsblock_t   first;
        ino_tree_node_t *irec;
        int             ino_offset = 0;
        int             i;
        int             error;
-       struct xfs_defer_ops    dfops;
        const int       mode = 0755;
        int             nres;
        struct xfs_name xname;
@@ -998,7 +977,6 @@ mk_orphanage(xfs_mount_t *mp)
        /*
         * could not be found, create it
         */
-       libxfs_defer_init(&dfops, &first);
        nres = XFS_MKDIR_SPACE_RES(mp, xname.len);
        i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp);
        if (i)
@@ -1050,6 +1028,7 @@ mk_orphanage(xfs_mount_t *mp)
         */
        set_inode_used(irec, ino_offset);
        add_inode_ref(irec, ino_offset);
+       add_inode_reached(irec, ino_offset);
 
        /*
         * now that we know the transaction will stay around,
@@ -1060,8 +1039,7 @@ mk_orphanage(xfs_mount_t *mp)
        /*
         * create the actual entry
         */
-       error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first,
-                                       &dfops, nres);
+       error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, nres);
        if (error)
                do_error(
                _("can't make %s, createname error %d\n"),
@@ -1069,31 +1047,25 @@ mk_orphanage(xfs_mount_t *mp)
 
        /*
         * bump up the link count in the root directory to account
-        * for .. in the new directory
+        * for .. in the new directory, and update the irec copy of the
+        * on-disk nlink so we don't fail the link count check later.
         */
        inc_nlink(VFS_I(pip));
-       add_inode_ref(find_inode_rec(mp,
-                               XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
-                               XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)), 0);
-
-
+       irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
+                                 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
+       add_inode_ref(irec, 0);
+       set_inode_disk_nlinks(irec, 0, get_inode_disk_nlinks(irec, 0) + 1);
 
        libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
        libxfs_dir_init(tp, ip, pip);
        libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
-       libxfs_defer_ijoin(&dfops, ip);
-       error = -libxfs_defer_finish(&tp, &dfops);
+       error = -libxfs_trans_commit(tp);
        if (error) {
                do_error(_("%s directory creation failed -- bmapf error %d\n"),
                        ORPHANAGE, error);
        }
-
-
-       libxfs_trans_commit(tp);
-       IRELE(ip);
-       IRELE(pip);
-       add_inode_reached(irec,ino_offset);
+       libxfs_irele(ip);
+       libxfs_irele(pip);
 
        return(ino);
 }
@@ -1111,8 +1083,6 @@ mv_orphanage(
        xfs_ino_t               entry_ino_num;
        xfs_inode_t             *ino_p;
        xfs_trans_t             *tp;
-       xfs_fsblock_t           first;
-       struct xfs_defer_ops            dfops;
        int                     err;
        unsigned char           fname[MAXPATHLEN + 1];
        int                     nres;
@@ -1168,9 +1138,8 @@ mv_orphanage(
                        libxfs_trans_ijoin(tp, orphanage_ip, 0);
                        libxfs_trans_ijoin(tp, ino_p, 0);
 
-                       libxfs_defer_init(&dfops, &first);
                        err = -libxfs_dir_createname(tp, orphanage_ip, &xname,
-                                               ino, &first, &dfops, nres);
+                                               ino, nres);
                        if (err)
                                do_error(
        _("name create failed in %s (%d), filesystem may be out of space\n"),
@@ -1183,7 +1152,7 @@ mv_orphanage(
                        libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
 
                        err = -libxfs_dir_createname(tp, ino_p, &xfs_name_dotdot,
-                                       orphanage_ino, &first, &dfops, nres);
+                                       orphanage_ino, nres);
                        if (err)
                                do_error(
        _("creation of .. entry failed (%d), filesystem may be out of space\n"),
@@ -1191,15 +1160,10 @@ mv_orphanage(
 
                        inc_nlink(VFS_I(ino_p));
                        libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
-
-                       libxfs_defer_ijoin(&dfops, ino_p);
-                       err = -libxfs_defer_finish(&tp, &dfops);
+                       err = -libxfs_trans_commit(tp);
                        if (err)
                                do_error(
-       _("bmap finish failed (err - %d), filesystem may be out of space\n"),
-                                       err);
-
-                       libxfs_trans_commit(tp);
+       _("creation of .. entry failed (%d)\n"), err);
                } else  {
                        err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_rename,
                                                  nres, 0, 0, &tp);
@@ -1211,10 +1175,9 @@ mv_orphanage(
                        libxfs_trans_ijoin(tp, orphanage_ip, 0);
                        libxfs_trans_ijoin(tp, ino_p, 0);
 
-                       libxfs_defer_init(&dfops, &first);
 
                        err = -libxfs_dir_createname(tp, orphanage_ip, &xname,
-                                               ino, &first, &dfops, nres);
+                                               ino, nres);
                        if (err)
                                do_error(
        _("name create failed in %s (%d), filesystem may be out of space\n"),
@@ -1233,21 +1196,17 @@ mv_orphanage(
                        if (entry_ino_num != orphanage_ino)  {
                                err = -libxfs_dir_replace(tp, ino_p,
                                                &xfs_name_dotdot, orphanage_ino,
-                                               &first, &dfops, nres);
+                                               nres);
                                if (err)
                                        do_error(
        _("name replace op failed (%d), filesystem may be out of space\n"),
                                                err);
                        }
 
-                       libxfs_defer_ijoin(&dfops, ino_p);
-                       err = -libxfs_defer_finish(&tp, &dfops);
+                       err = -libxfs_trans_commit(tp);
                        if (err)
                                do_error(
-       _("bmap finish failed (%d), filesystem may be out of space\n"),
-                                       err);
-
-                       libxfs_trans_commit(tp);
+       _("orphanage name replace op failed (%d)\n"), err);
                }
 
        } else  {
@@ -1268,9 +1227,8 @@ mv_orphanage(
                libxfs_trans_ijoin(tp, orphanage_ip, 0);
                libxfs_trans_ijoin(tp, ino_p, 0);
 
-               libxfs_defer_init(&dfops, &first);
                err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino,
-                                               &first, &dfops, nres);
+                                               nres);
                if (err)
                        do_error(
        _("name create failed in %s (%d), filesystem may be out of space\n"),
@@ -1279,18 +1237,13 @@ mv_orphanage(
 
                set_nlink(VFS_I(ino_p), 1);
                libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
-
-               libxfs_defer_ijoin(&dfops, ino_p);
-               err = -libxfs_defer_finish(&tp, &dfops);
+               err = -libxfs_trans_commit(tp);
                if (err)
                        do_error(
-       _("bmap finish failed (%d), filesystem may be out of space\n"),
-                               err);
-
-               libxfs_trans_commit(tp);
+       _("orphanage name create failed (%d)\n"), err);
        }
-       IRELE(ino_p);
-       IRELE(orphanage_ip);
+       libxfs_irele(ino_p);
+       libxfs_irele(orphanage_ip);
 }
 
 static int
@@ -1371,11 +1324,9 @@ longform_dir2_rebuild(
        int                     nres;
        xfs_trans_t             *tp;
        xfs_fileoff_t           lastblock;
-       xfs_fsblock_t           firstblock;
-       struct xfs_defer_ops            dfops;
        xfs_inode_t             pip;
        dir_hash_ent_t          *p;
-       int                     done;
+       int                     done = 0;
 
        /*
         * trash directory completely and rebuild from scratch using the
@@ -1395,8 +1346,6 @@ longform_dir2_rebuild(
            libxfs_dir_ino_validate(mp, pip.i_ino))
                pip.i_ino = mp->m_sb.sb_rootino;
 
-       libxfs_defer_init(&dfops, &firstblock);
-
        nres = XFS_REMOVE_SPACE_RES(mp);
        error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp);
        if (error)
@@ -1412,14 +1361,25 @@ longform_dir2_rebuild(
                        error);
 
        /* free all data, leaf, node and freespace blocks */
-       error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA, 0,
-                               &firstblock, &dfops, &done);
-       if (error) {
-               do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);
-               goto out_bmap_cancel;
-       }
-
-       ASSERT(done);
+       while (!done) {
+              error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA,
+                                      0, &done);
+              if (error) {
+                      do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);
+                      goto out_bmap_cancel;
+              }
+              error = -libxfs_defer_finish(&tp);
+              if (error) {
+                      do_warn(("defer_finish failed -- error - %d\n"), error);
+                      goto out_bmap_cancel;
+              }
+              /*
+               * Close out trans and start the next one in the chain.
+               */
+              error = -libxfs_trans_roll_inode(&tp, ip);
+              if (error)
+                       goto out_bmap_cancel;
+        }
 
        error = -libxfs_dir_init(tp, ip, &pip);
        if (error) {
@@ -1427,10 +1387,10 @@ longform_dir2_rebuild(
                goto out_bmap_cancel;
        }
 
-       libxfs_defer_ijoin(&dfops, ip);
-       error = -libxfs_defer_finish(&tp, &dfops);
-
-       libxfs_trans_commit(tp);
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               do_error(
+       _("dir init failed (%d)\n"), error);
 
        if (ino == mp->m_sb.sb_rootino)
                need_root_dotdot = 0;
@@ -1452,9 +1412,8 @@ longform_dir2_rebuild(
 
                libxfs_trans_ijoin(tp, ip, 0);
 
-               libxfs_defer_init(&dfops, &firstblock);
                error = -libxfs_dir_createname(tp, ip, &p->name, p->inum,
-                                               &firstblock, &dfops, nres);
+                                               nres);
                if (error) {
                        do_warn(
 _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n"),
@@ -1462,22 +1421,15 @@ _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n"
                        goto out_bmap_cancel;
                }
 
-               libxfs_defer_ijoin(&dfops, ip);
-               error = -libxfs_defer_finish(&tp, &dfops);
-               if (error) {
-                       do_warn(
-       _("bmap finish failed (%d), filesystem may be out of space\n"),
-                               error);
-                       goto out_bmap_cancel;
-               }
-
-               libxfs_trans_commit(tp);
+               error = -libxfs_trans_commit(tp);
+               if (error)
+                       do_error(
+_("name create failed (%d) during rebuild\n"), error);
        }
 
        return;
 
 out_bmap_cancel:
-       libxfs_defer_cancel(&dfops);
        libxfs_trans_cancel(tp);
        return;
 }
@@ -1496,8 +1448,6 @@ dir2_kill_block(
 {
        xfs_da_args_t   args;
        int             error;
-       xfs_fsblock_t   firstblock;
-       struct xfs_defer_ops    dfops;
        int             nres;
        xfs_trans_t     *tp;
 
@@ -1508,11 +1458,8 @@ dir2_kill_block(
        libxfs_trans_ijoin(tp, ip, 0);
        libxfs_trans_bjoin(tp, bp);
        memset(&args, 0, sizeof(args));
-       libxfs_defer_init(&dfops, &firstblock);
        args.dp = ip;
        args.trans = tp;
-       args.firstblock = &firstblock;
-       args.dfops = &dfops;
        args.whichfork = XFS_DATA_FORK;
        args.geo = mp->m_dir_geo;
        if (da_bno >= mp->m_dir_geo->leafblk && da_bno < mp->m_dir_geo->freeblk)
@@ -1523,9 +1470,10 @@ dir2_kill_block(
        if (error)
                do_error(_("shrink_inode failed inode %" PRIu64 " block %u\n"),
                        ip->i_ino, da_bno);
-       libxfs_defer_ijoin(&dfops, ip);
-       libxfs_defer_finish(&tp, &dfops);
-       libxfs_trans_commit(tp);
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               do_error(
+_("directory shrink failed (%d)\n"), error);
 }
 
 /*
@@ -1557,8 +1505,6 @@ longform_dir2_entry_check_data(
        struct xfs_dir2_data_free *bf;
        char                    *endptr;
        int                     error;
-       xfs_fsblock_t           firstblock;
-       struct xfs_defer_ops            dfops;
        char                    fname[MAXNAMELEN + 1];
        freetab_t               *freetab;
        int                     i;
@@ -1700,7 +1646,6 @@ longform_dir2_entry_check_data(
        libxfs_trans_ijoin(tp, ip, 0);
        libxfs_trans_bjoin(tp, bp);
        libxfs_trans_bhold(tp, bp);
-       libxfs_defer_init(&dfops, &firstblock);
        if (be32_to_cpu(d->magic) != wantmagic) {
                do_warn(
        _("bad directory block magic # %#x for directory inode %" PRIu64 " block %d: "),
@@ -2001,9 +1946,10 @@ _("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 "
                                d, &i);
        if (needlog)
                libxfs_dir2_data_log_header(&da, bp);
-       libxfs_defer_ijoin(&dfops, ip);
-       libxfs_defer_finish(&tp, &dfops);
-       libxfs_trans_commit(tp);
+       error = -libxfs_trans_commit(tp);
+       if (error)
+               do_error(
+_("directory block fixing failed (%d)\n"), error);
 
        /* record the largest free space in the freetab for later checking */
        bf = M_DIROPS(mp)->data_bestfree_p(d);
@@ -2409,6 +2355,8 @@ longform_dir2_entry_check(xfs_mount_t     *mp,
 
                db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);
                if (db >= num_bps) {
+                       int last_size = num_bps;
+
                        /* more data blocks than expected */
                        num_bps = db + 1;
                        bplist = realloc(bplist, num_bps * sizeof(struct xfs_buf*));
@@ -2416,6 +2364,9 @@ longform_dir2_entry_check(xfs_mount_t     *mp,
                                do_error(_("realloc failed in %s (%zu bytes)\n"),
                                        __func__,
                                        num_bps * sizeof(struct xfs_buf*));
+                       /* Initialize the new elements */
+                       for (i = last_size; i < num_bps; i++)
+                               bplist[i] = NULL;
                }
 
                if (isblock)
@@ -2918,8 +2869,6 @@ process_dir_inode(
        int                     ino_offset)
 {
        xfs_ino_t               ino;
-       struct xfs_defer_ops            dfops;
-       xfs_fsblock_t           first;
        xfs_inode_t             *ip;
        xfs_trans_t             *tp;
        dir_hash_tab_t          *hashtab;
@@ -3021,7 +2970,9 @@ process_dir_inode(
                        if (dirty)  {
                                libxfs_trans_log_inode(tp, ip,
                                        XFS_ILOG_CORE | XFS_ILOG_DDATA);
-                               libxfs_trans_commit(tp);
+                               error = -libxfs_trans_commit(tp);
+                               if (error)
+                                       res_failed(error);
                        } else  {
                                libxfs_trans_cancel(tp);
                        }
@@ -3055,20 +3006,17 @@ process_dir_inode(
 
                libxfs_trans_ijoin(tp, ip, 0);
 
-               libxfs_defer_init(&dfops, &first);
-
                error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot,
-                                       ip->i_ino, &first, &dfops, nres);
+                                       ip->i_ino, nres);
                if (error)
                        do_error(
        _("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error);
 
                libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
-               libxfs_defer_ijoin(&dfops, ip);
-               error = -libxfs_defer_finish(&tp, &dfops);
-               ASSERT(error == 0);
-               libxfs_trans_commit(tp);
+               error = -libxfs_trans_commit(tp);
+               if (error)
+                       do_error(
+       _("root inode \"..\" entry recreation failed (%d)\n"), error);
 
                need_root_dotdot = 0;
        } else if (need_root_dotdot && ino == mp->m_sb.sb_rootino)  {
@@ -3113,24 +3061,21 @@ process_dir_inode(
 
                        libxfs_trans_ijoin(tp, ip, 0);
 
-                       libxfs_defer_init(&dfops, &first);
-
                        error = -libxfs_dir_createname(tp, ip, &xfs_name_dot,
-                                       ip->i_ino, &first, &dfops, nres);
+                                       ip->i_ino, nres);
                        if (error)
                                do_error(
        _("can't make \".\" entry in dir ino %" PRIu64 ", createname error %d\n"),
                                        ino, error);
 
                        libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
-                       libxfs_defer_ijoin(&dfops, ip);
-                       error = -libxfs_defer_finish(&tp, &dfops);
-                       ASSERT(error == 0);
-                       libxfs_trans_commit(tp);
+                       error = -libxfs_trans_commit(tp);
+                       if (error)
+                               do_error(
+       _("root inode \".\" entry recreation failed (%d)\n"), error);
                }
        }
-       IRELE(ip);
+       libxfs_irele(ip);
 }
 
 /*