]> 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 e9c9f45100df0a94b48249ef3b935991b5ce538f..3b1739bdb0ff6d888d3eddd67d8add17e08f3b07 100644 (file)
 #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
@@ -45,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 size of the on-disk extent count,
-        * either a signed 32-bit number for the data fork, or a signed 16-bit
-        * number for the attr fork.
+        * 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 */
@@ -113,7 +121,7 @@ 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);
+       struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
 
        return whichfork != XFS_COW_FORK &&
                ifp->if_format == XFS_DINODE_FMT_EXTENTS &&
@@ -125,7 +133,7 @@ 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);
+       struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
 
        return whichfork != XFS_COW_FORK &&
                ifp->if_format == XFS_DINODE_FMT_BTREE &&
@@ -185,22 +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) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
-       else
-               offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
-
-       ASSERT(offset < XFS_LITINO(mp));
-       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(
@@ -212,8 +213,8 @@ xfs_bmap_forkoff_reset(
            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;
        }
 }
 
@@ -229,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 */
@@ -241,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;
        }
 
@@ -286,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",
@@ -306,12 +307,12 @@ 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_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_btree_block  *block; /* current btree block */
        xfs_fsblock_t           bno;    /* block # of "block" */
        struct xfs_buf          *bp;    /* buffer for "block" */
@@ -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,56 +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_cache_alloc(xfs_bmap_free_item_zone,
-                              GFP_KERNEL | __GFP_NOFAIL);
-       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
  */
@@ -580,7 +531,7 @@ 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 */
@@ -596,7 +547,6 @@ xfs_bmap_btree_to_extents(
 
        ASSERT(cur);
        ASSERT(whichfork != XFS_COW_FORK);
-       ASSERT(ifp->if_flags & XFS_IFEXTENTS);
        ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
        ASSERT(be16_to_cpu(rblock->bb_level) == 1);
        ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
@@ -616,15 +566,14 @@ 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);
        ifp->if_format = XFS_DINODE_FMT_EXTENTS;
        *logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
        return 0;
@@ -660,7 +609,7 @@ xfs_bmap_extents_to_btree(
 
        mp = ip->i_mount;
        ASSERT(whichfork != XFS_COW_FORK);
-       ifp = XFS_IFORK_PTR(ip, whichfork);
+       ifp = xfs_ifork_ptr(ip, whichfork);
        ASSERT(ifp->if_format == XFS_DINODE_FMT_EXTENTS);
 
        /*
@@ -668,7 +617,6 @@ xfs_bmap_extents_to_btree(
         * to expand the root.
         */
        xfs_iroot_realloc(ip, 1, whichfork);
-       ifp->if_flags |= XFS_IFBROOT;
 
        /*
         * Fill in the root.
@@ -719,7 +667,7 @@ xfs_bmap_extents_to_btree(
               args.agno >= XFS_FSB_TO_AGNO(mp, tp->t_firstblock));
        tp->t_firstblock = args.fsbno;
        cur->bc_ino.allocated++;
-       ip->i_d.di_nblocks++;
+       ip->i_nblocks++;
        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
        error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
                        XFS_FSB_TO_DADDR(mp, args.fsbno),
@@ -732,7 +680,7 @@ xfs_bmap_extents_to_btree(
         */
        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);
 
