]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - libxfs/xfs_bmap.c
xfs: use iomap_valid method to detect stale cached iomaps
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_bmap.c
index 1412398b7759c60a37f389d65c76f358ded89b30..3b1739bdb0ff6d888d3eddd67d8add17e08f3b07 100644 (file)
 #include "xfs_alloc.h"
 #include "xfs_bmap.h"
 #include "xfs_bmap_btree.h"
+#include "xfs_errortag.h"
 #include "xfs_trans_space.h"
 #include "xfs_trace.h"
 #include "xfs_attr_leaf.h"
 #include "xfs_quota_defs.h"
 #include "xfs_rmap.h"
+#include "xfs_ag.h"
 #include "xfs_ag_resv.h"
 #include "xfs_refcount.h"
 
-
-kmem_zone_t            *xfs_bmap_free_item_zone;
+struct kmem_cache              *xfs_bmap_intent_cache;
 
 /*
  * Miscellaneous helper functions
@@ -44,46 +45,54 @@ xfs_bmap_compute_maxlevels(
        xfs_mount_t     *mp,            /* file system mount structure */
        int             whichfork)      /* data or attr fork */
 {
+       uint64_t        maxblocks;      /* max blocks at this level */
+       xfs_extnum_t    maxleafents;    /* max leaf entries possible */
        int             level;          /* btree level */
-       uint            maxblocks;      /* max blocks at this level */
-       uint            maxleafents;    /* max leaf entries possible */
        int             maxrootrecs;    /* max records in root block */
        int             minleafrecs;    /* min records in leaf block */
        int             minnoderecs;    /* min records in node block */
        int             sz;             /* root block size */
 
        /*
-        * The maximum number of extents in a file, hence the maximum
-        * number of leaf entries, is controlled by the type of di_nextents
-        * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
-        * (a signed 16-bit number, xfs_aextnum_t).
+        * The maximum number of extents in a fork, hence the maximum number of
+        * leaf entries, is controlled by the size of the on-disk extent count.
         *
-        * Note that we can no longer assume that if we are in ATTR1 that
-        * the fork offset of all the inodes will be
-        * (xfs_default_attroffset(ip) >> 3) because we could have mounted
-        * with ATTR2 and then mounted back with ATTR1, keeping the
-        * di_forkoff's fixed but probably at various positions. Therefore,
-        * for both ATTR1 and ATTR2 we have to assume the worst case scenario
-        * of a minimum size available.
+        * Note that we can no longer assume that if we are in ATTR1 that the
+        * fork offset of all the inodes will be
+        * (xfs_default_attroffset(ip) >> 3) because we could have mounted with
+        * ATTR2 and then mounted back with ATTR1, keeping the i_forkoff's fixed
+        * but probably at various positions. Therefore, for both ATTR1 and
+        * ATTR2 we have to assume the worst case scenario of a minimum size
+        * available.
         */
-       if (whichfork == XFS_DATA_FORK) {
-               maxleafents = MAXEXTNUM;
+       maxleafents = xfs_iext_max_nextents(xfs_has_large_extent_counts(mp),
+                               whichfork);
+       if (whichfork == XFS_DATA_FORK)
                sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
-       } else {
-               maxleafents = MAXAEXTNUM;
+       else
                sz = XFS_BMDR_SPACE_CALC(MINABTPTRS);
-       }
+
        maxrootrecs = xfs_bmdr_maxrecs(sz, 0);
        minleafrecs = mp->m_bmap_dmnr[0];
        minnoderecs = mp->m_bmap_dmnr[1];
-       maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
+       maxblocks = howmany_64(maxleafents, minleafrecs);
        for (level = 1; maxblocks > 1; level++) {
                if (maxblocks <= maxrootrecs)
                        maxblocks = 1;
                else
-                       maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
+                       maxblocks = howmany_64(maxblocks, minnoderecs);
        }
        mp->m_bm_maxlevels[whichfork] = level;
+       ASSERT(mp->m_bm_maxlevels[whichfork] <= xfs_bmbt_maxlevels_ondisk());
+}
+
+unsigned int
+xfs_bmap_compute_attr_offset(
+       struct xfs_mount        *mp)
+{
+       if (mp->m_sb.sb_inodesize == 256)
+               return XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
+       return XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
 }
 
 STATIC int                             /* error */
