diff options
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 59 |
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 | */ | ||
3561 | xfs_bmbt_rec_t * /* pointer to found extent entry */ | ||
3562 | xfs_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 " |