@@ -790,7 +738,7 @@ 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(ifp->if_format == XFS_DINODE_FMT_LOCAL);
@@ -798,8 +746,6 @@ xfs_bmap_local_to_extents_empty(
        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;
        ifp->if_format = XFS_DINODE_FMT_EXTENTS;
@@ -832,7 +778,7 @@ 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);
+       ifp = xfs_ifork_ptr(ip, whichfork);
        ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
 
        if (!ifp->if_bytes) {
@@ -843,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;
@@ -901,7 +846,7 @@ xfs_bmap_local_to_extents(
        xfs_iext_insert(ip, &icur, &rec, 0);
 
        ifp->if_nextents = 1;
-       ip->i_d.di_nblocks = 1;
+       ip->i_nblocks = 1;
        xfs_trans_mod_dquot_byino(tp, ip,
                XFS_TRANS_DQ_BCOUNT, 1L);
        flags |= xfs_ilog_fext(whichfork);
@@ -920,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);
@@ -962,11 +909,11 @@ 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_df.if_nextents * sizeof(struct xfs_bmbt_rec) <=
-           XFS_IFORK_DSIZE(ip))
+           xfs_inode_data_fork_size(ip))
                return 0;
        cur = NULL;
        error = xfs_bmap_extents_to_btree(tp, ip, &cur, 0, flags,
@@ -997,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)) {
@@ -1020,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)
 {
+       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:
@@ -1065,39 +1016,26 @@ 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))
+       if (xfs_inode_has_attr_fork(ip))
                goto trans_cancel;
 