@@ -112,10 +121,11 @@ xfs_bmbt_lookup_first(
  */
 static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
 {
+       struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
+
        return whichfork != XFS_COW_FORK &&
-               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
-               XFS_IFORK_NEXTENTS(ip, whichfork) >
-                       XFS_IFORK_MAXEXT(ip, whichfork);
+               ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
+               ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork);
 }
 
 /*
@@ -123,10 +133,11 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork)
  */
 static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork)
 {
+       struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
+
        return whichfork != XFS_COW_FORK &&
-               XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
-               XFS_IFORK_NEXTENTS(ip, whichfork) <=
-                       XFS_IFORK_MAXEXT(ip, whichfork);
+               ifp->if_format == XFS_DINODE_FMT_BTREE &&
+               ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork);
 }
 
 /*
@@ -182,24 +193,15 @@ uint
 xfs_default_attroffset(
        struct xfs_inode        *ip)
 {
-       struct xfs_mount        *mp = ip->i_mount;
-       uint                    offset;
-
-       if (mp->m_sb.sb_inodesize == 256) {
-               offset = XFS_LITINO(mp, ip->i_d.di_version) -
-                               XFS_BMDR_SPACE_CALC(MINABTPTRS);
-       } else {
-               offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
-       }
-
-       ASSERT(offset < XFS_LITINO(mp, ip->i_d.di_version));
-       return offset;
+       if (ip->i_df.if_format == XFS_DINODE_FMT_DEV)
+               return roundup(sizeof(xfs_dev_t), 8);
+       return M_IGEO(ip->i_mount)->attr_fork_offset;
 }
 
 /*
- * Helper routine to reset inode di_forkoff field when switching
- * attribute fork from local to extent format - we reset it where
- * possible to make space available for inline data fork extents.
+ * Helper routine to reset inode i_forkoff field when switching attribute fork
+ * from local to extent format - we reset it where possible to make space
+ * available for inline data fork extents.
  */
 STATIC void
 xfs_bmap_forkoff_reset(
@@ -207,12 +209,12 @@ xfs_bmap_forkoff_reset(
        int             whichfork)
 {
        if (whichfork == XFS_ATTR_FORK &&
-           ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
-           ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
+           ip->i_df.if_format != XFS_DINODE_FMT_DEV &&
+           ip->i_df.if_format != XFS_DINODE_FMT_BTREE) {
                uint    dfl_forkoff = xfs_default_attroffset(ip) >> 3;
 
-               if (dfl_forkoff > ip->i_d.di_forkoff)
-                       ip->i_d.di_forkoff = dfl_forkoff;
+               if (dfl_forkoff > ip->i_forkoff)
+                       ip->i_forkoff = dfl_forkoff;
        }
 }
 
@@ -228,11 +230,11 @@ xfs_bmap_get_bp(
        if (!cur)
                return NULL;
 
-       for (i = 0; i < XFS_BTREE_MAXLEVELS; i++) {
-               if (!cur->bc_bufs[i])
+       for (i = 0; i < cur->bc_maxlevels; i++) {
+               if (!cur->bc_levels[i].bp)
                        break;
-               if (XFS_BUF_ADDR(cur->bc_bufs[i]) == bno)
-                       return cur->bc_bufs[i];
+               if (xfs_buf_daddr(cur->bc_levels[i].bp) == bno)
+                       return cur->bc_levels[i].bp;
        }
 
        /* Chase down all the log items to see if the bp is there */
@@ -240,7 +242,7 @@ xfs_bmap_get_bp(
                struct xfs_buf_log_item *bip = (struct xfs_buf_log_item *)lip;
 
                if (bip->bli_item.li_type == XFS_LI_BUF &&
-                   XFS_BUF_ADDR(bip->bli_buf) == bno)
+                   xfs_buf_daddr(bip->bli_buf) == bno)
                        return bip->bli_buf;
        }
 
@@ -285,7 +287,7 @@ xfs_check_block(
                        else
                                thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr);
                        if (*thispa == *pp) {
-                               xfs_warn(mp, "%s: thispa(%d) == pp(%d) %Ld",
+                               xfs_warn(mp, "%s: thispa(%d) == pp(%d) %lld",
                                        __func__, j, i,
                                        (unsigned long long)be64_to_cpu(*thispa));
                                xfs_err(mp, "%s: ptrs are equal in node\n",
@@ -305,35 +307,32 @@ xfs_check_block(
  */
 STATIC void
 xfs_bmap_check_leaf_extents(
-       xfs_btree_cur_t         *cur,   /* btree cursor or null */
+       struct xfs_btree_cur    *cur,   /* btree cursor or null */
        xfs_inode_t             *ip,            /* incore inode pointer */
        int                     whichfork)      /* data or attr fork */
 {
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_btree_block  *block; /* current btree block */
        xfs_fsblock_t           bno;    /* block # of "block" */
-       xfs_buf_t               *bp;    /* buffer for "block" */
+       struct xfs_buf          *bp;    /* buffer for "block" */
        int                     error;  /* error return value */
        xfs_extnum_t            i=0, j; /* index into the extents list */
-       struct xfs_ifork        *ifp;   /* fork structure */
        int                     level;  /* btree level, for checking */
-       xfs_mount_t             *mp;    /* file system mount structure */
        __be64                  *pp;    /* pointer to block address */
        xfs_bmbt_rec_t          *ep;    /* pointer to current extent */
        xfs_bmbt_rec_t          last = {0, 0}; /* last extent in prev block */
        xfs_bmbt_rec_t          *nextp; /* pointer to next extent */
        int                     bp_release = 0;
 
-       if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
+       if (ifp->if_format != XFS_DINODE_FMT_BTREE)
                return;
-       }
 
        /* skip large extent count inodes */
-       if (ip->i_d.di_nextents > 10000)
+       if (ip->i_df.if_nextents > 10000)
                return;
 
        bno = NULLFSBLOCK;
-       mp = ip->i_mount;
-       ifp = XFS_IFORK_PTR(ip, whichfork);
        block = ifp->if_broot;
        /*
         * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
@@ -376,8 +375,10 @@ xfs_bmap_check_leaf_extents(
                xfs_check_block(block, mp, 0, 0);
                pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
                bno = be64_to_cpu(*pp);
-               XFS_WANT_CORRUPTED_GOTO(mp,
-                                       xfs_verify_fsbno(mp, bno), error0);
+               if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbno(mp, bno))) {
+                       error = -EFSCORRUPTED;
+                       goto error0;
+               }
                if (bp_release) {
                        bp_release = 0;
                        xfs_trans_brelse(NULL, bp);
@@ -458,7 +459,7 @@ error0:
        if (bp_release)
                xfs_trans_brelse(NULL, bp);
 error_norelse:
-       xfs_warn(mp, "%s: BAD after btree leaves for %d extents",
+       xfs_warn(mp, "%s: BAD after btree leaves for %llu extents",
                __func__, i);
        xfs_err(mp, "%s: CORRUPTED BTREE OR SOMETHING", __func__);
        xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
@@ -475,7 +476,7 @@ STATIC void
 xfs_bmap_validate_ret(
        xfs_fileoff_t           bno,
        xfs_filblks_t           len,
-       int                     flags,
+       uint32_t                flags,
        xfs_bmbt_irec_t         *mval,
        int                     nmap,
        int                     ret_nmap)
@@ -511,55 +512,6 @@ xfs_bmap_validate_ret(
 #define        xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)    do { } while (0)
 #endif /* DEBUG */
 
-/*
- * bmap free list manipulation functions
- */
-
-/*
- * Add the extent to the list of extents to be free at transaction end.
- * The list is maintained sorted (by block number).
- */
-void
-__xfs_bmap_add_free(
-       struct xfs_trans                *tp,
-       xfs_fsblock_t                   bno,
-       xfs_filblks_t                   len,
-       const struct xfs_owner_info     *oinfo,
-       bool                            skip_discard)
-{
-       struct xfs_extent_free_item     *new;           /* new element */
-#ifdef DEBUG
-       struct xfs_mount                *mp = tp->t_mountp;
-       xfs_agnumber_t                  agno;
-       xfs_agblock_t                   agbno;
-
-       ASSERT(bno != NULLFSBLOCK);
-       ASSERT(len > 0);
-       ASSERT(len <= MAXEXTLEN);
-       ASSERT(!isnullstartblock(bno));
-       agno = XFS_FSB_TO_AGNO(mp, bno);
-       agbno = XFS_FSB_TO_AGBNO(mp, bno);
-       ASSERT(agno < mp->m_sb.sb_agcount);
-       ASSERT(agbno < mp->m_sb.sb_agblocks);
-       ASSERT(len < mp->m_sb.sb_agblocks);
-       ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
-#endif
-       ASSERT(xfs_bmap_free_item_zone != NULL);
-
-       new = kmem_zone_alloc(xfs_bmap_free_item_zone, 0);
-       new->xefi_startblock = bno;
-       new->xefi_blockcount = (xfs_extlen_t)len;
-       if (oinfo)
-               new->xefi_oinfo = *oinfo;
-       else
-               new->xefi_oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
-       new->xefi_skip_discard = skip_discard;
-       trace_xfs_bmap_free_defer(tp->t_mountp,
-                       XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
-                       XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len);
-       xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
-}
-
 /*
  * Inode fork format manipulation functions
  */
@@ -579,12 +531,12 @@ xfs_bmap_btree_to_extents(
        int                     *logflagsp, /* inode logging flags */
        int                     whichfork)  /* data or attr fork */
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_btree_block  *rblock = ifp->if_broot;
        struct xfs_btree_block  *cblock;/* child btree block */
        xfs_fsblock_t           cbno;   /* child block number */
-       xfs_buf_t               *cbp;   /* child block's buffer */
+       struct xfs_buf          *cbp;   /* child block's buffer */
        int                     error;  /* error return value */
        __be64                  *pp;    /* ptr to block address */
        struct xfs_owner_info   oinfo;
@@ -595,8 +547,7 @@ xfs_bmap_btree_to_extents(
 
        ASSERT(cur);
        ASSERT(whichfork != XFS_COW_FORK);
-       ASSERT(ifp->if_flags & XFS_IFEXTENTS);
-       ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
+       ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
        ASSERT(be16_to_cpu(rblock->bb_level) == 1);
        ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
        ASSERT(xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0) == 1);
@@ -604,8 +555,8 @@ xfs_bmap_btree_to_extents(
        pp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, ifp->if_broot_bytes);
        cbno = be64_to_cpu(*pp);
 #ifdef DEBUG
-       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
-                       xfs_btree_check_lptr(cur, cbno, 1));
+       if (XFS_IS_CORRUPT(cur->bc_mp, !xfs_btree_check_lptr(cur, cbno, 1)))
+               return -EFSCORRUPTED;
 #endif
        error = xfs_btree_read_bufl(mp, tp, cbno, &cbp, XFS_BMAP_BTREE_REF,
                                &xfs_bmbt_buf_ops);
@@ -615,16 +566,15 @@ xfs_bmap_btree_to_extents(
        if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
                return error;
        xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
-       xfs_bmap_add_free(cur->bc_tp, cbno, 1, &oinfo);
-       ip->i_d.di_nblocks--;
+       xfs_free_extent_later(cur->bc_tp, cbno, 1, &oinfo);
+       ip->i_nblocks--;
        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
        xfs_trans_binval(tp, cbp);
-       if (cur->bc_bufs[0] == cbp)
-               cur->bc_bufs[0] = NULL;
+       if (cur->bc_levels[0].bp == cbp)
+               cur->bc_levels[0].bp = NULL;
        xfs_iroot_realloc(ip, -1, whichfork);
        ASSERT(ifp->if_broot == NULL);
-       ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
-       XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
+       ifp->if_format = XFS_DINODE_FMT_EXTENTS;
        *logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
        return 0;
 }
@@ -659,15 +609,14 @@ xfs_bmap_extents_to_btree(
 
        mp = ip->i_mount;
        ASSERT(whichfork != XFS_COW_FORK);
-       ifp = XFS_IFORK_PTR(ip, whichfork);
-       ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
+       ifp = xfs_ifork_ptr(ip, whichfork);
+       ASSERT(ifp->if_format == XFS_DINODE_FMT_EXTENTS);
 
        /*
         * Make space in the inode incore. This needs to be undone if we fail
         * to expand the root.
         */
        xfs_iroot_realloc(ip, 1, whichfork);
-       ifp->if_flags |= XFS_IFBROOT;
 
        /*
         * Fill in the root.
@@ -680,11 +629,11 @@ xfs_bmap_extents_to_btree(
         * Need a cursor.  Can't allocate until bb_level is filled in.
         */
        cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
-       cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
+       cur->bc_ino.flags = wasdel ? XFS_BTCUR_BMBT_WASDEL : 0;
        /*
         * Convert to a btree with two levels, one record in root.
         */
-       XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
+       ifp->if_format = XFS_DINODE_FMT_BTREE;
        memset(&args, 0, sizeof(args));
        args.tp = tp;
        args.mp = mp;
@@ -717,21 +666,21 @@ xfs_bmap_extents_to_btree(
        ASSERT(tp->t_firstblock == NULLFSBLOCK ||
               args.agno >= XFS_FSB_TO_AGNO(mp, tp->t_firstblock));
        tp->t_firstblock = args.fsbno;
-       cur->bc_private.b.allocated++;
-       ip->i_d.di_nblocks++;
+       cur->bc_ino.allocated++;
+       ip->i_nblocks++;
        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
-       abp = xfs_btree_get_bufl(mp, tp, args.fsbno);
-       if (!abp) {
-               error = -EFSCORRUPTED;
+       error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
+                       XFS_FSB_TO_DADDR(mp, args.fsbno),
+                       mp->m_bsize, 0, &abp);
+       if (error)
                goto out_unreserve_dquot;
-       }
 
        /*
         * Fill in the child block.
         */
        abp->b_ops = &xfs_bmbt_buf_ops;
        ablock = XFS_BUF_TO_BLOCK(abp);
-       xfs_btree_init_block_int(mp, ablock, abp->b_bn,
+       xfs_btree_init_block_int(mp, ablock, xfs_buf_daddr(abp),
                                XFS_BTNUM_BMAP, 0, 0, ip->i_ino,
                                XFS_BTREE_LONG_PTRS);
 
@@ -742,7 +691,7 @@ xfs_bmap_extents_to_btree(
                xfs_bmbt_disk_set_all(arp, &rec);
                cnt++;
        }
-       ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork));
+       ASSERT(cnt == ifp->if_nextents);
        xfs_btree_set_numrecs(ablock, cnt);
 
        /*
@@ -770,7 +719,7 @@ out_unreserve_dquot:
        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
 out_root_realloc:
        xfs_iroot_realloc(ip, -1, whichfork);
-       XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
+       ifp->if_format = XFS_DINODE_FMT_EXTENTS;
        ASSERT(ifp->if_broot == NULL);
        xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
 
@@ -789,19 +738,17 @@ xfs_bmap_local_to_extents_empty(
        struct xfs_inode        *ip,
        int                     whichfork)
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
 
        ASSERT(whichfork != XFS_COW_FORK);
-       ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
+       ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
        ASSERT(ifp->if_bytes == 0);
-       ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
+       ASSERT(ifp->if_nextents == 0);
 
        xfs_bmap_forkoff_reset(ip, whichfork);
-       ifp->if_flags &= ~XFS_IFINLINE;
-       ifp->if_flags |= XFS_IFEXTENTS;
        ifp->if_u1.if_root = NULL;
        ifp->if_height = 0;
-       XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
+       ifp->if_format = XFS_DINODE_FMT_EXTENTS;
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 }
 
@@ -822,7 +769,7 @@ xfs_bmap_local_to_extents(
        int             flags;          /* logging flags returned */
        struct xfs_ifork *ifp;          /* inode fork pointer */
        xfs_alloc_arg_t args;           /* allocation arguments */
-       xfs_buf_t       *bp;            /* buffer for extent block */
+       struct xfs_buf  *bp;            /* buffer for extent block */
        struct xfs_bmbt_irec rec;
        struct xfs_iext_cursor icur;
 
@@ -831,8 +778,8 @@ xfs_bmap_local_to_extents(
         * So sending the data fork of a regular inode is invalid.
         */
        ASSERT(!(S_ISREG(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK));
-       ifp = XFS_IFORK_PTR(ip, whichfork);
-       ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
+       ifp = xfs_ifork_ptr(ip, whichfork);
+       ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
 
        if (!ifp->if_bytes) {
                xfs_bmap_local_to_extents_empty(tp, ip, whichfork);
@@ -842,7 +789,6 @@ xfs_bmap_local_to_extents(
 
        flags = 0;
        error = 0;
-       ASSERT((ifp->if_flags & (XFS_IFINLINE|XFS_IFEXTENTS)) == XFS_IFINLINE);
        memset(&args, 0, sizeof(args));
        args.tp = tp;
        args.mp = ip->i_mount;
@@ -868,7 +814,11 @@ xfs_bmap_local_to_extents(
        ASSERT(args.fsbno != NULLFSBLOCK);
        ASSERT(args.len == 1);
        tp->t_firstblock = args.fsbno;
-       bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno);
+       error = xfs_trans_get_buf(tp, args.mp->m_ddev_targp,
+                       XFS_FSB_TO_DADDR(args.mp, args.fsbno),
+                       args.mp->m_bsize, 0, &bp);
+       if (error)
+               goto done;
 
        /*
         * Initialize the block, copy the data and log the remote buffer.
@@ -895,8 +845,8 @@ xfs_bmap_local_to_extents(
        xfs_iext_first(ifp, &icur);
        xfs_iext_insert(ip, &icur, &rec, 0);
 
-       XFS_IFORK_NEXT_SET(ip, whichfork, 1);
-       ip->i_d.di_nblocks = 1;
+       ifp->if_nextents = 1;
+       ip->i_nblocks = 1;
        xfs_trans_mod_dquot_byino(tp, ip,
                XFS_TRANS_DQ_BCOUNT, 1L);
        flags |= xfs_ilog_fext(whichfork);
@@ -915,13 +865,15 @@ xfs_bmap_add_attrfork_btree(
        xfs_inode_t             *ip,            /* incore inode pointer */
        int                     *flags)         /* inode logging flags */
 {
-       xfs_btree_cur_t         *cur;           /* btree cursor */
+       struct xfs_btree_block  *block = ip->i_df.if_broot;
+       struct xfs_btree_cur    *cur;           /* btree cursor */
        int                     error;          /* error return value */
        xfs_mount_t             *mp;            /* file system mount struct */
        int                     stat;           /* newroot status */
 
        mp = ip->i_mount;
-       if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip))
+
+       if (XFS_BMAP_BMDR_SPACE(block) <= xfs_inode_data_fork_size(ip))
                *flags |= XFS_ILOG_DBROOT;
        else {
                cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK);
@@ -929,14 +881,17 @@ xfs_bmap_add_attrfork_btree(
                if (error)
                        goto error0;
                /* must be at least one entry */
-               XFS_WANT_CORRUPTED_GOTO(mp, stat == 1, error0);
+               if (XFS_IS_CORRUPT(mp, stat != 1)) {
+                       error = -EFSCORRUPTED;
+                       goto error0;
+               }
                if ((error = xfs_btree_new_iroot(cur, flags, &stat)))
                        goto error0;
                if (stat == 0) {
                        xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
                        return -ENOSPC;
                }
-               cur->bc_private.b.allocated = 0;
+               cur->bc_ino.allocated = 0;
                xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
        }
        return 0;
@@ -954,16 +909,17 @@ xfs_bmap_add_attrfork_extents(
        struct xfs_inode        *ip,            /* incore inode pointer */
        int                     *flags)         /* inode logging flags */
 {
-       xfs_btree_cur_t         *cur;           /* bmap btree cursor */
+       struct xfs_btree_cur    *cur;           /* bmap btree cursor */
        int                     error;          /* error return value */
 
-       if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
+       if (ip->i_df.if_nextents * sizeof(struct xfs_bmbt_rec) <=
+           xfs_inode_data_fork_size(ip))
                return 0;
        cur = NULL;
        error = xfs_bmap_extents_to_btree(tp, ip, &cur, 0, flags,
                                          XFS_DATA_FORK);
        if (cur) {
-               cur->bc_private.b.allocated = 0;
+               cur->bc_ino.allocated = 0;
                xfs_btree_del_cursor(cur, error);
        }
        return error;
@@ -988,7 +944,7 @@ xfs_bmap_add_attrfork_local(
 {
        struct xfs_da_args      dargs;          /* args for dir/attr code */
 
-       if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
+       if (ip->i_df.if_bytes <= xfs_inode_data_fork_size(ip))
                return 0;
 
        if (S_ISDIR(VFS_I(ip)->i_mode)) {
@@ -1011,24 +967,28 @@ xfs_bmap_add_attrfork_local(
        return -EFSCORRUPTED;
 }
 
-/* Set an inode attr fork off based on the format */
-int
+/*
+ * Set an inode attr fork offset based on the format of the data fork.
+ */
+static int
 xfs_bmap_set_attrforkoff(
        struct xfs_inode        *ip,
        int                     size,
        int                     *version)
 {
-       switch (ip->i_d.di_format) {
+       int                     default_size = xfs_default_attroffset(ip) >> 3;
+
+       switch (ip->i_df.if_format) {
        case XFS_DINODE_FMT_DEV:
-               ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
+               ip->i_forkoff = default_size;
                break;
        case XFS_DINODE_FMT_LOCAL:
        case XFS_DINODE_FMT_EXTENTS:
        case XFS_DINODE_FMT_BTREE:
-               ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
-               if (!ip->i_d.di_forkoff)
-                       ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
-               else if ((ip->i_mount->m_flags & XFS_MOUNT_ATTR2) && version)
+               ip->i_forkoff = xfs_attr_shortform_bytesfit(ip, size);
+               if (!ip->i_forkoff)
+                       ip->i_forkoff = default_size;
+               else if (xfs_has_attr2(ip->i_mount) && version)
                        *version = 2;
                break;
        default:
@@ -1056,48 +1016,28 @@ xfs_bmap_add_attrfork(
        int                     logflags;       /* logging flags */
        int                     error;          /* error return value */
 
-       ASSERT(XFS_IFORK_Q(ip) == 0);
+       ASSERT(xfs_inode_has_attr_fork(ip) == 0);
 
        mp = ip->i_mount;
        ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
 
        blks = XFS_ADDAFORK_SPACE_RES(mp);
 
-       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_addafork, blks, 0,
-                       rsvd ? XFS_TRANS_RESERVE : 0, &tp);
+       error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks, 0,
+                       rsvd, &tp);
        if (error)
                return error;
-
-       xfs_ilock(ip, XFS_ILOCK_EXCL);
-       error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ?
-                       XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
-                       XFS_QMOPT_RES_REGBLKS);
-       if (error)
-               goto trans_cancel;
-       if (XFS_IFORK_Q(ip))
-               goto trans_cancel;
-       if (ip->i_d.di_anextents != 0) {
-               error = -EFSCORRUPTED;
+       if (xfs_inode_has_attr_fork(ip))
                goto trans_cancel;
-       }
-       if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
-               /*
-                * For inodes coming from pre-6.2 filesystems.
-                */
-               ASSERT(ip->i_d.di_aformat == 0);
-               ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
-       }
 
-       xfs_trans_ijoin(tp, ip, 0);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
        error = xfs_bmap_set_attrforkoff(ip, size, &version);
        if (error)
                goto trans_cancel;
-       ASSERT(ip->i_afp == NULL);
-       ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, 0);
-       ip->i_afp->if_flags = XFS_IFEXTENTS;
+
+       xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);
        logflags = 0;
-       switch (ip->i_d.di_format) {
+       switch (ip->i_df.if_format) {
        case XFS_DINODE_FMT_LOCAL:
                error = xfs_bmap_add_attrfork_local(tp, ip, &logflags);
                break;
@@ -1115,17 +1055,17 @@ xfs_bmap_add_attrfork(
                xfs_trans_log_inode(tp, ip, logflags);
        if (error)
                goto trans_cancel;
-       if (!xfs_sb_version_hasattr(&mp->m_sb) ||
-          (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {
+       if (!xfs_has_attr(mp) ||
+          (!xfs_has_attr2(mp) && version == 2)) {
                bool log_sb = false;
 
                spin_lock(&mp->m_sb_lock);
-               if (!xfs_sb_version_hasattr(&mp->m_sb)) {
-                       xfs_sb_version_addattr(&mp->m_sb);
+               if (!xfs_has_attr(mp)) {
+                       xfs_add_attr(mp);
                        log_sb = true;
                }
-               if (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2) {
-                       xfs_sb_version_addattr2(&mp->m_sb);
+               if (!xfs_has_attr2(mp) && version == 2) {
+                       xfs_add_attr2(mp);
                        log_sb = true;
                }
                spin_unlock(&mp->m_sb_lock);
@@ -1161,20 +1101,20 @@ xfs_iread_bmbt_block(
 {
        struct xfs_iread_state  *ir = priv;
        struct xfs_mount        *mp = cur->bc_mp;
-       struct xfs_inode        *ip = cur->bc_private.b.ip;
+       struct xfs_inode        *ip = cur->bc_ino.ip;
        struct xfs_btree_block  *block;
        struct xfs_buf          *bp;
        struct xfs_bmbt_rec     *frp;
        xfs_extnum_t            num_recs;
        xfs_extnum_t            j;
-       int                     whichfork = cur->bc_private.b.whichfork;
+       int                     whichfork = cur->bc_ino.whichfork;
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
 
        block = xfs_btree_get_block(cur, level, &bp);
 
        /* Abort if we find more records than nextents. */
        num_recs = xfs_btree_get_numrecs(block);
-       if (unlikely(ir->loaded + num_recs >
-                    XFS_IFORK_NEXTENTS(ip, whichfork))) {
+       if (unlikely(ir->loaded + num_recs > ifp->if_nextents)) {
                xfs_warn(ip->i_mount, "corrupt dinode %llu, (btree extents).",
                                (unsigned long long)ip->i_ino);
                xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, block,
@@ -1200,7 +1140,7 @@ xfs_iread_bmbt_block(
                                xfs_bmap_fork_to_state(whichfork));
                trace_xfs_read_extent(ip, &ir->icur,
                                xfs_bmap_fork_to_state(whichfork), _THIS_IP_);
-               xfs_iext_next(XFS_IFORK_PTR(ip, whichfork), &ir->icur);
+               xfs_iext_next(ifp, &ir->icur);
        }
 
        return 0;
@@ -1216,18 +1156,15 @@ xfs_iread_extents(
        int                     whichfork)
 {
        struct xfs_iread_state  ir;
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_btree_cur    *cur;
        int                     error;
 
-       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+       if (!xfs_need_iread_extents(ifp))
+               return 0;
 
-       if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
-               error = -EFSCORRUPTED;
-               goto out;
-       }
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        ir.loaded = 0;
        xfs_iext_first(ifp, &ir.icur);
@@ -1238,14 +1175,11 @@ xfs_iread_extents(
        if (error)
                goto out;
 
-       if (ir.loaded != XFS_IFORK_NEXTENTS(ip, whichfork)) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
+       if (XFS_IS_CORRUPT(mp, ir.loaded != ifp->if_nextents)) {
                error = -EFSCORRUPTED;
                goto out;
        }
        ASSERT(ir.loaded == xfs_iext_count(ifp));
-
-       ifp->if_flags |= XFS_IFEXTENTS;
        return 0;
 out:
        xfs_iext_destroy(ifp);
@@ -1266,27 +1200,23 @@ xfs_bmap_first_unused(
        xfs_fileoff_t           *first_unused,  /* unused block */
        int                     whichfork)      /* data or attr fork */
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_bmbt_irec    got;
        struct xfs_iext_cursor  icur;
        xfs_fileoff_t           lastaddr = 0;
        xfs_fileoff_t           lowest, max;
        int                     error;
 
-       ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
-              XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
-              XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
-
-       if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
+       if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
                *first_unused = 0;
                return 0;
        }
 
-       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               error = xfs_iread_extents(tp, ip, whichfork);
-               if (error)
-                       return error;
-       }
+       ASSERT(xfs_ifork_has_extents(ifp));
+
+       error = xfs_iread_extents(tp, ip, whichfork);
+       if (error)
+               return error;
 
        lowest = max = *first_unused;
        for_each_xfs_iext(ifp, &icur, &got) {
@@ -1317,12 +1247,12 @@ xfs_bmap_last_before(
        xfs_fileoff_t           *last_block,    /* last block */
        int                     whichfork)      /* data or attr fork */
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_bmbt_irec    got;
        struct xfs_iext_cursor  icur;
        int                     error;
 
-       switch (XFS_IFORK_FORMAT(ip, whichfork)) {
+       switch (ifp->if_format) {
        case XFS_DINODE_FMT_LOCAL:
                *last_block = 0;
                return 0;
@@ -1330,14 +1260,13 @@ xfs_bmap_last_before(
        case XFS_DINODE_FMT_EXTENTS:
                break;
        default:
+               ASSERT(0);
                return -EFSCORRUPTED;
        }
 
-       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               error = xfs_iread_extents(tp, ip, whichfork);
-               if (error)
-                       return error;
-       }
+       error = xfs_iread_extents(tp, ip, whichfork);
+       if (error)
+               return error;
 
        if (!xfs_iext_lookup_extent_before(ip, ifp, last_block, &icur, &got))
                *last_block = 0;
@@ -1352,15 +1281,13 @@ xfs_bmap_last_extent(
        struct xfs_bmbt_irec    *rec,
        int                     *is_empty)
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_iext_cursor  icur;
        int                     error;
 
-       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               error = xfs_iread_extents(tp, ip, whichfork);
-               if (error)
-                       return error;
-       }
+       error = xfs_iread_extents(tp, ip, whichfork);
+       if (error)
+               return error;
 
        xfs_iext_last(ifp, &icur);
        if (!xfs_iext_get_extent(ifp, &icur, rec))
@@ -1420,17 +1347,17 @@ xfs_bmap_last_offset(
        xfs_fileoff_t           *last_block,
        int                     whichfork)
 {
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_bmbt_irec    rec;
        int                     is_empty;
        int                     error;
 
        *last_block = 0;
 
-       if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL)
+       if (ifp->if_format == XFS_DINODE_FMT_LOCAL)
                return 0;
 
-       if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
-           XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+       if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ifp)))
                return -EFSCORRUPTED;
 
        error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
@@ -1441,39 +1368,6 @@ xfs_bmap_last_offset(
        return 0;
 }
 
-/*
- * Returns whether the selected fork of the inode has exactly one
- * block or not.  For the data fork we check this matches di_size,
- * implying the file's range is 0..bsize-1.
- */
-int                                    /* 1=>1 block, 0=>otherwise */
-xfs_bmap_one_block(
-       xfs_inode_t     *ip,            /* incore inode */
-       int             whichfork)      /* data or attr fork */
-{
-       struct xfs_ifork *ifp;          /* inode fork pointer */
-       int             rval;           /* return value */
-       xfs_bmbt_irec_t s;              /* internal version of extent */
-       struct xfs_iext_cursor icur;
-
-#ifndef DEBUG
-       if (whichfork == XFS_DATA_FORK)
-               return XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize;
-#endif /* !DEBUG */
-       if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
-               return 0;
-       if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
-               return 0;
-       ifp = XFS_IFORK_PTR(ip, whichfork);
-       ASSERT(ifp->if_flags & XFS_IFEXTENTS);
-       xfs_iext_first(ifp, &icur);
-       xfs_iext_get_extent(ifp, &icur, &s);
-       rval = s.br_startoff == 0 && s.br_blockcount == 1;
-       if (rval && whichfork == XFS_DATA_FORK)
-               ASSERT(XFS_ISIZE(ip) == ip->i_mount->m_sb.sb_blocksize);
-       return rval;
-}
-
 /*
  * Extent tree manipulation functions used during allocation.
  */
@@ -1486,32 +1380,26 @@ xfs_bmap_add_extent_delay_real(
        struct xfs_bmalloca     *bma,
        int                     whichfork)
 {
+       struct xfs_mount        *mp = bma->ip->i_mount;
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(bma->ip, whichfork);
        struct xfs_bmbt_irec    *new = &bma->got;
        int                     error;  /* error return value */
        int                     i;      /* temp state */
-       struct xfs_ifork        *ifp;   /* inode fork pointer */
        xfs_fileoff_t           new_endoff;     /* end offset of new entry */
        xfs_bmbt_irec_t         r[3];   /* neighbor extent entries */
                                        /* left is 0, right is 1, prev is 2 */
        int                     rval=0; /* return value (logging flags) */
-       int                     state = xfs_bmap_fork_to_state(whichfork);
+       uint32_t                state = xfs_bmap_fork_to_state(whichfork);
        xfs_filblks_t           da_new; /* new count del alloc blocks used */
        xfs_filblks_t           da_old; /* old count del alloc blocks used */
        xfs_filblks_t           temp=0; /* value for da_new calculations */
        int                     tmp_rval;       /* partial logging flags */
-       struct xfs_mount        *mp;
-       xfs_extnum_t            *nextents;
        struct xfs_bmbt_irec    old;
 
-       mp = bma->ip->i_mount;
-       ifp = XFS_IFORK_PTR(bma->ip, whichfork);
        ASSERT(whichfork != XFS_ATTR_FORK);
-       nextents = (whichfork == XFS_COW_FORK ? &bma->ip->i_cnextents :
-                                               &bma->ip->i_d.di_nextents);
-
        ASSERT(!isnullstartblock(new->br_startblock));
        ASSERT(!bma->cur ||
-              (bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL));
+              (bma->cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL));
 
        XFS_STATS_INC(mp, xs_add_exlist);
 
@@ -1554,7 +1442,7 @@ xfs_bmap_add_extent_delay_real(
            LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
            LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
            LEFT.br_state == new->br_state &&
-           LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+           LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
                state |= BMAP_LEFT_CONTIG;
 
        /*
@@ -1572,13 +1460,13 @@ xfs_bmap_add_extent_delay_real(
            new_endoff == RIGHT.br_startoff &&
            new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&
            new->br_state == RIGHT.br_state &&
-           new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
+           new->br_blockcount + RIGHT.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
            ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
                       BMAP_RIGHT_FILLING)) !=
                      (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
                       BMAP_RIGHT_FILLING) ||
             LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
-                       <= MAXEXTLEN))
+                       <= XFS_MAX_BMBT_EXTLEN))
                state |= BMAP_RIGHT_CONTIG;
 
        error = 0;
@@ -1599,7 +1487,7 @@ xfs_bmap_add_extent_delay_real(
                xfs_iext_remove(bma->ip, &bma->icur, state);
                xfs_iext_prev(ifp, &bma->icur);
                xfs_iext_update_extent(bma->ip, state, &bma->icur, &LEFT);
-               (*nextents)--;
+               ifp->if_nextents--;
 
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
@@ -1608,15 +1496,24 @@ xfs_bmap_add_extent_delay_real(
                        error = xfs_bmbt_lookup_eq(bma->cur, &RIGHT, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_btree_delete(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_btree_decrement(bma->cur, 0, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(bma->cur, &LEFT);
                        if (error)
                                goto done;
@@ -1642,7 +1539,10 @@ xfs_bmap_add_extent_delay_real(
                        error = xfs_bmbt_lookup_eq(bma->cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(bma->cur, &LEFT);
                        if (error)
                                goto done;
@@ -1672,7 +1572,10 @@ xfs_bmap_add_extent_delay_real(
                        error = xfs_bmbt_lookup_eq(bma->cur, &RIGHT, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(bma->cur, &PREV);
                        if (error)
                                goto done;
@@ -1688,8 +1591,8 @@ xfs_bmap_add_extent_delay_real(
                PREV.br_startblock = new->br_startblock;
                PREV.br_state = new->br_state;
                xfs_iext_update_extent(bma->ip, state, &bma->icur, &PREV);
+               ifp->if_nextents++;
 
-               (*nextents)++;
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -1697,11 +1600,17 @@ xfs_bmap_add_extent_delay_real(
                        error = xfs_bmbt_lookup_eq(bma->cur, new, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
+                       if (XFS_IS_CORRUPT(mp, i != 0)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_btree_insert(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                }
                break;
 
@@ -1732,7 +1641,10 @@ xfs_bmap_add_extent_delay_real(
                        error = xfs_bmbt_lookup_eq(bma->cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(bma->cur, &LEFT);
                        if (error)
                                goto done;
@@ -1745,7 +1657,8 @@ xfs_bmap_add_extent_delay_real(
                 * The left neighbor is not contiguous.
                 */
                xfs_iext_update_extent(bma->ip, state, &bma->icur, new);
-               (*nextents)++;
+               ifp->if_nextents++;
+
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -1753,11 +1666,17 @@ xfs_bmap_add_extent_delay_real(
                        error = xfs_bmbt_lookup_eq(bma->cur, new, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
+                       if (XFS_IS_CORRUPT(mp, i != 0)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_btree_insert(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                }
 
                if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
@@ -1771,7 +1690,7 @@ xfs_bmap_add_extent_delay_real(
                temp = PREV.br_blockcount - new->br_blockcount;
                da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
                        startblockval(PREV.br_startblock) -
-                       (bma->cur ? bma->cur->bc_private.b.allocated : 0));
+                       (bma->cur ? bma->cur->bc_ino.allocated : 0));
 
                PREV.br_startoff = new_endoff;
                PREV.br_blockcount = temp;
@@ -1798,7 +1717,10 @@ xfs_bmap_add_extent_delay_real(
                        error = xfs_bmbt_lookup_eq(bma->cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(bma->cur, &RIGHT);
                        if (error)
                                goto done;
@@ -1822,7 +1744,8 @@ xfs_bmap_add_extent_delay_real(
                 * The right neighbor is not contiguous.
                 */
                xfs_iext_update_extent(bma->ip, state, &bma->icur, new);
-               (*nextents)++;
+               ifp->if_nextents++;
+
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -1830,11 +1753,17 @@ xfs_bmap_add_extent_delay_real(
                        error = xfs_bmbt_lookup_eq(bma->cur, new, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
+                       if (XFS_IS_CORRUPT(mp, i != 0)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_btree_insert(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                }
 
                if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
@@ -1848,7 +1777,7 @@ xfs_bmap_add_extent_delay_real(
                temp = PREV.br_blockcount - new->br_blockcount;
                da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp),
                        startblockval(PREV.br_startblock) -
-                       (bma->cur ? bma->cur->bc_private.b.allocated : 0));
+                       (bma->cur ? bma->cur->bc_ino.allocated : 0));
 
                PREV.br_startblock = nullstartblock(da_new);
                PREV.br_blockcount = temp;
@@ -1901,7 +1830,7 @@ xfs_bmap_add_extent_delay_real(
                xfs_iext_next(ifp, &bma->icur);
                xfs_iext_insert(bma->ip, &bma->icur, &RIGHT, state);
                xfs_iext_insert(bma->ip, &bma->icur, &LEFT, state);
-               (*nextents)++;
+               ifp->if_nextents++;
 
                if (bma->cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
@@ -1910,11 +1839,17 @@ xfs_bmap_add_extent_delay_real(
                        error = xfs_bmbt_lookup_eq(bma->cur, new, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
+                       if (XFS_IS_CORRUPT(mp, i != 0)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_btree_insert(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                }
 
                if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
@@ -1963,8 +1898,8 @@ xfs_bmap_add_extent_delay_real(
                xfs_mod_delalloc(mp, (int64_t)da_new - da_old);
 
        if (bma->cur) {
-               da_new += bma->cur->bc_private.b.allocated;
-               bma->cur->bc_private.b.allocated = 0;
+               da_new += bma->cur->bc_ino.allocated;
+               bma->cur->bc_ino.allocated = 0;
        }
 
        /* adjust for changes in reserved delayed indirect blocks */
@@ -1993,11 +1928,11 @@ xfs_bmap_add_extent_unwritten_real(
        xfs_inode_t             *ip,    /* incore inode pointer */
        int                     whichfork,
        struct xfs_iext_cursor  *icur,
-       xfs_btree_cur_t         **curp, /* if *curp is null, not a btree */
+       struct xfs_btree_cur    **curp, /* if *curp is null, not a btree */
        xfs_bmbt_irec_t         *new,   /* new data to add to file extents */
        int                     *logflagsp) /* inode logging flags */
 {
-       xfs_btree_cur_t         *cur;   /* btree cursor */
+       struct xfs_btree_cur    *cur;   /* btree cursor */
        int                     error;  /* error return value */
        int                     i;      /* temp state */
        struct xfs_ifork        *ifp;   /* inode fork pointer */
@@ -2005,14 +1940,14 @@ xfs_bmap_add_extent_unwritten_real(
        xfs_bmbt_irec_t         r[3];   /* neighbor extent entries */
                                        /* left is 0, right is 1, prev is 2 */
        int                     rval=0; /* return value (logging flags) */
-       int                     state = xfs_bmap_fork_to_state(whichfork);
+       uint32_t                state = xfs_bmap_fork_to_state(whichfork);
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_bmbt_irec    old;
 
        *logflagsp = 0;
 
        cur = *curp;
-       ifp = XFS_IFORK_PTR(ip, whichfork);
+       ifp = xfs_ifork_ptr(ip, whichfork);
 
        ASSERT(!isnullstartblock(new->br_startblock));
 
@@ -2055,7 +1990,7 @@ xfs_bmap_add_extent_unwritten_real(
            LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
            LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
            LEFT.br_state == new->br_state &&
-           LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+           LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
                state |= BMAP_LEFT_CONTIG;
 
        /*
@@ -2073,13 +2008,13 @@ xfs_bmap_add_extent_unwritten_real(
            new_endoff == RIGHT.br_startoff &&
            new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&
            new->br_state == RIGHT.br_state &&
-           new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
+           new->br_blockcount + RIGHT.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
            ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
                       BMAP_RIGHT_FILLING)) !=
                      (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
                       BMAP_RIGHT_FILLING) ||
             LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
-                       <= MAXEXTLEN))
+                       <= XFS_MAX_BMBT_EXTLEN))
                state |= BMAP_RIGHT_CONTIG;
 
        /*
@@ -2099,8 +2034,7 @@ xfs_bmap_add_extent_unwritten_real(
                xfs_iext_remove(ip, icur, state);
                xfs_iext_prev(ifp, icur);
                xfs_iext_update_extent(ip, state, icur, &LEFT);
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                               XFS_IFORK_NEXTENTS(ip, whichfork) - 2);
+               ifp->if_nextents -= 2;
                if (cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -2108,19 +2042,34 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, &RIGHT, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        if ((error = xfs_btree_delete(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        if ((error = xfs_btree_decrement(cur, 0, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        if ((error = xfs_btree_delete(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        if ((error = xfs_btree_decrement(cur, 0, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &LEFT);
                        if (error)
                                goto done;
@@ -2137,8 +2086,7 @@ xfs_bmap_add_extent_unwritten_real(
                xfs_iext_remove(ip, icur, state);
                xfs_iext_prev(ifp, icur);
                xfs_iext_update_extent(ip, state, icur, &LEFT);
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                               XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
+               ifp->if_nextents--;
                if (cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -2146,13 +2094,22 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, &PREV, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        if ((error = xfs_btree_delete(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        if ((error = xfs_btree_decrement(cur, 0, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &LEFT);
                        if (error)
                                goto done;
@@ -2171,9 +2128,8 @@ xfs_bmap_add_extent_unwritten_real(
                xfs_iext_remove(ip, icur, state);
                xfs_iext_prev(ifp, icur);
                xfs_iext_update_extent(ip, state, icur, &PREV);
+               ifp->if_nextents--;
 
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                               XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
                if (cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -2181,13 +2137,22 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, &RIGHT, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        if ((error = xfs_btree_delete(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        if ((error = xfs_btree_decrement(cur, 0, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &PREV);
                        if (error)
                                goto done;
@@ -2210,7 +2175,10 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, new, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &PREV);
                        if (error)
                                goto done;
@@ -2240,7 +2208,10 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &PREV);
                        if (error)
                                goto done;
@@ -2265,8 +2236,8 @@ xfs_bmap_add_extent_unwritten_real(
 
                xfs_iext_update_extent(ip, state, icur, &PREV);
                xfs_iext_insert(ip, icur, new, state);
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                               XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+               ifp->if_nextents++;
+
                if (cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -2274,14 +2245,20 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &PREV);
                        if (error)
                                goto done;
                        cur->bc_rec.b = *new;
                        if ((error = xfs_btree_insert(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                }
                break;
 
@@ -2308,7 +2285,10 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &PREV);
                        if (error)
                                goto done;
@@ -2332,9 +2312,8 @@ xfs_bmap_add_extent_unwritten_real(
                xfs_iext_update_extent(ip, state, icur, &PREV);
                xfs_iext_next(ifp, icur);
                xfs_iext_insert(ip, icur, new, state);
+               ifp->if_nextents++;
 
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                               XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
                if (cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -2342,17 +2321,26 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &PREV);
                        if (error)
                                goto done;
                        error = xfs_bmbt_lookup_eq(cur, new, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
+                       if (XFS_IS_CORRUPT(mp, i != 0)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        if ((error = xfs_btree_insert(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                }
                break;
 
@@ -2376,9 +2364,8 @@ xfs_bmap_add_extent_unwritten_real(
                xfs_iext_next(ifp, icur);
                xfs_iext_insert(ip, icur, &r[1], state);
                xfs_iext_insert(ip, icur, &r[0], state);
+               ifp->if_nextents += 2;
 
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                               XFS_IFORK_NEXTENTS(ip, whichfork) + 2);
                if (cur == NULL)
                        rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
                else {
@@ -2386,7 +2373,10 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        /* new right extent - oldext */
                        error = xfs_bmbt_update(cur, &r[1]);
                        if (error)
@@ -2395,7 +2385,10 @@ xfs_bmap_add_extent_unwritten_real(
                        cur->bc_rec.b = PREV;
                        if ((error = xfs_btree_insert(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        /*
                         * Reset the cursor to the position of the new extent
                         * we are about to insert as we can't trust it after
@@ -2404,11 +2397,17 @@ xfs_bmap_add_extent_unwritten_real(
                        error = xfs_bmbt_lookup_eq(cur, new, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
+                       if (XFS_IS_CORRUPT(mp, i != 0)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        /* new middle extent - newext */
                        if ((error = xfs_btree_insert(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                }
                break;
 
@@ -2442,7 +2441,7 @@ xfs_bmap_add_extent_unwritten_real(
 
        /* clear out the allocated field, done with it now in any case. */
        if (cur) {
-               cur->bc_private.b.allocated = 0;
+               cur->bc_ino.allocated = 0;
                *curp = cur;
        }
 
@@ -2470,10 +2469,10 @@ xfs_bmap_add_extent_hole_delay(
        xfs_filblks_t           newlen=0;       /* new indirect size */
        xfs_filblks_t           oldlen=0;       /* old indirect size */
        xfs_bmbt_irec_t         right;  /* right neighbor extent entry */
-       int                     state = xfs_bmap_fork_to_state(whichfork);
+       uint32_t                state = xfs_bmap_fork_to_state(whichfork);
        xfs_filblks_t           temp;    /* temp for indirect calculations */
 
-       ifp = XFS_IFORK_PTR(ip, whichfork);
+       ifp = xfs_ifork_ptr(ip, whichfork);
        ASSERT(isnullstartblock(new->br_startblock));
 
        /*
@@ -2501,15 +2500,15 @@ xfs_bmap_add_extent_hole_delay(
         */
        if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) &&
            left.br_startoff + left.br_blockcount == new->br_startoff &&
-           left.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+           left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
                state |= BMAP_LEFT_CONTIG;
 
        if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) &&
            new->br_startoff + new->br_blockcount == right.br_startoff &&
-           new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
+           new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
            (!(state & BMAP_LEFT_CONTIG) ||
             (left.br_blockcount + new->br_blockcount +
-             right.br_blockcount <= MAXEXTLEN)))
+             right.br_blockcount <= XFS_MAX_BMBT_EXTLEN)))
                state |= BMAP_RIGHT_CONTIG;
 
        /*
@@ -2607,9 +2606,9 @@ xfs_bmap_add_extent_hole_real(
        struct xfs_btree_cur    **curp,
        struct xfs_bmbt_irec    *new,
        int                     *logflagsp,
-       int                     flags)
+       uint32_t                flags)
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_btree_cur    *cur = *curp;
        int                     error;  /* error return value */
@@ -2617,11 +2616,11 @@ xfs_bmap_add_extent_hole_real(
        xfs_bmbt_irec_t         left;   /* left neighbor extent entry */
        xfs_bmbt_irec_t         right;  /* right neighbor extent entry */
        int                     rval=0; /* return value (logging flags) */
-       int                     state = xfs_bmap_fork_to_state(whichfork);
+       uint32_t                state = xfs_bmap_fork_to_state(whichfork);
        struct xfs_bmbt_irec    old;
 
        ASSERT(!isnullstartblock(new->br_startblock));
-       ASSERT(!cur || !(cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL));
+       ASSERT(!cur || !(cur->bc_ino.flags & XFS_BTCUR_BMBT_WASDEL));
 
        XFS_STATS_INC(mp, xs_add_exlist);
 
@@ -2652,17 +2651,17 @@ xfs_bmap_add_extent_hole_real(
            left.br_startoff + left.br_blockcount == new->br_startoff &&
            left.br_startblock + left.br_blockcount == new->br_startblock &&
            left.br_state == new->br_state &&
-           left.br_blockcount + new->br_blockcount <= MAXEXTLEN)
+           left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
                state |= BMAP_LEFT_CONTIG;
 
        if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&
            new->br_startoff + new->br_blockcount == right.br_startoff &&
            new->br_startblock + new->br_blockcount == right.br_startblock &&
            new->br_state == right.br_state &&
-           new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
+           new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
            (!(state & BMAP_LEFT_CONTIG) ||
             left.br_blockcount + new->br_blockcount +
-            right.br_blockcount <= MAXEXTLEN))
+            right.br_blockcount <= XFS_MAX_BMBT_EXTLEN))
                state |= BMAP_RIGHT_CONTIG;
 
        error = 0;
@@ -2681,9 +2680,8 @@ xfs_bmap_add_extent_hole_real(
                xfs_iext_remove(ip, icur, state);
                xfs_iext_prev(ifp, icur);
                xfs_iext_update_extent(ip, state, icur, &left);
+               ifp->if_nextents--;
 
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                       XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
                if (cur == NULL) {
                        rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
                } else {
@@ -2691,15 +2689,24 @@ xfs_bmap_add_extent_hole_real(
                        error = xfs_bmbt_lookup_eq(cur, &right, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_btree_delete(cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_btree_decrement(cur, 0, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &left);
                        if (error)
                                goto done;
@@ -2725,7 +2732,10 @@ xfs_bmap_add_extent_hole_real(
                        error = xfs_bmbt_lookup_eq(cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &left);
                        if (error)
                                goto done;
@@ -2752,7 +2762,10 @@ xfs_bmap_add_extent_hole_real(
                        error = xfs_bmbt_lookup_eq(cur, &old, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_bmbt_update(cur, &right);
                        if (error)
                                goto done;
@@ -2766,8 +2779,8 @@ xfs_bmap_add_extent_hole_real(
                 * Insert a new entry.
                 */
                xfs_iext_insert(ip, icur, new, state);
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                       XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+               ifp->if_nextents++;
+
                if (cur == NULL) {
                        rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
                } else {
@@ -2775,11 +2788,17 @@ xfs_bmap_add_extent_hole_real(
                        error = xfs_bmbt_lookup_eq(cur, new, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
+                       if (XFS_IS_CORRUPT(mp, i != 0)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                        error = xfs_btree_insert(cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                }
                break;
        }
@@ -2803,7 +2822,7 @@ xfs_bmap_add_extent_hole_real(
 
        /* clear out the allocated field, done with it now in any case. */
        if (cur)
-               cur->bc_private.b.allocated = 0;
+               cur->bc_ino.allocated = 0;
 
        xfs_bmap_check_leaf_extents(cur, ip, whichfork);
 done:
@@ -2816,7 +2835,7 @@ done:
  */
 
 /*
- * Adjust the size of the new extent based on di_extsize and rt extsize.
+ * Adjust the size of the new extent based on i_extsize and rt extsize.
  */
 int
 xfs_bmap_extsize_align(
@@ -2877,15 +2896,15 @@ xfs_bmap_extsize_align(
 
        /*
         * For large extent hint sizes, the aligned extent might be larger than
-        * MAXEXTLEN. In that case, reduce the size by an extsz so that it pulls
-        * the length back under MAXEXTLEN. The outer allocation loops handle
-        * short allocation just fine, so it is safe to do this. We only want to
-        * do it when we are forced to, though, because it means more allocation
-        * operations are required.
+        * XFS_BMBT_MAX_EXTLEN. In that case, reduce the size by an extsz so
+        * that it pulls the length back under XFS_BMBT_MAX_EXTLEN. The outer
+        * allocation loops handle short allocation just fine, so it is safe to
+        * do this. We only want to do it when we are forced to, though, because
+        * it means more allocation operations are required.
         */
-       while (align_alen > MAXEXTLEN)
+       while (align_alen > XFS_MAX_BMBT_EXTLEN)
                align_alen -= extsz;
-       ASSERT(align_alen <= MAXEXTLEN);
+       ASSERT(align_alen <= XFS_MAX_BMBT_EXTLEN);
 
        /*
         * If the previous block overlaps with this proposed allocation
@@ -2975,9 +2994,9 @@ xfs_bmap_extsize_align(
                        return -EINVAL;
        } else {
                ASSERT(orig_off >= align_off);
-               /* see MAXEXTLEN handling above */
+               /* see XFS_BMBT_MAX_EXTLEN handling above */
                ASSERT(orig_end <= align_off + align_alen ||
-                      align_alen + extsz > MAXEXTLEN);
+                      align_alen + extsz > XFS_MAX_BMBT_EXTLEN);
        }
 
 #ifdef DEBUG
@@ -3014,7 +3033,7 @@ xfs_bmap_adjacent(
        mp = ap->ip->i_mount;
        nullfb = ap->tp->t_firstblock == NULLFSBLOCK;
        rt = XFS_IS_REALTIME_INODE(ap->ip) &&
-               xfs_alloc_is_userdata(ap->datatype);
+               (ap->datatype & XFS_ALLOC_USERDATA);
        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp,
                                                        ap->tp->t_firstblock);
        /*
@@ -3158,12 +3177,14 @@ xfs_bmap_longest_free_extent(
 
        pag = xfs_perag_get(mp, ag);
        if (!pag->pagf_init) {
-               error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK);
-               if (error)
-                       goto out;
-
-               if (!pag->pagf_init) {
-                       *notinit = 1;
+               error = xfs_alloc_read_agf(pag, tp, XFS_ALLOC_FLAG_TRYLOCK,
+                               NULL);
+               if (error) {
+                       /* Couldn't lock the AGF, so skip this AG. */
+                       if (error == -EAGAIN) {
+                               *notinit = 1;
+                               error = 0;
+                       }
                        goto out;
                }
        }
@@ -3321,7 +3342,7 @@ xfs_bmap_btalloc_accounting(
        }
 
        /* data/attr fork only */
-       ap->ip->i_d.di_nblocks += args->len;
+       ap->ip->i_nblocks += args->len;
        xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
        if (ap->wasdel) {
                ap->ip->i_delayed_blks -= args->len;
@@ -3332,84 +3353,222 @@ xfs_bmap_btalloc_accounting(
                args->len);
 }
 
-STATIC int
-xfs_bmap_btalloc(
-       struct xfs_bmalloca     *ap)    /* bmap alloc argument struct */
+static int
+xfs_bmap_compute_alignments(
+       struct xfs_bmalloca     *ap,
+       struct xfs_alloc_arg    *args)
 {
-       xfs_mount_t     *mp;            /* mount point structure */
-       xfs_alloctype_t atype = 0;      /* type for allocation routines */
-       xfs_extlen_t    align = 0;      /* minimum allocation alignment */
-       xfs_agnumber_t  fb_agno;        /* ag number of ap->firstblock */
-       xfs_agnumber_t  ag;
-       xfs_alloc_arg_t args;
-       xfs_fileoff_t   orig_offset;
-       xfs_extlen_t    orig_length;
-       xfs_extlen_t    blen;
-       xfs_extlen_t    nextminlen = 0;
-       int             nullfb;         /* true if ap->firstblock isn't set */
-       int             isaligned;
-       int             tryagain;
-       int             error;
-       int             stripe_align;
-
-       ASSERT(ap->length);
-       orig_offset = ap->offset;
-       orig_length = ap->length;
-
-       mp = ap->ip->i_mount;
+       struct xfs_mount        *mp = args->mp;
+       xfs_extlen_t            align = 0; /* minimum allocation alignment */
+       int                     stripe_align = 0;
 
        /* stripe alignment for allocation is determined by mount parameters */
-       stripe_align = 0;
-       if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
+       if (mp->m_swidth && xfs_has_swalloc(mp))
                stripe_align = mp->m_swidth;
        else if (mp->m_dalign)
                stripe_align = mp->m_dalign;
 
        if (ap->flags & XFS_BMAPI_COWFORK)
                align = xfs_get_cowextsz_hint(ap->ip);
-       else if (xfs_alloc_is_userdata(ap->datatype))
+       else if (ap->datatype & XFS_ALLOC_USERDATA)
                align = xfs_get_extsz_hint(ap->ip);
        if (align) {
-               error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
-                                               align, 0, ap->eof, 0, ap->conv,
-                                               &ap->offset, &ap->length);
-               ASSERT(!error);
+               if (xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, align, 0,
+                                       ap->eof, 0, ap->conv, &ap->offset,
+                                       &ap->length))
+                       ASSERT(0);
                ASSERT(ap->length);
        }
 
+       /* apply extent size hints if obtained earlier */
+       if (align) {
+               args->prod = align;
+               div_u64_rem(ap->offset, args->prod, &args->mod);
+               if (args->mod)
+                       args->mod = args->prod - args->mod;
+       } else if (mp->m_sb.sb_blocksize >= PAGE_SIZE) {
+               args->prod = 1;
+               args->mod = 0;
+       } else {
+               args->prod = PAGE_SIZE >> mp->m_sb.sb_blocklog;
+               div_u64_rem(ap->offset, args->prod, &args->mod);
+               if (args->mod)
+                       args->mod = args->prod - args->mod;
+       }
+
+       return stripe_align;
+}
 
-       nullfb = ap->tp->t_firstblock == NULLFSBLOCK;
-       fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp,
-                                                       ap->tp->t_firstblock);
-       if (nullfb) {
-               if (xfs_alloc_is_userdata(ap->datatype) &&
-                   xfs_inode_is_filestream(ap->ip)) {
-                       ag = xfs_filestream_lookup_ag(ap->ip);
-                       ag = (ag != NULLAGNUMBER) ? ag : 0;
-                       ap->blkno = XFS_AGB_TO_FSB(mp, ag, 0);
-               } else {
-                       ap->blkno = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
-               }
-       } else
-               ap->blkno = ap->tp->t_firstblock;
+static void
+xfs_bmap_process_allocated_extent(
+       struct xfs_bmalloca     *ap,
+       struct xfs_alloc_arg    *args,
+       xfs_fileoff_t           orig_offset,
+       xfs_extlen_t            orig_length)
+{
+       int                     nullfb;
 
-       xfs_bmap_adjacent(ap);
+       nullfb = ap->tp->t_firstblock == NULLFSBLOCK;
 
        /*
-        * If allowed, use ap->blkno; otherwise must use firstblock since
-        * it's in the right allocation group.
+        * check the allocation happened at the same or higher AG than
+        * the first block that was allocated.
         */
-       if (nullfb || XFS_FSB_TO_AGNO(mp, ap->blkno) == fb_agno)
-               ;
-       else
-               ap->blkno = ap->tp->t_firstblock;
+       ASSERT(nullfb ||
+               XFS_FSB_TO_AGNO(args->mp, ap->tp->t_firstblock) <=
+               XFS_FSB_TO_AGNO(args->mp, args->fsbno));
+
+       ap->blkno = args->fsbno;
+       if (nullfb)
+               ap->tp->t_firstblock = args->fsbno;
+       ap->length = args->len;
        /*
-        * Normal allocation, done through xfs_alloc_vextent.
+        * If the extent size hint is active, we tried to round the
+        * caller's allocation request offset down to extsz and the
+        * length up to another extsz boundary.  If we found a free
+        * extent we mapped it in starting at this new offset.  If the
+        * newly mapped space isn't long enough to cover any of the
+        * range of offsets that was originally requested, move the
+        * mapping up so that we can fill as much of the caller's
+        * original request as possible.  Free space is apparently
+        * very fragmented so we're unlikely to be able to satisfy the
+        * hints anyway.
+        */
+       if (ap->length <= orig_length)
+               ap->offset = orig_offset;
+       else if (ap->offset + ap->length < orig_offset + orig_length)
+               ap->offset = orig_offset + orig_length - ap->length;
+       xfs_bmap_btalloc_accounting(ap, args);
+}
+
+#ifdef DEBUG
+static int
+xfs_bmap_exact_minlen_extent_alloc(
+       struct xfs_bmalloca     *ap)
+{
+       struct xfs_mount        *mp = ap->ip->i_mount;
+       struct xfs_alloc_arg    args = { .tp = ap->tp, .mp = mp };
+       xfs_fileoff_t           orig_offset;
+       xfs_extlen_t            orig_length;
+       int                     error;
+
+       ASSERT(ap->length);
+
+       if (ap->minlen != 1) {
+               ap->blkno = NULLFSBLOCK;
+               ap->length = 0;
+               return 0;
+       }
+
+       orig_offset = ap->offset;
+       orig_length = ap->length;
+
+       args.alloc_minlen_only = 1;
+
+       xfs_bmap_compute_alignments(ap, &args);
+
+       if (ap->tp->t_firstblock == NULLFSBLOCK) {
+               /*
+                * Unlike the longest extent available in an AG, we don't track
+                * the length of an AG's shortest extent.
+                * XFS_ERRTAG_BMAP_ALLOC_MINLEN_EXTENT is a debug only knob and
+                * hence we can afford to start traversing from the 0th AG since
+                * we need not be concerned about a drop in performance in
+                * "debug only" code paths.
+                */
+               ap->blkno = XFS_AGB_TO_FSB(mp, 0, 0);
+       } else {
+               ap->blkno = ap->tp->t_firstblock;
+       }
+
+       args.fsbno = ap->blkno;
+       args.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
+       args.type = XFS_ALLOCTYPE_FIRST_AG;
+       args.minlen = args.maxlen = ap->minlen;
+       args.total = ap->total;
+
+       args.alignment = 1;
+       args.minalignslop = 0;
+
+       args.minleft = ap->minleft;
+       args.wasdel = ap->wasdel;
+       args.resv = XFS_AG_RESV_NONE;
+       args.datatype = ap->datatype;
+
+       error = xfs_alloc_vextent(&args);
+       if (error)
+               return error;
+
+       if (args.fsbno != NULLFSBLOCK) {
+               xfs_bmap_process_allocated_extent(ap, &args, orig_offset,
+                       orig_length);
+       } else {
+               ap->blkno = NULLFSBLOCK;
+               ap->length = 0;
+       }
+
+       return 0;
+}
+#else
+
+#define xfs_bmap_exact_minlen_extent_alloc(bma) (-EFSCORRUPTED)
+
+#endif
+
+STATIC int
+xfs_bmap_btalloc(
+       struct xfs_bmalloca     *ap)
+{
+       struct xfs_mount        *mp = ap->ip->i_mount;
+       struct xfs_alloc_arg    args = { .tp = ap->tp, .mp = mp };
+       xfs_alloctype_t         atype = 0;
+       xfs_agnumber_t          fb_agno;        /* ag number of ap->firstblock */
+       xfs_agnumber_t          ag;
+       xfs_fileoff_t           orig_offset;
+       xfs_extlen_t            orig_length;
+       xfs_extlen_t            blen;
+       xfs_extlen_t            nextminlen = 0;
+       int                     nullfb; /* true if ap->firstblock isn't set */
+       int                     isaligned;
+       int                     tryagain;
+       int                     error;
+       int                     stripe_align;
+
+       ASSERT(ap->length);
+       orig_offset = ap->offset;
+       orig_length = ap->length;
+
+       stripe_align = xfs_bmap_compute_alignments(ap, &args);
+
+       nullfb = ap->tp->t_firstblock == NULLFSBLOCK;
+       fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp,
+                                                       ap->tp->t_firstblock);
+       if (nullfb) {
+               if ((ap->datatype & XFS_ALLOC_USERDATA) &&
+                   xfs_inode_is_filestream(ap->ip)) {
+                       ag = xfs_filestream_lookup_ag(ap->ip);
+                       ag = (ag != NULLAGNUMBER) ? ag : 0;
+                       ap->blkno = XFS_AGB_TO_FSB(mp, ag, 0);
+               } else {
+                       ap->blkno = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
+               }
+       } else
+               ap->blkno = ap->tp->t_firstblock;
+
+       xfs_bmap_adjacent(ap);
+
+       /*
+        * If allowed, use ap->blkno; otherwise must use firstblock since
+        * it's in the right allocation group.
+        */
+       if (nullfb || XFS_FSB_TO_AGNO(mp, ap->blkno) == fb_agno)
+               ;
+       else
+               ap->blkno = ap->tp->t_firstblock;
+       /*
+        * Normal allocation, done through xfs_alloc_vextent.
         */
        tryagain = isaligned = 0;
-       memset(&args, 0, sizeof(args));
-       args.tp = ap->tp;
-       args.mp = mp;
        args.fsbno = ap->blkno;
        args.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
 
@@ -3422,7 +3581,7 @@ xfs_bmap_btalloc(
                 * enough for the request.  If one isn't found, then adjust
                 * the minimum allocation size to the largest space found.
                 */
-               if (xfs_alloc_is_userdata(ap->datatype) &&
+               if ((ap->datatype & XFS_ALLOC_USERDATA) &&
                    xfs_inode_is_filestream(ap->ip))
                        error = xfs_bmap_btalloc_filestreams(ap, &args, &blen);
                else
@@ -3440,21 +3599,7 @@ xfs_bmap_btalloc(
                args.total = ap->total;
                args.minlen = ap->minlen;
        }
-       /* apply extent size hints if obtained earlier */
-       if (align) {
-               args.prod = align;
-               div_u64_rem(ap->offset, args.prod, &args.mod);
-               if (args.mod)
-                       args.mod = args.prod - args.mod;
-       } else if (mp->m_sb.sb_blocksize >= PAGE_SIZE) {
-               args.prod = 1;
-               args.mod = 0;
-       } else {
-               args.prod = PAGE_SIZE >> mp->m_sb.sb_blocklog;
-               div_u64_rem(ap->offset, args.prod, &args.mod);
-               if (args.mod)
-                       args.mod = args.prod - args.mod;
-       }
+
        /*
         * If we are not low on available data blocks, and the underlying
         * logical volume manager is a stripe, and the file offset is zero then
@@ -3510,8 +3655,6 @@ xfs_bmap_btalloc(
        args.wasdel = ap->wasdel;
        args.resv = XFS_AG_RESV_NONE;
        args.datatype = ap->datatype;
-       if (ap->datatype & XFS_ALLOC_USERDATA_ZERO)
-               args.ip = ap->ip;
 
        error = xfs_alloc_vextent(&args);
        if (error)
@@ -3558,37 +3701,10 @@ xfs_bmap_btalloc(
                        return error;
                ap->tp->t_flags |= XFS_TRANS_LOWMODE;
        }
+
        if (args.fsbno != NULLFSBLOCK) {
-               /*
-                * check the allocation happened at the same or higher AG than
-                * the first block that was allocated.
-                */
-               ASSERT(ap->tp->t_firstblock == NULLFSBLOCK ||
-                      XFS_FSB_TO_AGNO(mp, ap->tp->t_firstblock) <=
-                      XFS_FSB_TO_AGNO(mp, args.fsbno));
-
-               ap->blkno = args.fsbno;
-               if (ap->tp->t_firstblock == NULLFSBLOCK)
-                       ap->tp->t_firstblock = args.fsbno;
-               ASSERT(nullfb || fb_agno <= args.agno);
-               ap->length = args.len;
-               /*
-                * If the extent size hint is active, we tried to round the
-                * caller's allocation request offset down to extsz and the
-                * length up to another extsz boundary.  If we found a free
-                * extent we mapped it in starting at this new offset.  If the
-                * newly mapped space isn't long enough to cover any of the
-                * range of offsets that was originally requested, move the
-                * mapping up so that we can fill as much of the caller's
-                * original request as possible.  Free space is apparently
-                * very fragmented so we're unlikely to be able to satisfy the
-                * hints anyway.
-                */
-               if (ap->length <= orig_length)
-                       ap->offset = orig_offset;
-               else if (ap->offset + ap->length < orig_offset + orig_length)
-                       ap->offset = orig_offset + orig_length - ap->length;
-               xfs_bmap_btalloc_accounting(ap, &args);
+               xfs_bmap_process_allocated_extent(ap, &args, orig_offset,
+                       orig_length);
        } else {
                ap->blkno = NULLFSBLOCK;
                ap->length = 0;
@@ -3596,20 +3712,6 @@ xfs_bmap_btalloc(
        return 0;
 }
 
-/*
- * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
- * It figures out where to ask the underlying allocator to put the new extent.
- */
-STATIC int
-xfs_bmap_alloc(
-       struct xfs_bmalloca     *ap)    /* bmap alloc argument struct */
-{
-       if (XFS_IS_REALTIME_INODE(ap->ip) &&
-           xfs_alloc_is_userdata(ap->datatype))
-               return xfs_bmap_rtalloc(ap);
-       return xfs_bmap_btalloc(ap);
-}
-
 /* Trim extent to fit a logical block range. */
 void
 xfs_trim_extent(
@@ -3655,7 +3757,7 @@ xfs_bmapi_trim_map(
        xfs_fileoff_t           obno,
        xfs_fileoff_t           end,
        int                     n,
-       int                     flags)
+       uint32_t                flags)
 {
        if ((flags & XFS_BMAPI_ENTIRE) ||
            got->br_startoff + got->br_blockcount <= obno) {
@@ -3700,7 +3802,7 @@ xfs_bmapi_update_map(
        xfs_fileoff_t           obno,
        xfs_fileoff_t           end,
        int                     *n,
-       int                     flags)
+       uint32_t                flags)
 {
        xfs_bmbt_irec_t *mval = *map;
 
@@ -3753,10 +3855,11 @@ xfs_bmapi_read(
        xfs_filblks_t           len,
        struct xfs_bmbt_irec    *mval,
        int                     *nmap,
-       int                     flags)
+       uint32_t                flags)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_ifork        *ifp;
+       int                     whichfork = xfs_bmapi_whichfork(flags);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_bmbt_irec    got;
        xfs_fileoff_t           obno;
        xfs_fileoff_t           end;
@@ -3764,56 +3867,26 @@ xfs_bmapi_read(
        int                     error;
        bool                    eof = false;
        int                     n = 0;
-       int                     whichfork = xfs_bmapi_whichfork(flags);
 
        ASSERT(*nmap >= 1);
-       ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE|
-                          XFS_BMAPI_COWFORK)));
+       ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK | XFS_BMAPI_ENTIRE)));
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED|XFS_ILOCK_EXCL));
 
-       if (unlikely(XFS_TEST_ERROR(
-           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
-            mp, XFS_ERRTAG_BMAPIFORMAT))) {
-               XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp);
+       if (WARN_ON_ONCE(!ifp))
+               return -EFSCORRUPTED;
+
+       if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
+           XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT))
                return -EFSCORRUPTED;
-       }
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
        XFS_STATS_INC(mp, xs_blk_mapr);
 
-       ifp = XFS_IFORK_PTR(ip, whichfork);
-       if (!ifp) {
-               /* No CoW fork?  Return a hole. */
-               if (whichfork == XFS_COW_FORK) {
-                       mval->br_startoff = bno;
-                       mval->br_startblock = HOLESTARTBLOCK;
-                       mval->br_blockcount = len;
-                       mval->br_state = XFS_EXT_NORM;
-                       *nmap = 1;
-                       return 0;
-               }
-
-               /*
-                * A missing attr ifork implies that the inode says we're in
-                * extents or btree format but failed to pass the inode fork
-                * verifier while trying to load it.  Treat that as a file
-                * corruption too.
-                */
-#ifdef DEBUG
-               xfs_alert(mp, "%s: inode %llu missing fork %d",
-                               __func__, ip->i_ino, whichfork);
-#endif /* DEBUG */
-               return -EFSCORRUPTED;
-       }
-
-       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               error = xfs_iread_extents(NULL, ip, whichfork);
-               if (error)
-                       return error;
-       }
+       error = xfs_iread_extents(NULL, ip, whichfork);
+       if (error)
+               return error;
 
        if (!xfs_iext_lookup_extent(ip, ifp, bno, &icur, &got))
                eof = true;
@@ -3879,7 +3952,7 @@ xfs_bmapi_reserve_delalloc(
        int                     eof)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        xfs_extlen_t            alen;
        xfs_extlen_t            indlen;
        int                     error;
@@ -3889,7 +3962,7 @@ xfs_bmapi_reserve_delalloc(
         * Cap the alloc length. Keep track of prealloc so we know whether to
         * tag the inode before we return.
         */
-       alen = XFS_FILBLKS_MIN(len + prealloc, MAXEXTLEN);
+       alen = XFS_FILBLKS_MIN(len + prealloc, XFS_MAX_BMBT_EXTLEN);
        if (!eof)
                alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
        if (prealloc && alen >= len)
@@ -3913,8 +3986,7 @@ xfs_bmapi_reserve_delalloc(
         * blocks.  This number gets adjusted later.  We return if we haven't
         * allocated blocks already inside this loop.
         */
-       error = xfs_trans_reserve_quota_nblks(NULL, ip, (long)alen, 0,
-                                               XFS_QMOPT_RES_REGBLKS);
+       error = xfs_quota_reserve_blkres(ip, alen);
        if (error)
                return error;
 
@@ -3960,18 +4032,54 @@ out_unreserve_blocks:
        xfs_mod_fdblocks(mp, alen, false);
 out_unreserve_quota:
        if (XFS_IS_QUOTA_ON(mp))
-               xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0,
-                                               XFS_QMOPT_RES_REGBLKS);
+               xfs_quota_unreserve_blkres(ip, alen);
        return error;
 }
 
+static int
+xfs_bmap_alloc_userdata(
+       struct xfs_bmalloca     *bma)
+{
+       struct xfs_mount        *mp = bma->ip->i_mount;
+       int                     whichfork = xfs_bmapi_whichfork(bma->flags);
+       int                     error;
+
+       /*
+        * Set the data type being allocated. For the data fork, the first data
+        * in the file is treated differently to all other allocations. For the
+        * attribute fork, we only need to ensure the allocated range is not on
+        * the busy list.
+        */
+       bma->datatype = XFS_ALLOC_NOBUSY;
+       if (whichfork == XFS_DATA_FORK) {
+               bma->datatype |= XFS_ALLOC_USERDATA;
+               if (bma->offset == 0)
+                       bma->datatype |= XFS_ALLOC_INITIAL_USER_DATA;
+
+               if (mp->m_dalign && bma->length >= mp->m_dalign) {
+                       error = xfs_bmap_isaeof(bma, whichfork);
+                       if (error)
+                               return error;
+               }
+
+               if (XFS_IS_REALTIME_INODE(bma->ip))
+                       return xfs_bmap_rtalloc(bma);
+       }
+
+       if (unlikely(XFS_TEST_ERROR(false, mp,
+                       XFS_ERRTAG_BMAP_ALLOC_MINLEN_EXTENT)))
+               return xfs_bmap_exact_minlen_extent_alloc(bma);
+
+       return xfs_bmap_btalloc(bma);
+}
+
 static int
 xfs_bmapi_allocate(
        struct xfs_bmalloca     *bma)
 {
        struct xfs_mount        *mp = bma->ip->i_mount;
        int                     whichfork = xfs_bmapi_whichfork(bma->flags);
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(bma->ip, whichfork);
        int                     tmp_logflags = 0;
        int                     error;
 
@@ -3984,52 +4092,39 @@ xfs_bmapi_allocate(
        if (bma->wasdel) {
                bma->length = (xfs_extlen_t)bma->got.br_blockcount;
                bma->offset = bma->got.br_startoff;
-               xfs_iext_peek_prev_extent(ifp, &bma->icur, &bma->prev);
+               if (!xfs_iext_peek_prev_extent(ifp, &bma->icur, &bma->prev))
+                       bma->prev.br_startoff = NULLFILEOFF;
        } else {
-               bma->length = XFS_FILBLKS_MIN(bma->length, MAXEXTLEN);
+               bma->length = XFS_FILBLKS_MIN(bma->length, XFS_MAX_BMBT_EXTLEN);
                if (!bma->eof)
                        bma->length = XFS_FILBLKS_MIN(bma->length,
                                        bma->got.br_startoff - bma->offset);
        }
 
-       /*
-        * Set the data type being allocated. For the data fork, the first data
-        * in the file is treated differently to all other allocations. For the
-        * attribute fork, we only need to ensure the allocated range is not on
-        * the busy list.
-        */
-       if (!(bma->flags & XFS_BMAPI_METADATA)) {
-               bma->datatype = XFS_ALLOC_NOBUSY;
-               if (whichfork == XFS_DATA_FORK) {
-                       if (bma->offset == 0)
-                               bma->datatype |= XFS_ALLOC_INITIAL_USER_DATA;
-                       else
-                               bma->datatype |= XFS_ALLOC_USERDATA;
-               }
-               if (bma->flags & XFS_BMAPI_ZERO)
-                       bma->datatype |= XFS_ALLOC_USERDATA_ZERO;
-       }
+       if (bma->flags & XFS_BMAPI_CONTIG)
+               bma->minlen = bma->length;
+       else
+               bma->minlen = 1;
 
-       bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
+       if (bma->flags & XFS_BMAPI_METADATA) {
+               if (unlikely(XFS_TEST_ERROR(false, mp,
+                               XFS_ERRTAG_BMAP_ALLOC_MINLEN_EXTENT)))
+                       error = xfs_bmap_exact_minlen_extent_alloc(bma);
+               else
+                       error = xfs_bmap_btalloc(bma);
+       } else {
+               error = xfs_bmap_alloc_userdata(bma);
+       }
+       if (error || bma->blkno == NULLFSBLOCK)
+               return error;
 
-       /*
-        * Only want to do the alignment at the eof if it is userdata and
-        * allocation length is larger than a stripe unit.
-        */
-       if (mp->m_dalign && bma->length >= mp->m_dalign &&
-           !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
-               error = xfs_bmap_isaeof(bma, whichfork);
+       if (bma->flags & XFS_BMAPI_ZERO) {
+               error = xfs_zero_extent(bma->ip, bma->blkno, bma->length);
                if (error)
                        return error;
        }
 
-       error = xfs_bmap_alloc(bma);
-       if (error)
-               return error;
-
-       if (bma->blkno == NULLFSBLOCK)
-               return 0;
-       if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur)
+       if (ifp->if_format == XFS_DINODE_FMT_BTREE && !bma->cur)
                bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork);
        /*
         * Bump the number of extents we've allocated
@@ -4038,25 +4133,15 @@ xfs_bmapi_allocate(
        bma->nallocs++;
 
        if (bma->cur)
-               bma->cur->bc_private.b.flags =
-                       bma->wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
+               bma->cur->bc_ino.flags =
+                       bma->wasdel ? XFS_BTCUR_BMBT_WASDEL : 0;
 
        bma->got.br_startoff = bma->offset;
        bma->got.br_startblock = bma->blkno;
        bma->got.br_blockcount = bma->length;
        bma->got.br_state = XFS_EXT_NORM;
 
-       /*
-        * In the data fork, a wasdelay extent has been initialized, so
-        * shouldn't be flagged as unwritten.
-        *
-        * For the cow fork, however, we convert delalloc reservations
-        * (extents allocated for speculative preallocation) to
-        * allocated unwritten extents, and only convert the unwritten
-        * extents to real extents when we're about to write the data.
-        */
-       if ((!bma->wasdel || (bma->flags & XFS_BMAPI_COWFORK)) &&
-           (bma->flags & XFS_BMAPI_PREALLOC))
+       if (bma->flags & XFS_BMAPI_PREALLOC)
                bma->got.br_state = XFS_EXT_UNWRITTEN;
 
        if (bma->wasdel)
@@ -4090,10 +4175,10 @@ xfs_bmapi_convert_unwritten(
        struct xfs_bmalloca     *bma,
        struct xfs_bmbt_irec    *mval,
        xfs_filblks_t           len,
-       int                     flags)
+       uint32_t                flags)
 {
        int                     whichfork = xfs_bmapi_whichfork(flags);
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(bma->ip, whichfork);
        int                     tmp_logflags = 0;
        int                     error;
 
@@ -4112,7 +4197,7 @@ xfs_bmapi_convert_unwritten(
         * Modify (by adding) the state flag, if writing.
         */
        ASSERT(mval->br_blockcount <= len);
-       if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) {
+       if (ifp->if_format == XFS_DINODE_FMT_BTREE && !bma->cur) {
                bma->cur = xfs_bmbt_init_cursor(bma->ip->i_mount, bma->tp,
                                        bma->ip, whichfork);
        }
@@ -4170,11 +4255,13 @@ xfs_bmapi_minleft(
        struct xfs_inode        *ip,
        int                     fork)
 {
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, fork);
+
        if (tp && tp->t_firstblock != NULLFSBLOCK)
                return 0;
-       if (XFS_IFORK_FORMAT(ip, fork) != XFS_DINODE_FMT_BTREE)
+       if (ifp->if_format != XFS_DINODE_FMT_BTREE)
                return 1;
-       return be16_to_cpu(XFS_IFORK_PTR(ip, fork)->if_broot->bb_level) + 1;
+       return be16_to_cpu(ifp->if_broot->bb_level) + 1;
 }
 
 /*
@@ -4189,11 +4276,13 @@ xfs_bmapi_finish(
        int                     whichfork,
        int                     error)
 {
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(bma->ip, whichfork);
+
        if ((bma->logflags & xfs_ilog_fext(whichfork)) &&
-           XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+           ifp->if_format != XFS_DINODE_FMT_EXTENTS)
                bma->logflags &= ~xfs_ilog_fext(whichfork);
        else if ((bma->logflags & xfs_ilog_fbroot(whichfork)) &&
-                XFS_IFORK_FORMAT(bma->ip, whichfork) != XFS_DINODE_FMT_BTREE)
+                ifp->if_format != XFS_DINODE_FMT_BTREE)
                bma->logflags &= ~xfs_ilog_fbroot(whichfork);
 
        if (bma->logflags)
@@ -4214,7 +4303,7 @@ xfs_bmapi_write(
        struct xfs_inode        *ip,            /* incore inode */
        xfs_fileoff_t           bno,            /* starting file offs. mapped */
        xfs_filblks_t           len,            /* length to map in file */
-       int                     flags,          /* XFS_BMAPI_... */
+       uint32_t                flags,          /* XFS_BMAPI_... */
        xfs_extlen_t            total,          /* total blocks needed */
        struct xfs_bmbt_irec    *mval,          /* output: map values */
        int                     *nmap)          /* i/o: mval size/count */
@@ -4225,13 +4314,13 @@ xfs_bmapi_write(
                .total          = total,
        };
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_ifork        *ifp;
+       int                     whichfork = xfs_bmapi_whichfork(flags);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        xfs_fileoff_t           end;            /* end of mapped file region */
        bool                    eof = false;    /* after the end of extents */
        int                     error;          /* error return */
        int                     n;              /* current extent index */
        xfs_fileoff_t           obno;           /* old block number (offset) */
-       int                     whichfork;      /* data or attr fork */
 
 #ifdef DEBUG
        xfs_fileoff_t           orig_bno;       /* original block number value */
@@ -4246,13 +4335,12 @@ xfs_bmapi_write(
        orig_mval = mval;
        orig_nmap = *nmap;
 #endif
-       whichfork = xfs_bmapi_whichfork(flags);
 
        ASSERT(*nmap >= 1);
        ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
        ASSERT(tp != NULL);
        ASSERT(len > 0);
-       ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL);
+       ASSERT(ifp->if_format != XFS_DINODE_FMT_LOCAL);
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(!(flags & XFS_BMAPI_REMAP));
 
@@ -4268,26 +4356,19 @@ xfs_bmapi_write(
        ASSERT((flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)) !=
                        (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO));
 
-       if (unlikely(XFS_TEST_ERROR(
-           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
-            mp, XFS_ERRTAG_BMAPIFORMAT))) {
-               XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp);
+       if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
+           XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
                return -EFSCORRUPTED;
        }
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
-       ifp = XFS_IFORK_PTR(ip, whichfork);
-
        XFS_STATS_INC(mp, xs_blk_mapw);
 
-       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               error = xfs_iread_extents(tp, ip, whichfork);
-               if (error)
-                       goto error0;
-       }
+       error = xfs_iread_extents(tp, ip, whichfork);
+       if (error)
+               goto error0;
 
        if (!xfs_iext_lookup_extent(ip, ifp, bno, &bma.icur, &bma.got))
                eof = true;
@@ -4334,8 +4415,8 @@ xfs_bmapi_write(
                         * xfs_extlen_t and therefore 32 bits. Hence we have to
                         * check for 32-bit overflows and handle them here.
                         */
-                       if (len > (xfs_filblks_t)MAXEXTLEN)
-                               bma.length = MAXEXTLEN;
+                       if (len > (xfs_filblks_t)XFS_MAX_BMBT_EXTLEN)
+                               bma.length = XFS_MAX_BMBT_EXTLEN;
                        else
                                bma.length = len;
 
@@ -4390,9 +4471,8 @@ xfs_bmapi_write(
        if (error)
                goto error0;
 
-       ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
-              XFS_IFORK_NEXTENTS(ip, whichfork) >
-               XFS_IFORK_MAXEXT(ip, whichfork));
+       ASSERT(ifp->if_format != XFS_DINODE_FMT_BTREE ||
+              ifp->if_nextents > XFS_IFORK_MAXEXT(ip, whichfork));
        xfs_bmapi_finish(&bma, whichfork, 0);
        xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
                orig_nmap, *nmap);
@@ -4416,7 +4496,7 @@ xfs_bmapi_convert_delalloc(
        struct iomap            *iomap,
        unsigned int            *seq)
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_mount        *mp = ip->i_mount;
        xfs_fileoff_t           offset_fsb = XFS_B_TO_FSBT(mp, offset);
        struct xfs_bmalloca     bma = { NULL };
@@ -4439,6 +4519,14 @@ xfs_bmapi_convert_delalloc(
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, 0);
 
+       error = xfs_iext_count_may_overflow(ip, whichfork,
+                       XFS_IEXT_ADD_NOSPLIT_CNT);
+       if (error == -EFBIG)
+               error = xfs_iext_count_upgrade(tp, ip,
+                               XFS_IEXT_ADD_NOSPLIT_CNT);
+       if (error)
+               goto out_trans_cancel;
+
        if (!xfs_iext_lookup_extent(ip, ifp, offset_fsb, &bma.icur, &bma.got) ||
            bma.got.br_startoff > offset_fsb) {
                /*
@@ -4456,7 +4544,8 @@ xfs_bmapi_convert_delalloc(
         * the extent.  Just return the real extent at this offset.
         */
        if (!isnullstartblock(bma.got.br_startblock)) {
-               xfs_bmbt_to_iomap(ip, iomap, &bma.got, flags);
+               xfs_bmbt_to_iomap(ip, iomap, &bma.got, 0, flags,
+                               xfs_iomap_inode_sequence(ip, flags));
                *seq = READ_ONCE(ifp->if_seq);
                goto out_trans_cancel;
        }
@@ -4465,10 +4554,26 @@ xfs_bmapi_convert_delalloc(
        bma.ip = ip;
        bma.wasdel = true;
        bma.offset = bma.got.br_startoff;
-       bma.length = max_t(xfs_filblks_t, bma.got.br_blockcount, MAXEXTLEN);
+       bma.length = max_t(xfs_filblks_t, bma.got.br_blockcount,
+                       XFS_MAX_BMBT_EXTLEN);
        bma.minleft = xfs_bmapi_minleft(tp, ip, whichfork);
+
+       /*
+        * When we're converting the delalloc reservations backing dirty pages
+        * in the page cache, we must be careful about how we create the new
+        * extents:
+        *
+        * New CoW fork extents are created unwritten, turned into real extents
+        * when we're about to write the data to disk, and mapped into the data
+        * fork after the write finishes.  End of story.
+        *
+        * New data fork extents must be mapped in as unwritten and converted
+        * to real extents after the write succeeds to avoid exposing stale
+        * disk contents if we crash.
+        */
+       bma.flags = XFS_BMAPI_PREALLOC;
        if (whichfork == XFS_COW_FORK)
-               bma.flags = XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC;
+               bma.flags |= XFS_BMAPI_COWFORK;
 
        if (!xfs_iext_peek_prev_extent(ifp, &bma.icur, &bma.prev))
                bma.prev.br_startoff = NULLFILEOFF;
@@ -4488,7 +4593,8 @@ xfs_bmapi_convert_delalloc(
        XFS_STATS_INC(mp, xs_xstrat_quick);
 
        ASSERT(!isnullstartblock(bma.got.br_startblock));
-       xfs_bmbt_to_iomap(ip, iomap, &bma.got, flags);
+       xfs_bmbt_to_iomap(ip, iomap, &bma.got, 0, flags,
+                               xfs_iomap_inode_sequence(ip, flags));
        *seq = READ_ONCE(ifp->if_seq);
 
        if (whichfork == XFS_COW_FORK)
@@ -4519,7 +4625,7 @@ xfs_bmapi_remap(
        xfs_fileoff_t           bno,
        xfs_filblks_t           len,
        xfs_fsblock_t           startblock,
-       int                     flags)
+       uint32_t                flags)
 {
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_ifork        *ifp;
@@ -4529,31 +4635,26 @@ xfs_bmapi_remap(
        int                     whichfork = xfs_bmapi_whichfork(flags);
        int                     logflags = 0, error;
 
-       ifp = XFS_IFORK_PTR(ip, whichfork);
+       ifp = xfs_ifork_ptr(ip, whichfork);
        ASSERT(len > 0);
-       ASSERT(len <= (xfs_filblks_t)MAXEXTLEN);
+       ASSERT(len <= (xfs_filblks_t)XFS_MAX_BMBT_EXTLEN);
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC |
                           XFS_BMAPI_NORMAP)));
        ASSERT((flags & (XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC)) !=
                        (XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC));
 
-       if (unlikely(XFS_TEST_ERROR(
-           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
-            mp, XFS_ERRTAG_BMAPIFORMAT))) {
-               XFS_ERROR_REPORT("xfs_bmapi_remap", XFS_ERRLEVEL_LOW, mp);
+       if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
+           XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
                return -EFSCORRUPTED;
        }
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
-       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               error = xfs_iread_extents(tp, ip, whichfork);
-               if (error)
-                       return error;
-       }
+       error = xfs_iread_extents(tp, ip, whichfork);
+       if (error)
+               return error;
 
        if (xfs_iext_lookup_extent(ip, ifp, bno, &icur, &got)) {
                /* make sure we only reflink into a hole. */
@@ -4561,12 +4662,12 @@ xfs_bmapi_remap(
                ASSERT(got.br_startoff - bno >= len);
        }
 
-       ip->i_d.di_nblocks += len;
+       ip->i_nblocks += len;
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
-       if (ifp->if_flags & XFS_IFBROOT) {
+       if (ifp->if_format == XFS_DINODE_FMT_BTREE) {
                cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
-               cur->bc_private.b.flags = 0;
+               cur->bc_ino.flags = 0;
        }
 
        got.br_startoff = bno;
@@ -4585,9 +4686,9 @@ xfs_bmapi_remap(
        error = xfs_bmap_btree_to_extents(tp, ip, cur, &logflags, whichfork);
 
 error0:
-       if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS)
+       if (ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS)
                logflags &= ~XFS_ILOG_DEXT;
-       else if (ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
+       else if (ip->i_df.if_format != XFS_DINODE_FMT_BTREE)
                logflags &= ~XFS_ILOG_DBROOT;
 
        if (logflags)
@@ -4691,12 +4792,12 @@ xfs_bmap_del_extent_delay(
        struct xfs_bmbt_irec    *del)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_bmbt_irec    new;
        int64_t                 da_old, da_new, da_diff = 0;
        xfs_fileoff_t           del_endoff, got_endoff;
        xfs_filblks_t           got_indlen, new_indlen, stolen;
-       int                     state = xfs_bmap_fork_to_state(whichfork);
+       uint32_t                state = xfs_bmap_fork_to_state(whichfork);
        int                     error = 0;
        bool                    isrt;
 
@@ -4724,9 +4825,8 @@ xfs_bmap_del_extent_delay(
         * sb counters as we might have to borrow some blocks for the
         * indirect block accounting.
         */
-       error = xfs_trans_reserve_quota_nblks(NULL, ip,
-                       -((long)del->br_blockcount), 0,
-                       isrt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+       ASSERT(!isrt);
+       error = xfs_quota_unreserve_blkres(ip, del->br_blockcount);
        if (error)
                return error;
        ip->i_delayed_blks -= del->br_blockcount;
@@ -4819,10 +4919,10 @@ xfs_bmap_del_extent_cow(
        struct xfs_bmbt_irec    *del)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK);
        struct xfs_bmbt_irec    new;
        xfs_fileoff_t           del_endoff, got_endoff;
-       int                     state = BMAP_COWFORK;
+       uint32_t                state = BMAP_COWFORK;
 
        XFS_STATS_INC(mp, xs_del_exlist);
 
@@ -4891,11 +4991,11 @@ xfs_bmap_del_extent_real(
        xfs_inode_t             *ip,    /* incore inode pointer */
        xfs_trans_t             *tp,    /* current transaction pointer */
        struct xfs_iext_cursor  *icur,
-       xfs_btree_cur_t         *cur,   /* if null, not a btree */
+       struct xfs_btree_cur    *cur,   /* if null, not a btree */
        xfs_bmbt_irec_t         *del,   /* data to remove from extents */
        int                     *logflagsp, /* inode logging flags */
        int                     whichfork, /* data or attr fork */
-       int                     bflags) /* bmapi flags */
+       uint32_t                bflags) /* bmapi flags */
 {
        xfs_fsblock_t           del_endblock=0; /* first block past del */
        xfs_fileoff_t           del_endoff;     /* first offset past del */
@@ -4911,13 +5011,13 @@ xfs_bmap_del_extent_real(
        xfs_bmbt_irec_t         new;    /* new record to be inserted */
        /* REFERENCED */
        uint                    qfield; /* quota field to update */
-       int                     state = xfs_bmap_fork_to_state(whichfork);
+       uint32_t                state = xfs_bmap_fork_to_state(whichfork);
        struct xfs_bmbt_irec    old;
 
        mp = ip->i_mount;
        XFS_STATS_INC(mp, xs_del_exlist);
 
-       ifp = XFS_IFORK_PTR(ip, whichfork);
+       ifp = xfs_ifork_ptr(ip, whichfork);
        ASSERT(del->br_blockcount > 0);
        xfs_iext_get_extent(ifp, icur, &got);
        ASSERT(got.br_startoff <= del->br_startoff);
@@ -4937,28 +5037,32 @@ xfs_bmap_del_extent_real(
         * conversion to btree format, since the transaction will be dirty then.
         */
        if (tp->t_blk_res == 0 &&
-           XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
-           XFS_IFORK_NEXTENTS(ip, whichfork) >=
-                       XFS_IFORK_MAXEXT(ip, whichfork) &&
+           ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
+           ifp->if_nextents >= XFS_IFORK_MAXEXT(ip, whichfork) &&
            del->br_startoff > got.br_startoff && del_endoff < got_endoff)
                return -ENOSPC;
 
        flags = XFS_ILOG_CORE;
        if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
-               xfs_fsblock_t   bno;
                xfs_filblks_t   len;
                xfs_extlen_t    mod;
 
-               bno = div_u64_rem(del->br_startblock, mp->m_sb.sb_rextsize,
-                                 &mod);
-               ASSERT(mod == 0);
                len = div_u64_rem(del->br_blockcount, mp->m_sb.sb_rextsize,
                                  &mod);
                ASSERT(mod == 0);
 
-               error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
-               if (error)
-                       goto done;
+               if (!(bflags & XFS_BMAPI_REMAP)) {
+                       xfs_fsblock_t   bno;
+
+                       bno = div_u64_rem(del->br_startblock,
+                                       mp->m_sb.sb_rextsize, &mod);
+                       ASSERT(mod == 0);
+
+                       error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
+                       if (error)
+                               goto done;
+               }
+
                do_fx = 0;
                nblks = len * mp->m_sb.sb_rextsize;
                qfield = XFS_TRANS_DQ_RTBCOUNT;
@@ -4973,7 +5077,10 @@ xfs_bmap_del_extent_real(
                error = xfs_bmbt_lookup_eq(cur, &got, &i);
                if (error)
                        goto done;
-               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+               if (XFS_IS_CORRUPT(mp, i != 1)) {
+                       error = -EFSCORRUPTED;
+                       goto done;
+               }
        }
 
        if (got.br_startoff == del->br_startoff)
@@ -4988,8 +5095,8 @@ xfs_bmap_del_extent_real(
                 */
                xfs_iext_remove(ip, icur, state);
                xfs_iext_prev(ifp, icur);
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                       XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
+               ifp->if_nextents--;
+
                flags |= XFS_ILOG_CORE;
                if (!cur) {
                        flags |= xfs_ilog_fext(whichfork);
@@ -4997,7 +5104,10 @@ xfs_bmap_del_extent_real(
                }
                if ((error = xfs_btree_delete(cur, &i)))
                        goto done;
-               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+               if (XFS_IS_CORRUPT(mp, i != 1)) {
+                       error = -EFSCORRUPTED;
+                       goto done;
+               }
                break;
        case BMAP_LEFT_FILLING:
                /*
@@ -5033,6 +5143,7 @@ xfs_bmap_del_extent_real(
                /*
                 * Deleting the middle of the extent.
                 */
+
                old = got;
 
                got.br_blockcount = del->br_startoff - got.br_startoff;
@@ -5068,7 +5179,10 @@ xfs_bmap_del_extent_real(
                                error = xfs_bmbt_lookup_eq(cur, &got, &i);
                                if (error)
                                        goto done;
-                               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                               if (XFS_IS_CORRUPT(mp, i != 1)) {
+                                       error = -EFSCORRUPTED;
+                                       goto done;
+                               }
                                /*
                                 * Update the btree record back
                                 * to the original value.
@@ -5085,11 +5199,14 @@ xfs_bmap_del_extent_real(
                                error = -ENOSPC;
                                goto done;
                        }
-                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+                       if (XFS_IS_CORRUPT(mp, i != 1)) {
+                               error = -EFSCORRUPTED;
+                               goto done;
+                       }
                } else
                        flags |= xfs_ilog_fext(whichfork);
-               XFS_IFORK_NEXT_SET(ip, whichfork,
-                       XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+
+               ifp->if_nextents++;
                xfs_iext_next(ifp, icur);
                xfs_iext_insert(ip, icur, &new, state);
                break;
@@ -5105,7 +5222,7 @@ xfs_bmap_del_extent_real(
                if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) {
                        xfs_refcount_decrease_extent(tp, del);
                } else {
-                       __xfs_bmap_add_free(tp, del->br_startblock,
+                       __xfs_free_extent_later(tp, del->br_startblock,
                                        del->br_blockcount, NULL,
                                        (bflags & XFS_BMAPI_NODISCARD) ||
                                        del->br_state == XFS_EXT_UNWRITTEN);
@@ -5116,7 +5233,7 @@ xfs_bmap_del_extent_real(
         * Adjust inode # blocks in the file.
         */
        if (nblks)
-               ip->i_d.di_nblocks -= nblks;
+               ip->i_nblocks -= nblks;
        /*
         * Adjust quota data.
         */
@@ -5140,7 +5257,7 @@ __xfs_bunmapi(
        struct xfs_inode        *ip,            /* incore inode */
        xfs_fileoff_t           start,          /* first file offset deleted */
        xfs_filblks_t           *rlen,          /* i/o: amount remaining */
-       int                     flags,          /* misc flags */
+       uint32_t                flags,          /* misc flags */
        xfs_extnum_t            nexts)          /* number of extents max */
 {
        struct xfs_btree_cur    *cur;           /* bmap btree cursor */
@@ -5152,14 +5269,12 @@ __xfs_bunmapi(
        int                     isrt;           /* freeing in rt area */
        int                     logflags;       /* transaction logging flags */
        xfs_extlen_t            mod;            /* rt extent offset */
-       struct xfs_mount        *mp;            /* mount structure */
+       struct xfs_mount        *mp = ip->i_mount;
        int                     tmp_logflags;   /* partial logging flags */
        int                     wasdel;         /* was a delayed alloc extent */
        int                     whichfork;      /* data or attribute fork */
        xfs_fsblock_t           sum;
        xfs_filblks_t           len = *rlen;    /* length to unmap in file */
-       xfs_fileoff_t           max_len;
-       xfs_agnumber_t          prev_agno = NULLAGNUMBER, agno;
        xfs_fileoff_t           end;
        struct xfs_iext_cursor  icur;
        bool                    done = false;
@@ -5168,35 +5283,20 @@ __xfs_bunmapi(
 
        whichfork = xfs_bmapi_whichfork(flags);
        ASSERT(whichfork != XFS_COW_FORK);
-       ifp = XFS_IFORK_PTR(ip, whichfork);
-       if (unlikely(
-           XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-           XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
-               XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW,
-                                ip->i_mount);
+       ifp = xfs_ifork_ptr(ip, whichfork);
+       if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)))
                return -EFSCORRUPTED;
-       }
-       mp = ip->i_mount;
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(len > 0);
        ASSERT(nexts >= 0);
 
-       /*
-        * Guesstimate how many blocks we can unmap without running the risk of
-        * blowing out the transaction with a mix of EFIs and reflink
-        * adjustments.
-        */
-       if (tp && xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK)
-               max_len = min(len, xfs_refcount_max_unmap(tp->t_log_res));
-       else
-               max_len = len;
-
-       if (!(ifp->if_flags & XFS_IFEXTENTS) &&
-           (error = xfs_iread_extents(tp, ip, whichfork)))
+       error = xfs_iread_extents(tp, ip, whichfork);
+       if (error)
                return error;
+
        if (xfs_iext_count(ifp) == 0) {
                *rlen = 0;
                return 0;
@@ -5212,10 +5312,10 @@ __xfs_bunmapi(
        end--;
 
        logflags = 0;
-       if (ifp->if_flags & XFS_IFBROOT) {
-               ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
+       if (ifp->if_format == XFS_DINODE_FMT_BTREE) {
+               ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
                cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
-               cur->bc_private.b.flags = 0;
+               cur->bc_ino.flags = 0;
        } else
                cur = NULL;
 
@@ -5231,7 +5331,7 @@ __xfs_bunmapi(
 
        extno = 0;
        while (end != (xfs_fileoff_t)-1 && end >= start &&
-              (nexts == 0 || extno < nexts) && max_len > 0) {
+              (nexts == 0 || extno < nexts)) {
                /*
                 * Is the found extent after a hole in which end lives?
                 * Just back up to the previous extent, if so.
@@ -5256,16 +5356,6 @@ __xfs_bunmapi(
                del = got;
                wasdel = isnullstartblock(del.br_startblock);
 
-               /*
-                * Make sure we don't touch multiple AGF headers out of order
-                * in a single transaction, as that could cause AB-BA deadlocks.
-                */
-               if (!wasdel) {
-                       agno = XFS_FSB_TO_AGNO(mp, del.br_startblock);
-                       if (prev_agno != NULLAGNUMBER && prev_agno > agno)
-                               break;
-                       prev_agno = agno;
-               }
                if (got.br_startoff < start) {
                        del.br_startoff = start;
                        del.br_blockcount -= start - got.br_startoff;
@@ -5275,14 +5365,6 @@ __xfs_bunmapi(
                if (del.br_startoff + del.br_blockcount > end + 1)
                        del.br_blockcount = end + 1 - del.br_startoff;
 
-               /* How much can we safely unmap? */
-               if (max_len < del.br_blockcount) {
-                       del.br_startoff += del.br_blockcount - max_len;
-                       if (!wasdel)
-                               del.br_startblock += del.br_blockcount - max_len;
-                       del.br_blockcount = max_len;
-               }
-
                if (!isrt)
                        goto delete;
 
@@ -5336,16 +5418,17 @@ __xfs_bunmapi(
                }
                div_u64_rem(del.br_startblock, mp->m_sb.sb_rextsize, &mod);
                if (mod) {
+                       xfs_extlen_t off = mp->m_sb.sb_rextsize - mod;
+
                        /*
                         * Realtime extent is lined up at the end but not
                         * at the front.  We'll get rid of full extents if
                         * we can.
                         */
-                       mod = mp->m_sb.sb_rextsize - mod;
-                       if (del.br_blockcount > mod) {
-                               del.br_blockcount -= mod;
-                               del.br_startoff += mod;
-                               del.br_startblock += mod;
+                       if (del.br_blockcount > off) {
+                               del.br_blockcount -= off;
+                               del.br_startoff += off;
+                               del.br_startblock += off;
                        } else if (del.br_startoff == start &&
                                   (del.br_state == XFS_EXT_UNWRITTEN ||
                                    tp->t_blk_res == 0)) {
@@ -5363,6 +5446,7 @@ __xfs_bunmapi(
                                continue;
                        } else if (del.br_state == XFS_EXT_UNWRITTEN) {
                                struct xfs_bmbt_irec    prev;
+                               xfs_fileoff_t           unwrite_start;
 
                                /*
                                 * This one is already unwritten.
@@ -5376,12 +5460,13 @@ __xfs_bunmapi(
                                ASSERT(!isnullstartblock(prev.br_startblock));
                                ASSERT(del.br_startblock ==
                                       prev.br_startblock + prev.br_blockcount);
-                               if (prev.br_startoff < start) {
-                                       mod = start - prev.br_startoff;
-                                       prev.br_blockcount -= mod;
-                                       prev.br_startblock += mod;
-                                       prev.br_startoff = start;
-                               }
+                               unwrite_start = max3(start,
+                                                    del.br_startoff - mod,
+                                                    prev.br_startoff);
+                               mod = unwrite_start - prev.br_startoff;
+                               prev.br_startoff = unwrite_start;
+                               prev.br_startblock += mod;
+                               prev.br_blockcount -= mod;
                                prev.br_state = XFS_EXT_UNWRITTEN;
                                error = xfs_bmap_add_extent_unwritten_real(tp,
                                                ip, whichfork, &icur, &cur,
@@ -5415,7 +5500,6 @@ delete:
                if (error)
                        goto error0;
 
-               max_len -= del.br_blockcount;
                end = del.br_startoff - 1;
 nodelete:
                /*
@@ -5455,10 +5539,10 @@ error0:
         * logging the extent records if we've converted to btree format.
         */
        if ((logflags & xfs_ilog_fext(whichfork)) &&
-           XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
+           ifp->if_format != XFS_DINODE_FMT_EXTENTS)
                logflags &= ~xfs_ilog_fext(whichfork);
        else if ((logflags & xfs_ilog_fbroot(whichfork)) &&
-                XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
+                ifp->if_format != XFS_DINODE_FMT_BTREE)
                logflags &= ~xfs_ilog_fbroot(whichfork);
        /*
         * Log inode even in the error case, if the transaction
@@ -5468,7 +5552,7 @@ error0:
                xfs_trans_log_inode(tp, ip, logflags);
        if (cur) {
                if (!error)
-                       cur->bc_private.b.allocated = 0;
+                       cur->bc_ino.allocated = 0;
                xfs_btree_del_cursor(cur, error);
        }
        return error;
@@ -5481,7 +5565,7 @@ xfs_bunmapi(
        struct xfs_inode        *ip,
        xfs_fileoff_t           bno,
        xfs_filblks_t           len,
-       int                     flags,
+       uint32_t                flags,
        xfs_extnum_t            nexts,
        int                     *done)
 {
@@ -5513,7 +5597,7 @@ xfs_bmse_can_merge(
        if ((left->br_startoff + left->br_blockcount != startoff) ||
            (left->br_startblock + left->br_blockcount != got->br_startblock) ||
            (left->br_state != got->br_state) ||
-           (left->br_blockcount + got->br_blockcount > MAXEXTLEN))
+           (left->br_blockcount + got->br_blockcount > XFS_MAX_BMBT_EXTLEN))
                return false;
 
        return true;
@@ -5540,6 +5624,7 @@ xfs_bmse_merge(
        struct xfs_btree_cur            *cur,
        int                             *logflags)      /* output */
 {
+       struct xfs_ifork                *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_bmbt_irec            new;
        xfs_filblks_t                   blockcount;
        int                             error, i;
@@ -5558,8 +5643,7 @@ xfs_bmse_merge(
         * Update the on-disk extent count, the btree if necessary and log the
         * inode.
         */
-       XFS_IFORK_NEXT_SET(ip, whichfork,
-                          XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
+       ifp->if_nextents--;
        *logflags |= XFS_ILOG_CORE;
        if (!cur) {
                *logflags |= XFS_ILOG_DEXT;
@@ -5570,18 +5654,21 @@ xfs_bmse_merge(
        error = xfs_bmbt_lookup_eq(cur, got, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
+       if (XFS_IS_CORRUPT(mp, i != 1))
+               return -EFSCORRUPTED;
 
        error = xfs_btree_delete(cur, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
+       if (XFS_IS_CORRUPT(mp, i != 1))
+               return -EFSCORRUPTED;
 
        /* lookup and update size of the previous extent */
        error = xfs_bmbt_lookup_eq(cur, left, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
+       if (XFS_IS_CORRUPT(mp, i != 1))
+               return -EFSCORRUPTED;
 
        error = xfs_bmbt_update(cur, &new);
        if (error)
@@ -5594,7 +5681,7 @@ xfs_bmse_merge(
 
 done:
        xfs_iext_remove(ip, icur, 0);
-       xfs_iext_prev(XFS_IFORK_PTR(ip, whichfork), icur);
+       xfs_iext_prev(ifp, icur);
        xfs_iext_update_extent(ip, xfs_bmap_fork_to_state(whichfork), icur,
                        &new);
 
@@ -5629,7 +5716,8 @@ xfs_bmap_shift_update_extent(
                error = xfs_bmbt_lookup_eq(cur, &prev, &i);
                if (error)
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
+               if (XFS_IS_CORRUPT(mp, i != 1))
+                       return -EFSCORRUPTED;
 
                error = xfs_bmbt_update(cur, got);
                if (error)
@@ -5657,7 +5745,7 @@ xfs_bmap_collapse_extents(
 {
        int                     whichfork = XFS_DATA_FORK;
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_btree_cur    *cur = NULL;
        struct xfs_bmbt_irec    got, prev;
        struct xfs_iext_cursor  icur;
@@ -5665,36 +5753,33 @@ xfs_bmap_collapse_extents(
        int                     error = 0;
        int                     logflags = 0;
 
-       if (unlikely(XFS_TEST_ERROR(
-           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
-            mp, XFS_ERRTAG_BMAPIFORMAT))) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
+       if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
+           XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
                return -EFSCORRUPTED;
        }
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL));
 
-       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               error = xfs_iread_extents(tp, ip, whichfork);
-               if (error)
-                       return error;
-       }
+       error = xfs_iread_extents(tp, ip, whichfork);
+       if (error)
+               return error;
 
-       if (ifp->if_flags & XFS_IFBROOT) {
+       if (ifp->if_format == XFS_DINODE_FMT_BTREE) {
                cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
-               cur->bc_private.b.flags = 0;
+               cur->bc_ino.flags = 0;
        }
 
        if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, &icur, &got)) {
                *done = true;
                goto del_cursor;
        }
-       XFS_WANT_CORRUPTED_GOTO(mp, !isnullstartblock(got.br_startblock),
-                               del_cursor);
+       if (XFS_IS_CORRUPT(mp, isnullstartblock(got.br_startblock))) {
+               error = -EFSCORRUPTED;
+               goto del_cursor;
+       }
 
        new_startoff = got.br_startoff - offset_shift_fsb;
        if (xfs_iext_peek_prev_extent(ifp, &icur, &prev)) {
@@ -5751,7 +5836,7 @@ xfs_bmap_can_insert_extents(
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
 
-       if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+       if (xfs_is_shutdown(ip->i_mount))
                return -EIO;
 
        xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -5775,7 +5860,7 @@ xfs_bmap_insert_extents(
 {
        int                     whichfork = XFS_DATA_FORK;
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_btree_cur    *cur = NULL;
        struct xfs_bmbt_irec    got, next;
        struct xfs_iext_cursor  icur;
@@ -5783,28 +5868,23 @@ xfs_bmap_insert_extents(
        int                     error = 0;
        int                     logflags = 0;
 
-       if (unlikely(XFS_TEST_ERROR(
-           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
-            mp, XFS_ERRTAG_BMAPIFORMAT))) {
-               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
+       if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
+           XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
                return -EFSCORRUPTED;
        }
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL));
 
-       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               error = xfs_iread_extents(tp, ip, whichfork);
-               if (error)
-                       return error;
-       }
+       error = xfs_iread_extents(tp, ip, whichfork);
+       if (error)
+               return error;
 
-       if (ifp->if_flags & XFS_IFBROOT) {
+       if (ifp->if_format == XFS_DINODE_FMT_BTREE) {
                cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
-               cur->bc_private.b.flags = 0;
+               cur->bc_ino.flags = 0;
        }
 
        if (*next_fsb == NULLFSBLOCK) {
@@ -5820,10 +5900,12 @@ xfs_bmap_insert_extents(
                        goto del_cursor;
                }
        }
-       XFS_WANT_CORRUPTED_GOTO(mp, !isnullstartblock(got.br_startblock),
-                               del_cursor);
+       if (XFS_IS_CORRUPT(mp, isnullstartblock(got.br_startblock))) {
+               error = -EFSCORRUPTED;
+               goto del_cursor;
+       }
 
-       if (stop_fsb >= got.br_startoff + got.br_blockcount) {
+       if (XFS_IS_CORRUPT(mp, stop_fsb > got.br_startoff)) {
                error = -EFSCORRUPTED;
                goto del_cursor;
        }
@@ -5871,43 +5953,36 @@ del_cursor:
  * @split_fsb is a block where the extents is split.  If split_fsb lies in a
  * hole or the first block of extents, just return 0.
  */
-STATIC int
-xfs_bmap_split_extent_at(
+int
+xfs_bmap_split_extent(
        struct xfs_trans        *tp,
        struct xfs_inode        *ip,
        xfs_fileoff_t           split_fsb)
 {
        int                             whichfork = XFS_DATA_FORK;
+       struct xfs_ifork                *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_btree_cur            *cur = NULL;
        struct xfs_bmbt_irec            got;
        struct xfs_bmbt_irec            new; /* split extent */
        struct xfs_mount                *mp = ip->i_mount;
-       struct xfs_ifork                *ifp;
        xfs_fsblock_t                   gotblkcnt; /* new block count for got */
        struct xfs_iext_cursor          icur;
        int                             error = 0;
        int                             logflags = 0;
        int                             i = 0;
 
-       if (unlikely(XFS_TEST_ERROR(
-           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
-            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
-            mp, XFS_ERRTAG_BMAPIFORMAT))) {
-               XFS_ERROR_REPORT("xfs_bmap_split_extent_at",
-                                XFS_ERRLEVEL_LOW, mp);
+       if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)) ||
+           XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) {
                return -EFSCORRUPTED;
        }
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
-       ifp = XFS_IFORK_PTR(ip, whichfork);
-       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               /* Read in all the extents */
-               error = xfs_iread_extents(tp, ip, whichfork);
-               if (error)
-                       return error;
-       }
+       /* Read in all the extents */
+       error = xfs_iread_extents(tp, ip, whichfork);
+       if (error)
+               return error;
 
        /*
         * If there are not extents, or split_fsb lies in a hole we are done.
@@ -5922,13 +5997,16 @@ xfs_bmap_split_extent_at(
        new.br_blockcount = got.br_blockcount - gotblkcnt;
        new.br_state = got.br_state;
 
-       if (ifp->if_flags & XFS_IFBROOT) {
+       if (ifp->if_format == XFS_DINODE_FMT_BTREE) {
                cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
-               cur->bc_private.b.flags = 0;
+               cur->bc_ino.flags = 0;
                error = xfs_bmbt_lookup_eq(cur, &got, &i);
                if (error)
                        goto del_cursor;
-               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor);
+               if (XFS_IS_CORRUPT(mp, i != 1)) {
+                       error = -EFSCORRUPTED;
+                       goto del_cursor;
+               }
        }
 
        got.br_blockcount = gotblkcnt;
@@ -5946,18 +6024,23 @@ xfs_bmap_split_extent_at(
        /* Add new extent */
        xfs_iext_next(ifp, &icur);
        xfs_iext_insert(ip, &icur, &new, 0);
-       XFS_IFORK_NEXT_SET(ip, whichfork,
-                          XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+       ifp->if_nextents++;
 
        if (cur) {
                error = xfs_bmbt_lookup_eq(cur, &new, &i);
                if (error)
                        goto del_cursor;
-               XFS_WANT_CORRUPTED_GOTO(mp, i == 0, del_cursor);
+               if (XFS_IS_CORRUPT(mp, i != 0)) {
+                       error = -EFSCORRUPTED;
+                       goto del_cursor;
+               }
                error = xfs_btree_insert(cur, &i);
                if (error)
                        goto del_cursor;
-               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor);
+               if (XFS_IS_CORRUPT(mp, i != 1)) {
+                       error = -EFSCORRUPTED;
+                       goto del_cursor;
+               }
        }
 
        /*
@@ -5974,7 +6057,7 @@ xfs_bmap_split_extent_at(
 
 del_cursor:
        if (cur) {
-               cur->bc_private.b.allocated = 0;
+               cur->bc_ino.allocated = 0;
                xfs_btree_del_cursor(cur, error);
        }
 
@@ -5983,34 +6066,6 @@ del_cursor:
        return error;
 }
 
-int
-xfs_bmap_split_extent(
-       struct xfs_inode        *ip,
-       xfs_fileoff_t           split_fsb)
-{
-       struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_trans        *tp;
-       int                     error;
-
-       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write,
-                       XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, 0, &tp);
-       if (error)
-               return error;
-
-       xfs_ilock(ip, XFS_ILOCK_EXCL);
-       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-
-       error = xfs_bmap_split_extent_at(tp, ip, split_fsb);
-       if (error)
-               goto out;
-
-       return xfs_trans_commit(tp);
-
-out:
-       xfs_trans_cancel(tp);
-       return error;
-}
-
 /* Deferred mapping is only for real extents in the data fork. */
 static bool
 xfs_bmap_is_update_needed(
@@ -6040,7 +6095,7 @@ __xfs_bmap_add(
                        bmap->br_blockcount,
                        bmap->br_state);
 
-       bi = kmem_alloc(sizeof(struct xfs_bmap_intent), KM_NOFS);
+       bi = kmem_cache_alloc(xfs_bmap_intent_cache, GFP_NOFS | __GFP_NOFAIL);
        INIT_LIST_HEAD(&bi->bi_list);
        bi->bi_type = type;
        bi->bi_owner = ip;
@@ -6134,26 +6189,37 @@ xfs_bmap_validate_extent(
        struct xfs_bmbt_irec    *irec)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       xfs_fsblock_t           endfsb;
-       bool                    isrt;
 
-       isrt = XFS_IS_REALTIME_INODE(ip);
-       endfsb = irec->br_startblock + irec->br_blockcount - 1;
-       if (isrt) {
-               if (!xfs_verify_rtbno(mp, irec->br_startblock))
-                       return __this_address;
-               if (!xfs_verify_rtbno(mp, endfsb))
+       if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
+               return __this_address;
+
+       if (XFS_IS_REALTIME_INODE(ip) && whichfork == XFS_DATA_FORK) {
+               if (!xfs_verify_rtext(mp, irec->br_startblock,
+                                         irec->br_blockcount))
                        return __this_address;
        } else {
-               if (!xfs_verify_fsbno(mp, irec->br_startblock))
-                       return __this_address;
-               if (!xfs_verify_fsbno(mp, endfsb))
-                       return __this_address;
-               if (XFS_FSB_TO_AGNO(mp, irec->br_startblock) !=
-                   XFS_FSB_TO_AGNO(mp, endfsb))
+               if (!xfs_verify_fsbext(mp, irec->br_startblock,
+                                          irec->br_blockcount))
                        return __this_address;
        }
        if (irec->br_state != XFS_EXT_NORM && whichfork != XFS_DATA_FORK)
                return __this_address;
        return NULL;
 }
+
+int __init
+xfs_bmap_intent_init_cache(void)
+{
+       xfs_bmap_intent_cache = kmem_cache_create("xfs_bmap_intent",
+                       sizeof(struct xfs_bmap_intent),
+                       0, 0, NULL);
+
+       return xfs_bmap_intent_cache != NULL ? 0 : -ENOMEM;
+}
+
+void
+xfs_bmap_intent_destroy_cache(void)
+{
+       kmem_cache_destroy(xfs_bmap_intent_cache);
+       xfs_bmap_intent_cache = NULL;
+}