aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r--fs/xfs/xfs_bmap.c59
1 files changed, 51 insertions, 8 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 53c47a181f87..81a95b684b6b 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -3423,6 +3423,7 @@ xfs_bmap_local_to_extents(
3423 xfs_bmap_forkoff_reset(args.mp, ip, whichfork); 3423 xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
3424 xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); 3424 xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
3425 xfs_iext_add(ifp, 0, 1); 3425 xfs_iext_add(ifp, 0, 1);
3426 ASSERT((ifp->if_flags & (XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFEXTENTS);
3426 ep = xfs_iext_get_ext(ifp, 0); 3427 ep = xfs_iext_get_ext(ifp, 0);
3427 xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM); 3428 xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
3428 xfs_bmap_trace_post_update(fname, "new", ip, 0, whichfork); 3429 xfs_bmap_trace_post_update(fname, "new", ip, 0, whichfork);
@@ -3552,6 +3553,54 @@ xfs_bmap_do_search_extents(
3552} 3553}
3553 3554
3554/* 3555/*
3556 * Call xfs_bmap_do_search_extents() to search for the extent
3557 * record containing block bno. If in multi-level in-core extent
3558 * allocation mode, find and extract the target extent buffer,
3559 * otherwise just use the direct extent list.
3560 */
3561xfs_bmbt_rec_t * /* pointer to found extent entry */
3562xfs_bmap_search_multi_extents(
3563 xfs_ifork_t *ifp, /* inode fork pointer */
3564 xfs_fileoff_t bno, /* block number searched for */
3565 int *eofp, /* out: end of file found */
3566 xfs_extnum_t *lastxp, /* out: last extent index */
3567 xfs_bmbt_irec_t *gotp, /* out: extent entry found */
3568 xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
3569{
3570 xfs_bmbt_rec_t *base; /* base of extent records */
3571 xfs_bmbt_rec_t *ep; /* extent record pointer */
3572 xfs_ext_irec_t *erp = NULL; /* indirection array pointer */
3573 xfs_extnum_t lastx; /* last extent index */
3574 xfs_extnum_t nextents; /* number of file extents */
3575
3576 /*
3577 * For multi-level extent allocation mode, find the
3578 * target extent list and pass only the contiguous
3579 * list to xfs_bmap_do_search_extents. Convert lastx
3580 * from a file extent index to an index within the
3581 * target extent list.
3582 */
3583 if (ifp->if_flags & XFS_IFEXTIREC) {
3584 int erp_idx = 0;
3585 erp = xfs_iext_bno_to_irec(ifp, bno, &erp_idx);
3586 base = erp->er_extbuf;
3587 nextents = erp->er_extcount;
3588 lastx = ifp->if_lastex - erp->er_extoff;
3589 } else {
3590 base = &ifp->if_u1.if_extents[0];
3591 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
3592 lastx = ifp->if_lastex;
3593 }
3594 ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno,
3595 eofp, lastxp, gotp, prevp);
3596 /* Convert lastx back to file-based index */
3597 if (ifp->if_flags & XFS_IFEXTIREC) {
3598 *lastxp += erp->er_extoff;
3599 }
3600 return ep;
3601}
3602
3603/*
3555 * Search the extents list for the inode, for the extent containing bno. 3604 * Search the extents list for the inode, for the extent containing bno.
3556 * If bno lies in a hole, point to the next entry. If bno lies past eof, 3605 * If bno lies in a hole, point to the next entry. If bno lies past eof,
3557 * *eofp will be set, and *prevp will contain the last entry (null if none). 3606 * *eofp will be set, and *prevp will contain the last entry (null if none).
@@ -3569,20 +3618,14 @@ xfs_bmap_search_extents(
3569 xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */ 3618 xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
3570{ 3619{
3571 xfs_ifork_t *ifp; /* inode fork pointer */ 3620 xfs_ifork_t *ifp; /* inode fork pointer */
3572 xfs_bmbt_rec_t *base; /* base of extent list */
3573 xfs_extnum_t lastx; /* last extent index used */
3574 xfs_extnum_t nextents; /* number of file extents */
3575 xfs_bmbt_rec_t *ep; /* extent record pointer */ 3621 xfs_bmbt_rec_t *ep; /* extent record pointer */
3576 int rt; /* realtime flag */ 3622 int rt; /* realtime flag */
3577 3623
3578 XFS_STATS_INC(xs_look_exlist); 3624 XFS_STATS_INC(xs_look_exlist);
3579 ifp = XFS_IFORK_PTR(ip, whichfork); 3625 ifp = XFS_IFORK_PTR(ip, whichfork);
3580 lastx = ifp->if_lastex;
3581 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
3582 base = &ifp->if_u1.if_extents[0];
3583 3626
3584 ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp, 3627 ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);
3585 lastxp, gotp, prevp); 3628
3586 rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); 3629 rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
3587 if (unlikely(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM))) { 3630 if (unlikely(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM))) {
3588 cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld " 3631 cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld "