* performed with log redo items!
         */
        if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+               int             w       = XFS_DATA_FORK;
+               uint32_t        ipnext  = XFS_IFORK_NEXTENTS(ip, w);
+               uint32_t        tipnext = XFS_IFORK_NEXTENTS(tip, w);
+
+               /*
+                * Conceptually this shouldn't affect the shape of either bmbt,
+                * but since we atomically move extents one by one, we reserve
+                * enough space to rebuild both trees.
+                */
+               resblks = XFS_SWAP_RMAP_SPACE_RES(mp, ipnext, w);
+               resblks +=  XFS_SWAP_RMAP_SPACE_RES(mp, tipnext, w);
+
                /*
-                * Conceptually this shouldn't affect the shape of either
-                * bmbt, but since we atomically move extents one by one,
-                * we reserve enough space to rebuild both trees.
+                * Handle the corner case where either inode might straddle the
+                * btree format boundary. If so, the inode could bounce between
+                * btree <-> extent format on unmap -> remap cycles, freeing and
+                * allocating a bmapbt block each time.
                 */
-               resblks = XFS_SWAP_RMAP_SPACE_RES(mp,
-                               XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK),
-                               XFS_DATA_FORK) +
-                         XFS_SWAP_RMAP_SPACE_RES(mp,
-                               XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK),
-                               XFS_DATA_FORK);
+               if (ipnext == (XFS_IFORK_MAXEXT(ip, w) + 1))
+                       resblks += XFS_IFORK_MAXEXT(ip, w);
+               if (tipnext == (XFS_IFORK_MAXEXT(tip, w) + 1))
+                       resblks += XFS_IFORK_MAXEXT(tip, w);
        }
        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
        if (error)