-       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_cache_zalloc(xfs_ifork_zone,
-                                     GFP_KERNEL | __GFP_NOFAIL);
-
-       ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS;
-       ip->i_afp->if_flags = XFS_IFEXTENTS;
+       xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);
        logflags = 0;
        switch (ip->i_df.if_format) {
        case XFS_DINODE_FMT_LOCAL:
@@ -1117,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);
@@ -1170,7 +1108,7 @@ xfs_iread_bmbt_block(
        xfs_extnum_t            num_recs;
        xfs_extnum_t            j;
        int                     whichfork = cur->bc_ino.whichfork;
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
 
        block = xfs_btree_get_block(cur, level, &bp);
 
@@ -1218,17 +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 (XFS_IS_CORRUPT(mp, ifp->if_format != XFS_DINODE_FMT_BTREE)) {
-               error = -EFSCORRUPTED;
-               goto out;
-       }
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        ir.loaded = 0;
        xfs_iext_first(ifp, &ir.icur);
@@ -1244,8 +1180,6 @@ xfs_iread_extents(
                goto out;
        }
        ASSERT(ir.loaded == xfs_iext_count(ifp));
-
-       ifp->if_flags |= XFS_IFEXTENTS;
        return 0;
 out:
        xfs_iext_destroy(ifp);
@@ -1266,7 +1200,7 @@ 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;
@@ -1280,11 +1214,9 @@ xfs_bmap_first_unused(
 
        ASSERT(xfs_ifork_has_extents(ifp));
 
-       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;
 
        lowest = max = *first_unused;
        for_each_xfs_iext(ifp, &icur, &got) {
@@ -1315,7 +1247,7 @@ 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;
@@ -1332,11 +1264,9 @@ xfs_bmap_last_before(
                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;
@@ -1351,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))
@@ -1419,7 +1347,7 @@ xfs_bmap_last_offset(
        xfs_fileoff_t           *last_block,
        int                     whichfork)
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_bmbt_irec    rec;
        int                     is_empty;
        int                     error;
@@ -1440,38 +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(
-       struct xfs_inode        *ip,            /* incore inode */
-       int                     whichfork)      /* data or attr fork */
-{
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
-       int                     rval;           /* return value */
-       struct xfs_bmbt_irec    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 (ifp->if_nextents != 1)
-               return 0;
-       if (ifp->if_format != XFS_DINODE_FMT_EXTENTS)
-               return 0;
-       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.
  */
@@ -1485,7 +1381,7 @@ xfs_bmap_add_extent_delay_real(
        int                     whichfork)
 {
        struct xfs_mount        *mp = bma->ip->i_mount;
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
+       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 */
@@ -1493,7 +1389,7 @@ xfs_bmap_add_extent_delay_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);
        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 */
@@ -1546,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;
 
        /*
@@ -1564,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;
@@ -2032,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 */
@@ -2044,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));
 
@@ -2094,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;
 
        /*
@@ -2112,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;
 
        /*
@@ -2573,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));
 
        /*
@@ -2604,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;
 
        /*
@@ -2710,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 */
@@ -2720,7 +2616,7 @@ 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));
@@ -2755,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;
@@ -2939,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(
@@ -3000,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
@@ -3098,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
@@ -3281,7 +3177,8 @@ 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);
+               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) {
@@ -3445,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;
@@ -3456,35 +3353,17 @@ 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;
@@ -3494,13 +3373,172 @@ xfs_bmap_btalloc(
        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;
+}
+
+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;
+
+       nullfb = ap->tp->t_firstblock == NULLFSBLOCK;
+
+       /*
+        * check the allocation happened at the same or higher AG than
+        * the first block that was allocated.
+        */
+       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;
+       /*
+        * 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,
@@ -3531,9 +3569,6 @@ xfs_bmap_btalloc(
         * 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;
 
@@ -3564,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
@@ -3680,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;
@@ -3763,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) {
@@ -3808,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;
 
@@ -3861,11 +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;
        int                     whichfork = xfs_bmapi_whichfork(flags);
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_bmbt_irec    got;
        xfs_fileoff_t           obno;
        xfs_fileoff_t           end;
@@ -3885,16 +3879,14 @@ xfs_bmapi_read(
            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);
 
-       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;
@@ -3960,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;
@@ -3970,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)
@@ -3994,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;
 
@@ -4041,8 +4032,7 @@ 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;
 }
 
@@ -4076,6 +4066,10 @@ xfs_bmap_alloc_userdata(
                        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);
 }
 
@@ -4085,7 +4079,7 @@ xfs_bmapi_allocate(
 {
        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;
 
@@ -4101,7 +4095,7 @@ xfs_bmapi_allocate(
                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);
@@ -4112,10 +4106,15 @@ xfs_bmapi_allocate(
        else
                bma->minlen = 1;
 
-       if (bma->flags & XFS_BMAPI_METADATA)
-               error = xfs_bmap_btalloc(bma);
-       else
+       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;
 
@@ -4125,7 +4124,7 @@ xfs_bmapi_allocate(
                        return error;
        }
 
-       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
@@ -4176,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;
 
@@ -4198,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);
        }
@@ -4256,7 +4255,7 @@ xfs_bmapi_minleft(
        struct xfs_inode        *ip,
        int                     fork)
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, fork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, fork);
 
        if (tp && tp->t_firstblock != NULLFSBLOCK)
                return 0;
@@ -4277,7 +4276,7 @@ xfs_bmapi_finish(
        int                     whichfork,
        int                     error)
 {
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(bma->ip, whichfork);
 
        if ((bma->logflags & xfs_ilog_fext(whichfork)) &&
            ifp->if_format != XFS_DINODE_FMT_EXTENTS)
@@ -4304,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 */
@@ -4316,7 +4315,7 @@ xfs_bmapi_write(
        };
        struct xfs_mount        *mp = ip->i_mount;
        int                     whichfork = xfs_bmapi_whichfork(flags);
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       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 */
@@ -4362,16 +4361,14 @@ xfs_bmapi_write(
                return -EFSCORRUPTED;
        }
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
        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;
@@ -4418,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;
 
@@ -4499,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 };
@@ -4520,14 +4517,16 @@ xfs_bmapi_convert_delalloc(
                return error;
 
        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;
 
-       xfs_trans_ijoin(tp, ip, 0);
-
        if (!xfs_iext_lookup_extent(ip, ifp, offset_fsb, &bma.icur, &bma.got) ||
            bma.got.br_startoff > offset_fsb) {
                /*
@@ -4545,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;
        }
@@ -4554,7 +4554,8 @@ 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);
 
        /*
@@ -4592,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)
@@ -4623,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;
@@ -4633,9 +4635,9 @@ 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)));
@@ -4647,14 +4649,12 @@ xfs_bmapi_remap(
                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. */
@@ -4662,10 +4662,10 @@ 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_ino.flags = 0;
        }
@@ -4792,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;
 
@@ -4825,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;
@@ -4920,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);
 
