diff options
author | Christoph Hellwig <hch@lst.de> | 2017-11-03 10:34:43 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2017-11-06 11:53:40 -0800 |
commit | b2b1712a640824e7c131bfdd2585d57bf8ccb39a (patch) | |
tree | ad756c7caa0bb7252aaf444b077c518e0a5d9f0f /fs/xfs/libxfs/xfs_bmap.c | |
parent | 906abed501bf5a2103946deb7a4a40b31c56f027 (diff) | |
download | lwn-b2b1712a640824e7c131bfdd2585d57bf8ccb39a.tar.gz lwn-b2b1712a640824e7c131bfdd2585d57bf8ccb39a.zip |
xfs: introduce the xfs_iext_cursor abstraction
Add a new xfs_iext_cursor structure to hide the direct extent map
index manipulations. In addition to the existing lookup/get/insert/
remove and update routines new primitives to get the first and last
extent cursor, as well as moving up and down by one extent are
provided. Also new are convenience to increment/decrement the
cursor and retreive the new extent, as well as to peek into the
previous/next extent without updating the cursor and last but not
least a macro to iterate over all extents in a fork.
[darrick: rename for_each_iext to for_each_xfs_iext]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs/libxfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 441 |
1 files changed, 212 insertions, 229 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index f4d0639dc4ae..e48fc5c6fcdf 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -672,8 +672,9 @@ xfs_bmap_extents_to_btree( xfs_bmbt_key_t *kp; /* root block key pointer */ xfs_mount_t *mp; /* mount structure */ xfs_bmbt_ptr_t *pp; /* root block address pointer */ + struct xfs_iext_cursor icur; struct xfs_bmbt_irec rec; - xfs_extnum_t i = 0, cnt = 0; + xfs_extnum_t cnt = 0; mp = ip->i_mount; ASSERT(whichfork != XFS_COW_FORK); @@ -752,7 +753,7 @@ xfs_bmap_extents_to_btree( XFS_BTNUM_BMAP, 0, 0, ip->i_ino, XFS_BTREE_LONG_PTRS); - while (xfs_iext_get_extent(ifp, i++, &rec)) { + for_each_xfs_iext(ifp, &icur, &rec) { if (isnullstartblock(rec.br_startblock)) continue; arp = XFS_BMBT_REC_ADDR(mp, ablock, 1 + cnt); @@ -828,6 +829,7 @@ xfs_bmap_local_to_extents( xfs_alloc_arg_t args; /* allocation arguments */ xfs_buf_t *bp; /* buffer for extent block */ struct xfs_bmbt_irec rec; + struct xfs_iext_cursor icur; /* * We don't want to deal with the case of keeping inode data inline yet. @@ -894,7 +896,8 @@ xfs_bmap_local_to_extents( rec.br_startblock = args.fsbno; rec.br_blockcount = 1; rec.br_state = XFS_EXT_NORM; - xfs_iext_insert(ip, 0, 1, &rec, 0); + xfs_iext_first(ifp, &icur); + xfs_iext_insert(ip, &icur, 1, &rec, 0); XFS_IFORK_NEXT_SET(ip, whichfork, 1); ip->i_d.di_nblocks = 1; @@ -1174,6 +1177,7 @@ xfs_iread_extents( struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); xfs_extnum_t nextents = XFS_IFORK_NEXTENTS(ip, whichfork); struct xfs_btree_block *block = ifp->if_broot; + struct xfs_iext_cursor icur; xfs_fsblock_t bno; struct xfs_buf *bp; xfs_extnum_t i, j; @@ -1223,6 +1227,7 @@ xfs_iread_extents( * Here with bp and block set to the leftmost leaf node in the tree. */ i = 0; + xfs_iext_first(ifp, &icur); /* * Loop over all leaf nodes. Copy information to the extent records. @@ -1264,7 +1269,8 @@ xfs_iread_extents( } trp->l0 = be64_to_cpu(frp->l0); trp->l1 = be64_to_cpu(frp->l1); - trace_xfs_read_extent(ip, i, state, _THIS_IP_); + trace_xfs_read_extent(ip, &icur, state, _THIS_IP_); + xfs_iext_next(ifp, &icur); } xfs_trans_brelse(tp, bp); bno = nextbno; @@ -1312,7 +1318,7 @@ xfs_bmap_first_unused( { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_bmbt_irec got; - xfs_extnum_t idx = 0; + struct xfs_iext_cursor icur; xfs_fileoff_t lastaddr = 0; xfs_fileoff_t lowest, max; int error; @@ -1333,7 +1339,7 @@ xfs_bmap_first_unused( } lowest = max = *first_unused; - while (xfs_iext_get_extent(ifp, idx++, &got)) { + for_each_xfs_iext(ifp, &icur, &got) { /* * See if the hole before this extent will work. */ @@ -1363,7 +1369,7 @@ xfs_bmap_last_before( { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_bmbt_irec got; - xfs_extnum_t idx; + struct xfs_iext_cursor icur; int error; switch (XFS_IFORK_FORMAT(ip, whichfork)) { @@ -1383,7 +1389,7 @@ xfs_bmap_last_before( return error; } - if (!xfs_iext_lookup_extent_before(ip, ifp, last_block, &idx, &got)) + if (!xfs_iext_lookup_extent_before(ip, ifp, last_block, &icur, &got)) *last_block = 0; return 0; } @@ -1397,8 +1403,8 @@ xfs_bmap_last_extent( int *is_empty) { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); + struct xfs_iext_cursor icur; int error; - int nextents; if (!(ifp->if_flags & XFS_IFEXTENTS)) { error = xfs_iread_extents(tp, ip, whichfork); @@ -1406,14 +1412,11 @@ xfs_bmap_last_extent( return error; } - nextents = xfs_iext_count(ifp); - if (nextents == 0) { + xfs_iext_last(ifp, &icur); + if (!xfs_iext_get_extent(ifp, &icur, rec)) *is_empty = 1; - return 0; - } - - xfs_iext_get_extent(ifp, nextents - 1, rec); - *is_empty = 0; + else + *is_empty = 0; return 0; } @@ -1501,6 +1504,7 @@ xfs_bmap_one_block( xfs_ifork_t *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) @@ -1512,7 +1516,8 @@ xfs_bmap_one_block( return 0; ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(ifp->if_flags & XFS_IFEXTENTS); - xfs_iext_get_extent(ifp, 0, &s); + 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); @@ -1554,8 +1559,6 @@ xfs_bmap_add_extent_delay_real( nextents = (whichfork == XFS_COW_FORK ? &bma->ip->i_cnextents : &bma->ip->i_d.di_nextents); - ASSERT(bma->idx >= 0); - ASSERT(bma->idx <= xfs_iext_count(ifp)); ASSERT(!isnullstartblock(new->br_startblock)); ASSERT(!bma->cur || (bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); @@ -1569,7 +1572,7 @@ xfs_bmap_add_extent_delay_real( /* * Set up a bunch of variables to make the tests simpler. */ - xfs_iext_get_extent(ifp, bma->idx, &PREV); + xfs_iext_get_extent(ifp, &bma->icur, &PREV); new_endoff = new->br_startoff + new->br_blockcount; ASSERT(isnullstartblock(PREV.br_startblock)); ASSERT(PREV.br_startoff <= new->br_startoff); @@ -1591,10 +1594,8 @@ xfs_bmap_add_extent_delay_real( * Check and set flags if this segment has a left neighbor. * Don't set contiguous if the combined extent would be too large. */ - if (bma->idx > 0) { + if (xfs_iext_peek_prev_extent(ifp, &bma->icur, &LEFT)) { state |= BMAP_LEFT_VALID; - xfs_iext_get_extent(ifp, bma->idx - 1, &LEFT); - if (isnullstartblock(LEFT.br_startblock)) state |= BMAP_LEFT_DELAY; } @@ -1611,10 +1612,8 @@ xfs_bmap_add_extent_delay_real( * Don't set contiguous if the combined extent would be too large. * Also check for all-three-contiguous being too large. */ - if (bma->idx < xfs_iext_count(ifp) - 1) { + if (xfs_iext_peek_next_extent(ifp, &bma->icur, &RIGHT)) { state |= BMAP_RIGHT_VALID; - xfs_iext_get_extent(ifp, bma->idx + 1, &RIGHT); - if (isnullstartblock(RIGHT.br_startblock)) state |= BMAP_RIGHT_DELAY; } @@ -1646,9 +1645,9 @@ xfs_bmap_add_extent_delay_real( */ LEFT.br_blockcount += PREV.br_blockcount + RIGHT.br_blockcount; - xfs_iext_remove(bma->ip, bma->idx, 2, state); - bma->idx--; - xfs_iext_update_extent(bma->ip, state, bma->idx, &LEFT); + xfs_iext_remove(bma->ip, &bma->icur, 2, state); + xfs_iext_prev(ifp, &bma->icur); + xfs_iext_update_extent(bma->ip, state, &bma->icur, &LEFT); (*nextents)--; if (bma->cur == NULL) @@ -1681,9 +1680,9 @@ xfs_bmap_add_extent_delay_real( old = LEFT; LEFT.br_blockcount += PREV.br_blockcount; - xfs_iext_remove(bma->ip, bma->idx, 1, state); - bma->idx--; - xfs_iext_update_extent(bma->ip, state, bma->idx, &LEFT); + xfs_iext_remove(bma->ip, &bma->icur, 1, state); + xfs_iext_prev(ifp, &bma->icur); + xfs_iext_update_extent(bma->ip, state, &bma->icur, &LEFT); if (bma->cur == NULL) rval = XFS_ILOG_DEXT; @@ -1707,10 +1706,10 @@ xfs_bmap_add_extent_delay_real( PREV.br_startblock = new->br_startblock; PREV.br_blockcount += RIGHT.br_blockcount; - bma->idx++; - xfs_iext_remove(bma->ip, bma->idx, 1, state); - bma->idx--; - xfs_iext_update_extent(bma->ip, state, bma->idx, &PREV); + xfs_iext_next(ifp, &bma->icur); + xfs_iext_remove(bma->ip, &bma->icur, 1, state); + xfs_iext_prev(ifp, &bma->icur); + xfs_iext_update_extent(bma->ip, state, &bma->icur, &PREV); if (bma->cur == NULL) rval = XFS_ILOG_DEXT; @@ -1734,7 +1733,7 @@ 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->idx, &PREV); + xfs_iext_update_extent(bma->ip, state, &bma->icur, &PREV); (*nextents)++; if (bma->cur == NULL) @@ -1768,9 +1767,9 @@ xfs_bmap_add_extent_delay_real( PREV.br_startoff += new->br_blockcount; PREV.br_startblock = nullstartblock(da_new); - xfs_iext_update_extent(bma->ip, state, bma->idx, &PREV); - bma->idx--; - xfs_iext_update_extent(bma->ip, state, bma->idx, &LEFT); + xfs_iext_update_extent(bma->ip, state, &bma->icur, &PREV); + xfs_iext_prev(ifp, &bma->icur); + xfs_iext_update_extent(bma->ip, state, &bma->icur, &LEFT); if (bma->cur == NULL) rval = XFS_ILOG_DEXT; @@ -1784,7 +1783,6 @@ xfs_bmap_add_extent_delay_real( if (error) goto done; } - break; case BMAP_LEFT_FILLING: @@ -1792,7 +1790,7 @@ xfs_bmap_add_extent_delay_real( * Filling in the first part of a previous delayed allocation. * The left neighbor is not contiguous. */ - xfs_iext_update_extent(bma->ip, state, bma->idx, new); + xfs_iext_update_extent(bma->ip, state, &bma->icur, new); (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1825,7 +1823,9 @@ xfs_bmap_add_extent_delay_real( PREV.br_startoff = new_endoff; PREV.br_blockcount = temp; PREV.br_startblock = nullstartblock(da_new); - xfs_iext_insert(bma->ip, bma->idx + 1, 1, &PREV, state); + xfs_iext_next(ifp, &bma->icur); + xfs_iext_insert(bma->ip, &bma->icur, 1, &PREV, state); + xfs_iext_prev(ifp, &bma->icur); break; case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: @@ -1858,9 +1858,9 @@ xfs_bmap_add_extent_delay_real( PREV.br_blockcount = temp; PREV.br_startblock = nullstartblock(da_new); - xfs_iext_update_extent(bma->ip, state, bma->idx, &PREV); - bma->idx++; - xfs_iext_update_extent(bma->ip, state, bma->idx, &RIGHT); + xfs_iext_update_extent(bma->ip, state, &bma->icur, &PREV); + xfs_iext_next(ifp, &bma->icur); + xfs_iext_update_extent(bma->ip, state, &bma->icur, &RIGHT); break; case BMAP_RIGHT_FILLING: @@ -1868,7 +1868,7 @@ xfs_bmap_add_extent_delay_real( * Filling in the last part of a previous delayed allocation. * The right neighbor is not contiguous. */ - xfs_iext_update_extent(bma->ip, state, bma->idx, new); + xfs_iext_update_extent(bma->ip, state, &bma->icur, new); (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; @@ -1900,9 +1900,8 @@ xfs_bmap_add_extent_delay_real( PREV.br_startblock = nullstartblock(da_new); PREV.br_blockcount = temp; - xfs_iext_insert(bma->ip, bma->idx, 1, &PREV, state); - - bma->idx++; + xfs_iext_insert(bma->ip, &bma->icur, 1, &PREV, state); + xfs_iext_next(ifp, &bma->icur); break; case 0: @@ -1945,10 +1944,11 @@ xfs_bmap_add_extent_delay_real( PREV.br_startblock = nullstartblock(xfs_bmap_worst_indlen(bma->ip, PREV.br_blockcount)); - xfs_iext_update_extent(bma->ip, state, bma->idx, &PREV); + xfs_iext_update_extent(bma->ip, state, &bma->icur, &PREV); /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ - xfs_iext_insert(bma->ip, bma->idx + 1, 2, &LEFT, state); + xfs_iext_next(ifp, &bma->icur); + xfs_iext_insert(bma->ip, &bma->icur, 2, &LEFT, state); (*nextents)++; if (bma->cur == NULL) @@ -1976,7 +1976,6 @@ xfs_bmap_add_extent_delay_real( da_new = startblockval(PREV.br_startblock) + startblockval(RIGHT.br_startblock); - bma->idx++; break; case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: @@ -2040,7 +2039,7 @@ xfs_bmap_add_extent_unwritten_real( struct xfs_trans *tp, xfs_inode_t *ip, /* incore inode pointer */ int whichfork, - xfs_extnum_t *idx, /* extent number to update/insert */ + struct xfs_iext_cursor *icur, xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ @@ -2064,8 +2063,6 @@ xfs_bmap_add_extent_unwritten_real( cur = *curp; ifp = XFS_IFORK_PTR(ip, whichfork); - ASSERT(*idx >= 0); - ASSERT(*idx <= xfs_iext_count(ifp)); ASSERT(!isnullstartblock(new->br_startblock)); XFS_STATS_INC(mp, xs_add_exlist); @@ -2078,7 +2075,7 @@ xfs_bmap_add_extent_unwritten_real( * Set up a bunch of variables to make the tests simpler. */ error = 0; - xfs_iext_get_extent(ifp, *idx, &PREV); + xfs_iext_get_extent(ifp, icur, &PREV); ASSERT(new->br_state != PREV.br_state); new_endoff = new->br_startoff + new->br_blockcount; ASSERT(PREV.br_startoff <= new->br_startoff); @@ -2097,10 +2094,8 @@ xfs_bmap_add_extent_unwritten_real( * Check and set flags if this segment has a left neighbor. * Don't set contiguous if the combined extent would be too large. */ - if (*idx > 0) { + if (xfs_iext_peek_prev_extent(ifp, icur, &LEFT)) { state |= BMAP_LEFT_VALID; - xfs_iext_get_extent(ifp, *idx - 1, &LEFT); - if (isnullstartblock(LEFT.br_startblock)) state |= BMAP_LEFT_DELAY; } @@ -2117,9 +2112,8 @@ xfs_bmap_add_extent_unwritten_real( * Don't set contiguous if the combined extent would be too large. * Also check for all-three-contiguous being too large. */ - if (*idx < xfs_iext_count(ifp) - 1) { + if (xfs_iext_peek_next_extent(ifp, icur, &RIGHT)) { state |= BMAP_RIGHT_VALID; - xfs_iext_get_extent(ifp, *idx + 1, &RIGHT); if (isnullstartblock(RIGHT.br_startblock)) state |= BMAP_RIGHT_DELAY; } @@ -2150,9 +2144,9 @@ xfs_bmap_add_extent_unwritten_real( */ LEFT.br_blockcount += PREV.br_blockcount + RIGHT.br_blockcount; - xfs_iext_remove(ip, *idx, 2, state); - --*idx; - xfs_iext_update_extent(ip, state, *idx, &LEFT); + xfs_iext_remove(ip, icur, 2, 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); if (cur == NULL) @@ -2188,9 +2182,9 @@ xfs_bmap_add_extent_unwritten_real( */ LEFT.br_blockcount += PREV.br_blockcount; - xfs_iext_remove(ip, *idx, 1, state); - --*idx; - xfs_iext_update_extent(ip, state, *idx, &LEFT); + xfs_iext_remove(ip, icur, 1, 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); if (cur == NULL) @@ -2221,10 +2215,10 @@ xfs_bmap_add_extent_unwritten_real( PREV.br_blockcount += RIGHT.br_blockcount; PREV.br_state = new->br_state; - ++*idx; - xfs_iext_remove(ip, *idx, 1, state); - --*idx; - xfs_iext_update_extent(ip, state, *idx, &PREV); + xfs_iext_next(ifp, icur); + xfs_iext_remove(ip, icur, 1, state); + xfs_iext_prev(ifp, icur); + xfs_iext_update_extent(ip, state, icur, &PREV); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) - 1); @@ -2255,7 +2249,7 @@ xfs_bmap_add_extent_unwritten_real( * the new one. */ PREV.br_state = new->br_state; - xfs_iext_update_extent(ip, state, *idx, &PREV); + xfs_iext_update_extent(ip, state, icur, &PREV); if (cur == NULL) rval = XFS_ILOG_DEXT; @@ -2283,9 +2277,9 @@ xfs_bmap_add_extent_unwritten_real( PREV.br_startblock += new->br_blockcount; PREV.br_blockcount -= new->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, &PREV); - --*idx; - xfs_iext_update_extent(ip, state, *idx, &LEFT); + xfs_iext_update_extent(ip, state, icur, &PREV); + xfs_iext_prev(ifp, icur); + xfs_iext_update_extent(ip, state, icur, &LEFT); if (cur == NULL) rval = XFS_ILOG_DEXT; @@ -2317,8 +2311,8 @@ xfs_bmap_add_extent_unwritten_real( PREV.br_startblock += new->br_blockcount; PREV.br_blockcount -= new->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, &PREV); - xfs_iext_insert(ip, *idx, 1, new, state); + xfs_iext_update_extent(ip, state, icur, &PREV); + xfs_iext_insert(ip, icur, 1, new, state); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); if (cur == NULL) @@ -2351,9 +2345,9 @@ xfs_bmap_add_extent_unwritten_real( RIGHT.br_startblock = new->br_startblock; RIGHT.br_blockcount += new->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, &PREV); - ++*idx; - xfs_iext_update_extent(ip, state, *idx, &RIGHT); + xfs_iext_update_extent(ip, state, icur, &PREV); + xfs_iext_next(ifp, icur); + xfs_iext_update_extent(ip, state, icur, &RIGHT); if (cur == NULL) rval = XFS_ILOG_DEXT; @@ -2383,9 +2377,9 @@ xfs_bmap_add_extent_unwritten_real( old = PREV; PREV.br_blockcount -= new->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, &PREV); - ++*idx; - xfs_iext_insert(ip, *idx, 1, new, state); + xfs_iext_update_extent(ip, state, icur, &PREV); + xfs_iext_next(ifp, icur); + xfs_iext_insert(ip, icur, 1, new, state); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); @@ -2426,9 +2420,9 @@ xfs_bmap_add_extent_unwritten_real( r[1].br_startblock = new->br_startblock + new->br_blockcount; r[1].br_state = PREV.br_state; - xfs_iext_update_extent(ip, state, *idx, &PREV); - ++*idx; - xfs_iext_insert(ip, *idx, 2, &r[0], state); + xfs_iext_update_extent(ip, state, icur, &PREV); + xfs_iext_next(ifp, icur); + xfs_iext_insert(ip, icur, 2, &r[0], state); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 2); @@ -2517,7 +2511,7 @@ STATIC void xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ int whichfork, - xfs_extnum_t *idx, /* extent number to update/insert */ + struct xfs_iext_cursor *icur, xfs_bmbt_irec_t *new) /* new data to add to file extents */ { xfs_ifork_t *ifp; /* inode fork pointer */ @@ -2534,10 +2528,8 @@ xfs_bmap_add_extent_hole_delay( /* * Check and set flags if this segment has a left neighbor */ - if (*idx > 0) { + if (xfs_iext_peek_prev_extent(ifp, icur, &left)) { state |= BMAP_LEFT_VALID; - xfs_iext_get_extent(ifp, *idx - 1, &left); - if (isnullstartblock(left.br_startblock)) state |= BMAP_LEFT_DELAY; } @@ -2546,10 +2538,8 @@ xfs_bmap_add_extent_hole_delay( * Check and set flags if the current (right) segment exists. * If it doesn't exist, we're converting the hole at end-of-file. */ - if (*idx < xfs_iext_count(ifp)) { + if (xfs_iext_get_extent(ifp, icur, &right)) { state |= BMAP_RIGHT_VALID; - xfs_iext_get_extent(ifp, *idx, &right); - if (isnullstartblock(right.br_startblock)) state |= BMAP_RIGHT_DELAY; } @@ -2592,9 +2582,9 @@ xfs_bmap_add_extent_hole_delay( left.br_startblock = nullstartblock(newlen); left.br_blockcount = temp; - xfs_iext_remove(ip, *idx, 1, state); - --*idx; - xfs_iext_update_extent(ip, state, *idx, &left); + xfs_iext_remove(ip, icur, 1, state); + xfs_iext_prev(ifp, icur); + xfs_iext_update_extent(ip, state, icur, &left); break; case BMAP_LEFT_CONTIG: @@ -2612,8 +2602,8 @@ xfs_bmap_add_extent_hole_delay( left.br_blockcount = temp; left.br_startblock = nullstartblock(newlen); - --*idx; - xfs_iext_update_extent(ip, state, *idx, &left); + xfs_iext_prev(ifp, icur); + xfs_iext_update_extent(ip, state, icur, &left); break; case BMAP_RIGHT_CONTIG: @@ -2630,7 +2620,7 @@ xfs_bmap_add_extent_hole_delay( right.br_startoff = new->br_startoff; right.br_startblock = nullstartblock(newlen); right.br_blockcount = temp; - xfs_iext_update_extent(ip, state, *idx, &right); + xfs_iext_update_extent(ip, state, icur, &right); break; case 0: @@ -2640,7 +2630,7 @@ xfs_bmap_add_extent_hole_delay( * Insert a new entry. */ oldlen = newlen = 0; - xfs_iext_insert(ip, *idx, 1, new, state); + xfs_iext_insert(ip, icur, 1, new, state); break; } if (oldlen != newlen) { @@ -2661,7 +2651,7 @@ xfs_bmap_add_extent_hole_real( struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, - xfs_extnum_t *idx, + struct xfs_iext_cursor *icur, struct xfs_btree_cur **curp, struct xfs_bmbt_irec *new, xfs_fsblock_t *first, @@ -2679,8 +2669,6 @@ xfs_bmap_add_extent_hole_real( int state = xfs_bmap_fork_to_state(whichfork); struct xfs_bmbt_irec old; - ASSERT(*idx >= 0); - ASSERT(*idx <= xfs_iext_count(ifp)); ASSERT(!isnullstartblock(new->br_startblock)); ASSERT(!cur || !(cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); @@ -2689,9 +2677,8 @@ xfs_bmap_add_extent_hole_real( /* * Check and set flags if this segment has a left neighbor. */ - if (*idx > 0) { + if (xfs_iext_peek_prev_extent(ifp, icur, &left)) { state |= BMAP_LEFT_VALID; - xfs_iext_get_extent(ifp, *idx - 1, &left); if (isnullstartblock(left.br_startblock)) state |= BMAP_LEFT_DELAY; } @@ -2700,9 +2687,8 @@ xfs_bmap_add_extent_hole_real( * Check and set flags if this segment has a current value. * Not true if we're inserting into the "hole" at eof. */ - if (*idx < xfs_iext_count(ifp)) { + if (xfs_iext_get_extent(ifp, icur, &right)) { state |= BMAP_RIGHT_VALID; - xfs_iext_get_extent(ifp, *idx, &right); if (isnullstartblock(right.br_startblock)) state |= BMAP_RIGHT_DELAY; } @@ -2741,9 +2727,9 @@ xfs_bmap_add_extent_hole_real( */ left.br_blockcount += new->br_blockcount + right.br_blockcount; - xfs_iext_remove(ip, *idx, 1, state); - --*idx; - xfs_iext_update_extent(ip, state, *idx, &left); + xfs_iext_remove(ip, icur, 1, 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); @@ -2778,8 +2764,8 @@ xfs_bmap_add_extent_hole_real( old = left; left.br_blockcount += new->br_blockcount; - --*idx; - xfs_iext_update_extent(ip, state, *idx, &left); + xfs_iext_prev(ifp, icur); + xfs_iext_update_extent(ip, state, icur, &left); if (cur == NULL) { rval = xfs_ilog_fext(whichfork); @@ -2806,7 +2792,7 @@ xfs_bmap_add_extent_hole_real( right.br_startoff = new->br_startoff; right.br_startblock = new->br_startblock; right.br_blockcount += new->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, &right); + xfs_iext_update_extent(ip, state, icur, &right); if (cur == NULL) { rval = xfs_ilog_fext(whichfork); @@ -2828,7 +2814,7 @@ xfs_bmap_add_extent_hole_real( * real allocation. * Insert a new entry. */ - xfs_iext_insert(ip, *idx, 1, new, state); + xfs_iext_insert(ip, icur, 1, new, state); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); if (cur == NULL) { @@ -3778,7 +3764,7 @@ xfs_bmapi_read( struct xfs_bmbt_irec got; xfs_fileoff_t obno; xfs_fileoff_t end; - xfs_extnum_t idx; + struct xfs_iext_cursor icur; int error; bool eof = false; int n = 0; @@ -3820,7 +3806,7 @@ xfs_bmapi_read( return error; } - if (!xfs_iext_lookup_extent(ip, ifp, bno, &idx, &got)) + if (!xfs_iext_lookup_extent(ip, ifp, bno, &icur, &got)) eof = true; end = bno + len; obno = bno; @@ -3852,7 +3838,7 @@ xfs_bmapi_read( break; /* Else go on to the next record. */ - if (!xfs_iext_get_extent(ifp, ++idx, &got)) + if (!xfs_iext_next_extent(ifp, &icur, &got)) eof = true; } *nmap = n; @@ -3880,7 +3866,7 @@ xfs_bmapi_reserve_delalloc( xfs_filblks_t len, xfs_filblks_t prealloc, struct xfs_bmbt_irec *got, - xfs_extnum_t *lastx, + struct xfs_iext_cursor *icur, int eof) { struct xfs_mount *mp = ip->i_mount; @@ -3910,7 +3896,7 @@ xfs_bmapi_reserve_delalloc( if (extsz) { struct xfs_bmbt_irec prev; - if (!xfs_iext_get_extent(ifp, *lastx - 1, &prev)) + if (!xfs_iext_peek_prev_extent(ifp, icur, &prev)) prev.br_startoff = NULLFILEOFF; error = xfs_bmap_extsize_align(mp, got, &prev, extsz, rt, eof, @@ -3959,7 +3945,7 @@ xfs_bmapi_reserve_delalloc( got->br_blockcount = alen; got->br_state = XFS_EXT_NORM; - xfs_bmap_add_extent_hole_delay(ip, whichfork, lastx, got); + xfs_bmap_add_extent_hole_delay(ip, whichfork, icur, got); /* * Tag the inode if blocks were preallocated. Note that COW fork @@ -4004,8 +3990,7 @@ xfs_bmapi_allocate( if (bma->wasdel) { bma->length = (xfs_extlen_t)bma->got.br_blockcount; bma->offset = bma->got.br_startoff; - if (bma->idx) - xfs_iext_get_extent(ifp, bma->idx - 1, &bma->prev); + xfs_iext_peek_prev_extent(ifp, &bma->icur, &bma->prev); } else { bma->length = XFS_FILBLKS_MIN(bma->length, MAXEXTLEN); if (!bma->eof) @@ -4090,7 +4075,7 @@ xfs_bmapi_allocate( error = xfs_bmap_add_extent_delay_real(bma, whichfork); else error = xfs_bmap_add_extent_hole_real(bma->tp, bma->ip, - whichfork, &bma->idx, &bma->cur, &bma->got, + whichfork, &bma->icur, &bma->cur, &bma->got, bma->firstblock, bma->dfops, &bma->logflags); bma->logflags |= tmp_logflags; @@ -4102,7 +4087,7 @@ xfs_bmapi_allocate( * or xfs_bmap_add_extent_hole_real might have merged it into one of * the neighbouring ones. */ - xfs_iext_get_extent(ifp, bma->idx, &bma->got); + xfs_iext_get_extent(ifp, &bma->icur, &bma->got); ASSERT(bma->got.br_startoff <= bma->offset); ASSERT(bma->got.br_startoff + bma->got.br_blockcount >= @@ -4160,8 +4145,8 @@ xfs_bmapi_convert_unwritten( } error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, whichfork, - &bma->idx, &bma->cur, mval, bma->firstblock, bma->dfops, - &tmp_logflags); + &bma->icur, &bma->cur, mval, bma->firstblock, + bma->dfops, &tmp_logflags); /* * Log the inode core unconditionally in the unwritten extent conversion * path because the conversion might not have done so (e.g., if the @@ -4183,7 +4168,7 @@ xfs_bmapi_convert_unwritten( * xfs_bmap_add_extent_unwritten_real might have merged it into one * of the neighbouring ones. */ - xfs_iext_get_extent(ifp, bma->idx, &bma->got); + xfs_iext_get_extent(ifp, &bma->icur, &bma->got); /* * We may have combined previously unwritten space with written space, @@ -4302,9 +4287,9 @@ xfs_bmapi_write( end = bno + len; obno = bno; - if (!xfs_iext_lookup_extent(ip, ifp, bno, &bma.idx, &bma.got)) + if (!xfs_iext_lookup_extent(ip, ifp, bno, &bma.icur, &bma.got)) eof = true; - if (!xfs_iext_get_extent(ifp, bma.idx - 1, &bma.prev)) + if (!xfs_iext_peek_prev_extent(ifp, &bma.icur, &bma.prev)) bma.prev.br_startoff = NULLFILEOFF; bma.tp = tp; bma.ip = ip; @@ -4409,7 +4394,7 @@ xfs_bmapi_write( /* Else go on to the next record. */ bma.prev = bma.got; - if (!xfs_iext_get_extent(ifp, ++bma.idx, &bma.got)) + if (!xfs_iext_next_extent(ifp, &bma.icur, &bma.got)) eof = true; } *nmap = n; @@ -4482,7 +4467,7 @@ xfs_bmapi_remap( struct xfs_btree_cur *cur = NULL; xfs_fsblock_t firstblock = NULLFSBLOCK; struct xfs_bmbt_irec got; - xfs_extnum_t idx; + struct xfs_iext_cursor icur; int logflags = 0, error; ASSERT(len > 0); @@ -4506,7 +4491,7 @@ xfs_bmapi_remap( return error; } - if (xfs_iext_lookup_extent(ip, ifp, bno, &idx, &got)) { + if (xfs_iext_lookup_extent(ip, ifp, bno, &icur, &got)) { /* make sure we only reflink into a hole. */ ASSERT(got.br_startoff > bno); ASSERT(got.br_startoff - bno >= len); @@ -4527,8 +4512,8 @@ xfs_bmapi_remap( got.br_blockcount = len; got.br_state = XFS_EXT_NORM; - error = xfs_bmap_add_extent_hole_real(tp, ip, XFS_DATA_FORK, &idx, &cur, - &got, &firstblock, dfops, &logflags); + error = xfs_bmap_add_extent_hole_real(tp, ip, XFS_DATA_FORK, &icur, + &cur, &got, &firstblock, dfops, &logflags); if (error) goto error0; @@ -4644,7 +4629,7 @@ int xfs_bmap_del_extent_delay( struct xfs_inode *ip, int whichfork, - xfs_extnum_t *idx, + struct xfs_iext_cursor *icur, struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del) { @@ -4666,8 +4651,6 @@ xfs_bmap_del_extent_delay( da_old = startblockval(got->br_startblock); da_new = 0; - ASSERT(*idx >= 0); - ASSERT(*idx <= xfs_iext_count(ifp)); ASSERT(del->br_blockcount > 0); ASSERT(got->br_startoff <= del->br_startoff); ASSERT(got_endoff >= del_endoff); @@ -4701,8 +4684,8 @@ xfs_bmap_del_extent_delay( /* * Matches the whole extent. Delete the entry. */ - xfs_iext_remove(ip, *idx, 1, state); - --*idx; + xfs_iext_remove(ip, icur, 1, state); + xfs_iext_prev(ifp, icur); break; case BMAP_LEFT_FILLING: /* @@ -4713,7 +4696,7 @@ xfs_bmap_del_extent_delay( da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, got->br_blockcount), da_old); got->br_startblock = nullstartblock((int)da_new); - xfs_iext_update_extent(ip, state, *idx, got); + xfs_iext_update_extent(ip, state, icur, got); break; case BMAP_RIGHT_FILLING: /* @@ -4723,7 +4706,7 @@ xfs_bmap_del_extent_delay( da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, got->br_blockcount), da_old); got->br_startblock = nullstartblock((int)da_new); - xfs_iext_update_extent(ip, state, *idx, got); + xfs_iext_update_extent(ip, state, icur, got); break; case 0: /* @@ -4751,9 +4734,9 @@ xfs_bmap_del_extent_delay( new.br_state = got->br_state; new.br_startblock = nullstartblock((int)new_indlen); - xfs_iext_update_extent(ip, state, *idx, got); - ++*idx; - xfs_iext_insert(ip, *idx, 1, &new, state); + xfs_iext_update_extent(ip, state, icur, got); + xfs_iext_next(ifp, icur); + xfs_iext_insert(ip, icur, 1, &new, state); da_new = got_indlen + new_indlen - stolen; del->br_blockcount -= stolen; @@ -4772,7 +4755,7 @@ xfs_bmap_del_extent_delay( void xfs_bmap_del_extent_cow( struct xfs_inode *ip, - xfs_extnum_t *idx, + struct xfs_iext_cursor *icur, struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del) { @@ -4787,8 +4770,6 @@ xfs_bmap_del_extent_cow( del_endoff = del->br_startoff + del->br_blockcount; got_endoff = got->br_startoff + got->br_blockcount; - ASSERT(*idx >= 0); - ASSERT(*idx <= xfs_iext_count(ifp)); ASSERT(del->br_blockcount > 0); ASSERT(got->br_startoff <= del->br_startoff); ASSERT(got_endoff >= del_endoff); @@ -4804,8 +4785,8 @@ xfs_bmap_del_extent_cow( /* * Matches the whole extent. Delete the entry. */ - xfs_iext_remove(ip, *idx, 1, state); - --*idx; + xfs_iext_remove(ip, icur, 1, state); + xfs_iext_prev(ifp, icur); break; case BMAP_LEFT_FILLING: /* @@ -4814,14 +4795,14 @@ xfs_bmap_del_extent_cow( got->br_startoff = del_endoff; got->br_blockcount -= del->br_blockcount; got->br_startblock = del->br_startblock + del->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, got); + xfs_iext_update_extent(ip, state, icur, got); break; case BMAP_RIGHT_FILLING: /* * Deleting the last part of the extent. */ got->br_blockcount -= del->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, got); + xfs_iext_update_extent(ip, state, icur, got); break; case 0: /* @@ -4834,9 +4815,9 @@ xfs_bmap_del_extent_cow( new.br_state = got->br_state; new.br_startblock = del->br_startblock + del->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, got); - ++*idx; - xfs_iext_insert(ip, *idx, 1, &new, state); + xfs_iext_update_extent(ip, state, icur, got); + xfs_iext_next(ifp, icur); + xfs_iext_insert(ip, icur, 1, &new, state); break; } } @@ -4849,7 +4830,7 @@ STATIC int /* error */ xfs_bmap_del_extent_real( xfs_inode_t *ip, /* incore inode pointer */ xfs_trans_t *tp, /* current transaction pointer */ - xfs_extnum_t *idx, /* extent number to update/delete */ + struct xfs_iext_cursor *icur, struct xfs_defer_ops *dfops, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *del, /* data to remove from extents */ @@ -4878,9 +4859,8 @@ xfs_bmap_del_extent_real( XFS_STATS_INC(mp, xs_del_exlist); ifp = XFS_IFORK_PTR(ip, whichfork); - ASSERT((*idx >= 0) && (*idx < xfs_iext_count(ifp))); ASSERT(del->br_blockcount > 0); - xfs_iext_get_extent(ifp, *idx, &got); + xfs_iext_get_extent(ifp, icur, &got); ASSERT(got.br_startoff <= del->br_startoff); del_endoff = del->br_startoff + del->br_blockcount; got_endoff = got.br_startoff + got.br_blockcount; @@ -4945,9 +4925,8 @@ xfs_bmap_del_extent_real( /* * Matches the whole extent. Delete the entry. */ - xfs_iext_remove(ip, *idx, 1, state); - --*idx; - + xfs_iext_remove(ip, icur, 1, state); + xfs_iext_prev(ifp, icur); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) - 1); flags |= XFS_ILOG_CORE; @@ -4966,7 +4945,7 @@ xfs_bmap_del_extent_real( got.br_startoff = del_endoff; got.br_startblock = del_endblock; got.br_blockcount -= del->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, &got); + xfs_iext_update_extent(ip, state, icur, &got); if (!cur) { flags |= xfs_ilog_fext(whichfork); break; @@ -4980,7 +4959,7 @@ xfs_bmap_del_extent_real( * Deleting the last part of the extent. */ got.br_blockcount -= del->br_blockcount; - xfs_iext_update_extent(ip, state, *idx, &got); + xfs_iext_update_extent(ip, state, icur, &got); if (!cur) { flags |= xfs_ilog_fext(whichfork); break; @@ -4996,7 +4975,7 @@ xfs_bmap_del_extent_real( old = got; got.br_blockcount = del->br_startoff - got.br_startoff; - xfs_iext_update_extent(ip, state, *idx, &got); + xfs_iext_update_extent(ip, state, icur, &got); new.br_startoff = del_endoff; new.br_blockcount = got_endoff - del_endoff; @@ -5040,7 +5019,7 @@ xfs_bmap_del_extent_real( * Reset the extent record back * to the original value. */ - xfs_iext_update_extent(ip, state, *idx, &old); + xfs_iext_update_extent(ip, state, icur, &old); flags = 0; error = -ENOSPC; goto done; @@ -5050,8 +5029,8 @@ xfs_bmap_del_extent_real( flags |= xfs_ilog_fext(whichfork); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); - ++*idx; - xfs_iext_insert(ip, *idx, 1, &new, state); + xfs_iext_next(ifp, icur); + xfs_iext_insert(ip, icur, 1, &new, state); break; } @@ -5114,7 +5093,6 @@ __xfs_bunmapi( xfs_bmbt_irec_t got; /* current extent record */ xfs_ifork_t *ifp; /* inode fork pointer */ int isrt; /* freeing in rt area */ - xfs_extnum_t lastx; /* last extent index used */ int logflags; /* transaction logging flags */ xfs_extlen_t mod; /* rt extent offset */ xfs_mount_t *mp; /* mount structure */ @@ -5126,6 +5104,8 @@ __xfs_bunmapi( xfs_fileoff_t max_len; xfs_agnumber_t prev_agno = NULLAGNUMBER, agno; xfs_fileoff_t end; + struct xfs_iext_cursor icur; + bool done = false; trace_xfs_bunmap(ip, start, len, flags, _RET_IP_); @@ -5168,7 +5148,7 @@ __xfs_bunmapi( isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); end = start + len; - if (!xfs_iext_lookup_extent_before(ip, ifp, &end, &lastx, &got)) { + if (!xfs_iext_lookup_extent_before(ip, ifp, &end, &icur, &got)) { *rlen = 0; return 0; } @@ -5195,16 +5175,16 @@ __xfs_bunmapi( } extno = 0; - while (end != (xfs_fileoff_t)-1 && end >= start && lastx >= 0 && + while (end != (xfs_fileoff_t)-1 && end >= start && (nexts == 0 || extno < nexts) && max_len > 0) { /* * Is the found extent after a hole in which end lives? * Just back up to the previous extent, if so. */ - if (got.br_startoff > end) { - if (--lastx < 0) - break; - xfs_iext_get_extent(ifp, lastx, &got); + if (got.br_startoff > end && + !xfs_iext_prev_extent(ifp, &icur, &got)) { + done = true; + break; } /* * Is the last block of this extent before the range @@ -5267,10 +5247,10 @@ __xfs_bunmapi( ASSERT(end >= mod); end -= mod > del.br_blockcount ? del.br_blockcount : mod; - if (end < got.br_startoff) { - if (--lastx >= 0) - xfs_iext_get_extent(ifp, lastx, - &got); + if (end < got.br_startoff && + !xfs_iext_prev_extent(ifp, &icur, &got)) { + done = true; + break; } continue; } @@ -5291,7 +5271,7 @@ __xfs_bunmapi( } del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent_unwritten_real(tp, ip, - whichfork, &lastx, &cur, &del, + whichfork, &icur, &cur, &del, firstblock, dfops, &logflags); if (error) goto error0; @@ -5318,8 +5298,11 @@ __xfs_bunmapi( */ ASSERT(end >= del.br_blockcount); end -= del.br_blockcount; - if (got.br_startoff > end && --lastx >= 0) - xfs_iext_get_extent(ifp, lastx, &got); + if (got.br_startoff > end && + !xfs_iext_prev_extent(ifp, &icur, &got)) { + done = true; + break; + } continue; } else if (del.br_state == XFS_EXT_UNWRITTEN) { struct xfs_bmbt_irec prev; @@ -5330,8 +5313,8 @@ __xfs_bunmapi( * Unwrite the killed part of that one and * try again. */ - ASSERT(lastx > 0); - xfs_iext_get_extent(ifp, lastx - 1, &prev); + if (!xfs_iext_prev_extent(ifp, &icur, &prev)) + ASSERT(0); ASSERT(prev.br_state == XFS_EXT_NORM); ASSERT(!isnullstartblock(prev.br_startblock)); ASSERT(del.br_startblock == @@ -5343,9 +5326,8 @@ __xfs_bunmapi( prev.br_startoff = start; } prev.br_state = XFS_EXT_UNWRITTEN; - lastx--; error = xfs_bmap_add_extent_unwritten_real(tp, - ip, whichfork, &lastx, &cur, + ip, whichfork, &icur, &cur, &prev, firstblock, dfops, &logflags); if (error) @@ -5355,7 +5337,7 @@ __xfs_bunmapi( ASSERT(del.br_state == XFS_EXT_NORM); del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent_unwritten_real(tp, - ip, whichfork, &lastx, &cur, + ip, whichfork, &icur, &cur, &del, firstblock, dfops, &logflags); if (error) @@ -5365,10 +5347,10 @@ __xfs_bunmapi( } if (wasdel) { - error = xfs_bmap_del_extent_delay(ip, whichfork, &lastx, + error = xfs_bmap_del_extent_delay(ip, whichfork, &icur, &got, &del); } else { - error = xfs_bmap_del_extent_real(ip, tp, &lastx, dfops, + error = xfs_bmap_del_extent_real(ip, tp, &icur, dfops, cur, &del, &tmp_logflags, whichfork, flags); logflags |= tmp_logflags; @@ -5384,15 +5366,16 @@ nodelete: * If not done go on to the next (previous) record. */ if (end != (xfs_fileoff_t)-1 && end >= start) { - if (lastx >= 0) { - xfs_iext_get_extent(ifp, lastx, &got); - if (got.br_startoff > end && --lastx >= 0) - xfs_iext_get_extent(ifp, lastx, &got); + if (!xfs_iext_get_extent(ifp, &icur, &got) || + (got.br_startoff > end && + !xfs_iext_prev_extent(ifp, &icur, &got))) { + done = true; + break; } extno++; } } - if (end == (xfs_fileoff_t)-1 || end < start || lastx < 0) + if (done || end == (xfs_fileoff_t)-1 || end < start) *rlen = 0; else *rlen = end - start + 1; @@ -5513,7 +5496,7 @@ xfs_bmse_merge( struct xfs_inode *ip, int whichfork, xfs_fileoff_t shift, /* shift fsb */ - int *current_ext, /* idx of gotp */ + struct xfs_iext_cursor *icur, struct xfs_bmbt_irec *got, /* extent to shift */ struct xfs_bmbt_irec *left, /* preceding extent */ struct xfs_btree_cur *cur, @@ -5568,10 +5551,10 @@ xfs_bmse_merge( return error; done: - xfs_iext_remove(ip, *current_ext, 1, 0); - --*current_ext; - xfs_iext_update_extent(ip, xfs_bmap_fork_to_state(whichfork), - *current_ext, &new); + xfs_iext_remove(ip, icur, 1, 0); + xfs_iext_prev(XFS_IFORK_PTR(ip, whichfork), icur); + xfs_iext_update_extent(ip, xfs_bmap_fork_to_state(whichfork), icur, + &new); /* update reverse mapping. rmap functions merge the rmaps for us */ error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, got); @@ -5586,7 +5569,7 @@ static int xfs_bmap_shift_update_extent( struct xfs_inode *ip, int whichfork, - xfs_extnum_t idx, + struct xfs_iext_cursor *icur, struct xfs_bmbt_irec *got, struct xfs_btree_cur *cur, int *logflags, @@ -5614,7 +5597,8 @@ xfs_bmap_shift_update_extent( *logflags |= XFS_ILOG_DEXT; } - xfs_iext_update_extent(ip, xfs_bmap_fork_to_state(whichfork), idx, got); + xfs_iext_update_extent(ip, xfs_bmap_fork_to_state(whichfork), icur, + got); /* update reverse mapping */ error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &prev); @@ -5639,7 +5623,7 @@ xfs_bmap_collapse_extents( struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_btree_cur *cur = NULL; struct xfs_bmbt_irec got, prev; - xfs_extnum_t current_ext; + struct xfs_iext_cursor icur; xfs_fileoff_t new_startoff; int error = 0; int logflags = 0; @@ -5670,14 +5654,14 @@ xfs_bmap_collapse_extents( cur->bc_private.b.flags = 0; } - if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, ¤t_ext, &got)) { + if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, &icur, &got)) { *done = true; goto del_cursor; } XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock)); new_startoff = got.br_startoff - offset_shift_fsb; - if (xfs_iext_get_extent(ifp, current_ext - 1, &prev)) { + if (xfs_iext_peek_prev_extent(ifp, &icur, &prev)) { if (new_startoff < prev.br_startoff + prev.br_blockcount) { error = -EINVAL; goto del_cursor; @@ -5685,8 +5669,8 @@ xfs_bmap_collapse_extents( if (xfs_bmse_can_merge(&prev, &got, offset_shift_fsb)) { error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb, - ¤t_ext, &got, &prev, cur, - &logflags, dfops); + &icur, &got, &prev, cur, &logflags, + dfops); if (error) goto del_cursor; goto done; @@ -5698,15 +5682,15 @@ xfs_bmap_collapse_extents( } } - error = xfs_bmap_shift_update_extent(ip, whichfork, current_ext, &got, - cur, &logflags, dfops, new_startoff); + error = xfs_bmap_shift_update_extent(ip, whichfork, &icur, &got, cur, + &logflags, dfops, new_startoff); if (error) goto del_cursor; done: - if (!xfs_iext_get_extent(ifp, ++current_ext, &got)) { - *done = true; - goto del_cursor; + if (!xfs_iext_next_extent(ifp, &icur, &got)) { + *done = true; + goto del_cursor; } *next_fsb = got.br_startoff; @@ -5735,7 +5719,7 @@ xfs_bmap_insert_extents( struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_btree_cur *cur = NULL; struct xfs_bmbt_irec got, next; - xfs_extnum_t current_ext; + struct xfs_iext_cursor icur; xfs_fileoff_t new_startoff; int error = 0; int logflags = 0; @@ -5767,15 +5751,14 @@ xfs_bmap_insert_extents( } if (*next_fsb == NULLFSBLOCK) { - current_ext = xfs_iext_count(ifp) - 1; - if (!xfs_iext_get_extent(ifp, current_ext, &got) || + xfs_iext_last(ifp, &icur); + if (!xfs_iext_get_extent(ifp, &icur, &got) || stop_fsb > got.br_startoff) { *done = true; goto del_cursor; } } else { - if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, ¤t_ext, - &got)) { + if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, &icur, &got)) { *done = true; goto del_cursor; } @@ -5788,7 +5771,7 @@ xfs_bmap_insert_extents( } new_startoff = got.br_startoff + offset_shift_fsb; - if (xfs_iext_get_extent(ifp, current_ext + 1, &next)) { + if (xfs_iext_peek_next_extent(ifp, &icur, &next)) { if (new_startoff + got.br_blockcount > next.br_startoff) { error = -EINVAL; goto del_cursor; @@ -5804,12 +5787,12 @@ xfs_bmap_insert_extents( WARN_ON_ONCE(1); } - error = xfs_bmap_shift_update_extent(ip, whichfork, current_ext, &got, - cur, &logflags, dfops, new_startoff); + error = xfs_bmap_shift_update_extent(ip, whichfork, &icur, &got, cur, + &logflags, dfops, new_startoff); if (error) goto del_cursor; - if (!xfs_iext_get_extent(ifp, --current_ext, &got) || + if (!xfs_iext_prev_extent(ifp, &icur, &got) || stop_fsb >= got.br_startoff + got.br_blockcount) { *done = true; goto del_cursor; @@ -5826,10 +5809,10 @@ del_cursor: } /* - * Splits an extent into two extents at split_fsb block such that it is - * the first block of the current_ext. @current_ext is a target extent - * to be split. @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. + * Splits an extent into two extents at split_fsb block such that it is the + * first block of the current_ext. @ext is a target extent to be split. + * @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( @@ -5846,7 +5829,7 @@ xfs_bmap_split_extent_at( struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp; xfs_fsblock_t gotblkcnt; /* new block count for got */ - xfs_extnum_t current_ext; + struct xfs_iext_cursor icur; int error = 0; int logflags = 0; int i = 0; @@ -5874,7 +5857,7 @@ xfs_bmap_split_extent_at( /* * If there are not extents, or split_fsb lies in a hole we are done. */ - if (!xfs_iext_lookup_extent(ip, ifp, split_fsb, ¤t_ext, &got) || + if (!xfs_iext_lookup_extent(ip, ifp, split_fsb, &icur, &got) || got.br_startoff >= split_fsb) return 0; @@ -5896,8 +5879,8 @@ xfs_bmap_split_extent_at( } got.br_blockcount = gotblkcnt; - xfs_iext_update_extent(ip, xfs_bmap_fork_to_state(whichfork), - current_ext, &got); + xfs_iext_update_extent(ip, xfs_bmap_fork_to_state(whichfork), &icur, + &got); logflags = XFS_ILOG_CORE; if (cur) { @@ -5908,8 +5891,8 @@ xfs_bmap_split_extent_at( logflags |= XFS_ILOG_DEXT; /* Add new extent */ - current_ext++; - xfs_iext_insert(ip, current_ext, 1, &new, 0); + xfs_iext_next(ifp, &icur); + xfs_iext_insert(ip, &icur, 1, &new, 0); XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); |