xfs: add a new xfs_iext_lookup_extent_before helper
This helper looks up the last extent the covers space before the passed in block number. This is useful for truncate and similar operations that operate backwards over the extent list. For xfs_bunmapi it also is a slight optimization as we can return early if there are not extents at or below the end of the to be truncated range. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
parent
211e95bbab
commit
dc56015faf
|
@ -1386,17 +1386,8 @@ xfs_bmap_last_before(
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xfs_iext_lookup_extent(ip, ifp, *last_block - 1, &idx, &got)) {
|
if (!xfs_iext_lookup_extent_before(ip, ifp, last_block, &idx, &got))
|
||||||
if (got.br_startoff <= *last_block - 1)
|
*last_block = 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xfs_iext_get_extent(ifp, idx - 1, &got)) {
|
|
||||||
*last_block = got.br_startoff + got.br_blockcount;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*last_block = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5171,17 +5162,13 @@ __xfs_bunmapi(
|
||||||
}
|
}
|
||||||
XFS_STATS_INC(mp, xs_blk_unmap);
|
XFS_STATS_INC(mp, xs_blk_unmap);
|
||||||
isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
|
isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
|
||||||
end = start + len - 1;
|
end = start + len;
|
||||||
|
|
||||||
/*
|
if (!xfs_iext_lookup_extent_before(ip, ifp, &end, &lastx, &got)) {
|
||||||
* Check to see if the given block number is past the end of the
|
*rlen = 0;
|
||||||
* file, back up to the last block if so...
|
return 0;
|
||||||
*/
|
|
||||||
if (!xfs_iext_lookup_extent(ip, ifp, end, &lastx, &got)) {
|
|
||||||
ASSERT(lastx > 0);
|
|
||||||
xfs_iext_get_extent(ifp, --lastx, &got);
|
|
||||||
end = got.br_startoff + got.br_blockcount - 1;
|
|
||||||
}
|
}
|
||||||
|
end--;
|
||||||
|
|
||||||
logflags = 0;
|
logflags = 0;
|
||||||
if (ifp->if_flags & XFS_IFBROOT) {
|
if (ifp->if_flags & XFS_IFBROOT) {
|
||||||
|
|
|
@ -1967,6 +1967,27 @@ xfs_iext_lookup_extent(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the last extent before end, and if this extent doesn't cover
|
||||||
|
* end, update end to the end of the extent.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
xfs_iext_lookup_extent_before(
|
||||||
|
struct xfs_inode *ip,
|
||||||
|
struct xfs_ifork *ifp,
|
||||||
|
xfs_fileoff_t *end,
|
||||||
|
xfs_extnum_t *idxp,
|
||||||
|
struct xfs_bmbt_irec *gotp)
|
||||||
|
{
|
||||||
|
if (xfs_iext_lookup_extent(ip, ifp, *end - 1, idxp, gotp) &&
|
||||||
|
gotp->br_startoff <= *end - 1)
|
||||||
|
return true;
|
||||||
|
if (!xfs_iext_get_extent(ifp, --*idxp, gotp))
|
||||||
|
return false;
|
||||||
|
*end = gotp->br_startoff + gotp->br_blockcount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if there is an extent at index idx, and return the expanded
|
* Return true if there is an extent at index idx, and return the expanded
|
||||||
* extent structure at idx in that case. Else return false.
|
* extent structure at idx in that case. Else return false.
|
||||||
|
|
|
@ -183,6 +183,10 @@ void xfs_iext_irec_update_extoffs(struct xfs_ifork *, int, int);
|
||||||
bool xfs_iext_lookup_extent(struct xfs_inode *ip,
|
bool xfs_iext_lookup_extent(struct xfs_inode *ip,
|
||||||
struct xfs_ifork *ifp, xfs_fileoff_t bno,
|
struct xfs_ifork *ifp, xfs_fileoff_t bno,
|
||||||
xfs_extnum_t *idxp, struct xfs_bmbt_irec *gotp);
|
xfs_extnum_t *idxp, struct xfs_bmbt_irec *gotp);
|
||||||
|
bool xfs_iext_lookup_extent_before(struct xfs_inode *ip,
|
||||||
|
struct xfs_ifork *ifp, xfs_fileoff_t *end,
|
||||||
|
xfs_extnum_t *idxp, struct xfs_bmbt_irec *gotp);
|
||||||
|
|
||||||
bool xfs_iext_get_extent(struct xfs_ifork *ifp, xfs_extnum_t idx,
|
bool xfs_iext_get_extent(struct xfs_ifork *ifp, xfs_extnum_t idx,
|
||||||
struct xfs_bmbt_irec *gotp);
|
struct xfs_bmbt_irec *gotp);
|
||||||
void xfs_iext_update_extent(struct xfs_inode *ip, int state,
|
void xfs_iext_update_extent(struct xfs_inode *ip, int state,
|
||||||
|
|
|
@ -733,18 +733,13 @@ xfs_reflink_end_cow(
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_trans_ijoin(tp, ip, 0);
|
xfs_trans_ijoin(tp, ip, 0);
|
||||||
|
|
||||||
/* If there is a hole at end_fsb - 1 go to the previous extent */
|
/*
|
||||||
if (!xfs_iext_lookup_extent(ip, ifp, end_fsb - 1, &idx, &got) ||
|
* In case of racing, overlapping AIO writes no COW extents might be
|
||||||
got.br_startoff > end_fsb) {
|
* left by the time I/O completes for the loser of the race. In that
|
||||||
/*
|
* case we are done.
|
||||||
* In case of racing, overlapping AIO writes no COW extents
|
*/
|
||||||
* might be left by the time I/O completes for the loser of
|
if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &idx, &got))
|
||||||
* the race. In that case we are done.
|
goto out_cancel;
|
||||||
*/
|
|
||||||
if (idx <= 0)
|
|
||||||
goto out_cancel;
|
|
||||||
xfs_iext_get_extent(ifp, --idx, &got);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Walk backwards until we're out of the I/O range... */
|
/* Walk backwards until we're out of the I/O range... */
|
||||||
while (got.br_startoff + got.br_blockcount > offset_fsb) {
|
while (got.br_startoff + got.br_blockcount > offset_fsb) {
|
||||||
|
|
Loading…
Reference in New Issue