@@ -4992,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 */
@@ -5012,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);
@@ -5145,26 +5144,6 @@ xfs_bmap_del_extent_real(
                 * Deleting the middle of the extent.
                 */
 
-               /*
-                * For directories, -ENOSPC is returned since a directory entry
-                * remove operation must not fail due to low extent count
-                * availability. -ENOSPC will be handled by higher layers of XFS
-                * by letting the corresponding empty Data/Free blocks to linger
-                * until a future remove operation. Dabtree blocks would be
-                * swapped with the last block in the leaf space and then the
-                * new last block will be unmapped.
-                *
-                * The above logic also applies to the source directory entry of
-                * a rename operation.
-                */
-               error = xfs_iext_count_may_overflow(ip, whichfork, 1);
-               if (error) {
-                       ASSERT(S_ISDIR(VFS_I(ip)->i_mode) &&
-                               whichfork == XFS_DATA_FORK);
-                       error = -ENOSPC;
-                       goto done;
-               }
-
                old = got;
 
                got.br_blockcount = del->br_startoff - got.br_startoff;
@@ -5243,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);
@@ -5254,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.
         */
@@ -5278,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 */
@@ -5296,8 +5275,6 @@ __xfs_bunmapi(
        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;
@@ -5306,29 +5283,20 @@ __xfs_bunmapi(
 
        whichfork = xfs_bmapi_whichfork(flags);
        ASSERT(whichfork != XFS_COW_FORK);
-       ifp = XFS_IFORK_PTR(ip, whichfork);
+       ifp = xfs_ifork_ptr(ip, whichfork);
        if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ifp)))
                return -EFSCORRUPTED;
-       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;
@@ -5344,7 +5312,7 @@ __xfs_bunmapi(
        end--;
 
        logflags = 0;
-       if (ifp->if_flags & XFS_IFBROOT) {
+       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_ino.flags = 0;
@@ -5363,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.
@@ -5388,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 && !isrt) {
-                       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;
@@ -5407,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;
 
@@ -5550,7 +5500,6 @@ delete:
                if (error)
                        goto error0;
 
-               max_len -= del.br_blockcount;
                end = del.br_startoff - 1;
 nodelete:
                /*
@@ -5616,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)
 {
@@ -5648,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;
@@ -5675,7 +5624,7 @@ xfs_bmse_merge(
        struct xfs_btree_cur            *cur,
        int                             *logflags)      /* output */
 {
-       struct xfs_ifork                *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_ifork                *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_bmbt_irec            new;
        xfs_filblks_t                   blockcount;
        int                             error, i;
@@ -5796,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;
@@ -5809,18 +5758,16 @@ xfs_bmap_collapse_extents(
                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_ino.flags = 0;
        }
@@ -5889,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);
@@ -5913,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;
@@ -5926,18 +5873,16 @@ xfs_bmap_insert_extents(
                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_ino.flags = 0;
        }
@@ -6015,7 +5960,7 @@ xfs_bmap_split_extent(
        xfs_fileoff_t           split_fsb)
 {
        int                             whichfork = XFS_DATA_FORK;
-       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;
        struct xfs_bmbt_irec            new; /* split extent */
@@ -6031,15 +5976,13 @@ xfs_bmap_split_extent(
                return -EFSCORRUPTED;
        }
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       if (xfs_is_shutdown(mp))
                return -EIO;
 
-       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.
@@ -6054,7 +5997,7 @@ xfs_bmap_split_extent(
        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_ino.flags = 0;
                error = xfs_bmbt_lookup_eq(cur, &got, &i);
@@ -6152,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;
@@ -6263,3 +6206,20 @@ xfs_bmap_validate_extent(
                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;
+}