aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
authorMandy Kirkconnell <alkirkco@sgi.com>2006-03-13 21:30:23 -0500
committerNathan Scott <nathans@sgi.com>2006-03-13 21:30:23 -0500
commit0293ce3a9fd1b34c933a96577a8ba737b681cf75 (patch)
tree19c01a41566aa3c631a4d903ca5f3242b15af169 /fs/xfs/xfs_bmap.c
parent4eea22f01bb4fdba1aab4430c33adbe88d9d4985 (diff)
[XFS] 929045 567344 This mod introduces multi-level in-core file extent
functionality, building upon the new layout introduced in mod xfs-linux:xfs-kern:207390a. The new multi-level extent allocations are only required for heavily fragmented files, so the old-style linear extent list is used on files until the extents reach a pre-determined size of 4k. 4k buffers are used because this is the system page size on Linux i386 and systems with larger page sizes don't seem to gain much, if anything, by using their native page size as the extent buffer size. Also, using 4k extent buffers everywhere provides a consistent interface for CXFS across different platforms. The 4k extent buffers are managed by an indirection array (xfs_ext_irec_t) which is basically just a pointer array with a bit of extra information to keep track of the number of extents in each buffer as well as the extent offset of each buffer. Major changes include: - Add multi-level in-core file extent functionality to the xfs_iext_ subroutines introduced in mod: xfs-linux:xfs-kern:207390a - Introduce 13 new subroutines which add functionality for multi-level in-core file extents: xfs_iext_add_indirect_multi() xfs_iext_remove_indirect() xfs_iext_realloc_indirect() xfs_iext_indirect_to_direct() xfs_iext_bno_to_irec() xfs_iext_idx_to_irec() xfs_iext_irec_init() xfs_iext_irec_new() xfs_iext_irec_remove() xfs_iext_irec_compact() xfs_iext_irec_compact_pages() xfs_iext_irec_compact_full() xfs_iext_irec_update_extoffs() SGI-PV: 928864 SGI-Modid: xfs-linux-melb:xfs-kern:207393a Signed-off-by: Mandy Kirkconnell <alkirkco@sgi.com> Signed-off-by: Nathan Scott <nathans@sgi.com>
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 "