diff options
author | Mandy Kirkconnell <alkirkco@sgi.com> | 2006-03-17 01:25:04 -0500 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2006-03-17 01:25:04 -0500 |
commit | 8867bc9bf0aed7181aa72c7c938c6ce830b75166 (patch) | |
tree | ae2dcc3a986e4e48fd81605f109be44c29362edd | |
parent | 524fbf5dd1b25acffe6f8a4ed5f3cce1023cfdb8 (diff) |
[XFS] There are a few problems with the new
xfs_bmap_search_multi_extents() wrapper function that I introduced in mod
xfs-linux:xfs-kern:207393a. The function was added as a wrapper around
xfs_bmap_do_search_extents() to avoid breaking the top-of-tree CXFS
interface. The idea of the function was basically to extract the target
extent buffer (if muli- level extent allocation mode), then call
xfs_bmap_do_search_extents() with either a pointer to the first extent in
the target buffer or a pointer to the first extent in the file, depending
on which extent mode was being used. However, in addition to locating the
target extent record for block bno, xfs_bmap_do_search_extents() also sets
four parameters needed by the caller: *lastx, *eofp, *gotp, *prevp.
Passing only the target extent buffer to xfs_bmap_do_search_extents()
causes *eofp to be set incorrectly if the extent is at the end of the
target list but there are actually more extents in the next er_extbuf.
Likewise, if the extent is the first one in the buffer but NOT the first
in the file, *prevp is incorrectly set to NULL. Adding the needed
functionality to xfs_bmap_search_multi_extents() to re-set any incorrectly
set fields is redundant and makes the call to xfs_bmap_do_search_extents()
not make much sense when multi-level extent allocation mode is being used.
This mod basically extracts the two functional components from
xfs_bmap_do_search_extents(), with the intent of obsoleting/removing
xfs_bmap_do_search_extents() after the CXFS mult-level in-core extent
changes are checked in. The two components are: 1) The binary search to
locate the target extent record, and 2) Setting the four parameters needed
by the caller (*lastx, *eofp, *gotp, *prevp). Component 1: I created a
new function in xfs_inode.c called xfs_iext_bno_to_ext(), which executes
the binary search to find the target extent record.
xfs_bmap_search_multi_extents() has been modified to call
xfs_iext_bno_to_ext() rather than xfs_bmap_do_search_extents(). Component
2: The parameter setting functionality has been added to
xfs_bmap_search_multi_extents(), eliminating the need for
xfs_bmap_do_search_extents(). These changes make the removal of
xfs_bmap_do_search_extents() trival once the CXFS changes are in place.
They also allow us to maintain the current XFS interface, using the new
search function introduced in mod xfs-linux:xfs-kern:207393a.
SGI-PV: 928864
SGI-Modid: xfs-linux-melb:xfs-kern:207866a
Signed-off-by: Mandy Kirkconnell <alkirkco@sgi.com>
Signed-off-by: Nathan Scott <nathans@sgi.com>
-rw-r--r-- | fs/xfs/xfs_bmap.c | 57 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 73 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 1 |
3 files changed, 102 insertions, 29 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 64a02eaf1dfe..2d702e4a74a3 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -3575,10 +3575,11 @@ xfs_bmap_do_search_extents( | |||
3575 | } | 3575 | } |
3576 | 3576 | ||
3577 | /* | 3577 | /* |
3578 | * Call xfs_bmap_do_search_extents() to search for the extent | 3578 | * Search the extent records for the entry containing block bno. |
3579 | * record containing block bno. If in multi-level in-core extent | 3579 | * If bno lies in a hole, point to the next entry. If bno lies |
3580 | * allocation mode, find and extract the target extent buffer, | 3580 | * past eof, *eofp will be set, and *prevp will contain the last |
3581 | * otherwise just use the direct extent list. | 3581 | * entry (null if none). Else, *lastxp will be set to the index |
3582 | * of the found entry; *gotp will contain the entry. | ||
3582 | */ | 3583 | */ |
3583 | xfs_bmbt_rec_t * /* pointer to found extent entry */ | 3584 | xfs_bmbt_rec_t * /* pointer to found extent entry */ |
3584 | xfs_bmap_search_multi_extents( | 3585 | xfs_bmap_search_multi_extents( |
@@ -3589,36 +3590,38 @@ xfs_bmap_search_multi_extents( | |||
3589 | xfs_bmbt_irec_t *gotp, /* out: extent entry found */ | 3590 | xfs_bmbt_irec_t *gotp, /* out: extent entry found */ |
3590 | xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */ | 3591 | xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */ |
3591 | { | 3592 | { |
3592 | xfs_bmbt_rec_t *base; /* base of extent records */ | ||
3593 | xfs_bmbt_rec_t *ep; /* extent record pointer */ | 3593 | xfs_bmbt_rec_t *ep; /* extent record pointer */ |
3594 | xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ | ||
3595 | xfs_extnum_t lastx; /* last extent index */ | 3594 | xfs_extnum_t lastx; /* last extent index */ |
3596 | xfs_extnum_t nextents; /* number of file extents */ | ||
3597 | 3595 | ||
3598 | /* | 3596 | /* |
3599 | * For multi-level extent allocation mode, find the | 3597 | * Initialize the extent entry structure to catch access to |
3600 | * target extent list and pass only the contiguous | 3598 | * uninitialized br_startblock field. |
3601 | * list to xfs_bmap_do_search_extents. Convert lastx | ||
3602 | * from a file extent index to an index within the | ||
3603 | * target extent list. | ||
3604 | */ | 3599 | */ |
3605 | if (ifp->if_flags & XFS_IFEXTIREC) { | 3600 | gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL; |
3606 | int erp_idx = 0; | 3601 | gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL; |
3607 | erp = xfs_iext_bno_to_irec(ifp, bno, &erp_idx); | 3602 | gotp->br_state = XFS_EXT_INVALID; |
3608 | base = erp->er_extbuf; | 3603 | #if XFS_BIG_BLKNOS |
3609 | nextents = erp->er_extcount; | 3604 | gotp->br_startblock = 0xffffa5a5a5a5a5a5LL; |
3610 | lastx = ifp->if_lastex - erp->er_extoff; | 3605 | #else |
3611 | } else { | 3606 | gotp->br_startblock = 0xffffa5a5; |
3612 | base = &ifp->if_u1.if_extents[0]; | 3607 | #endif |
3613 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | 3608 | prevp->br_startoff = NULLFILEOFF; |
3614 | lastx = ifp->if_lastex; | 3609 | |
3610 | ep = xfs_iext_bno_to_ext(ifp, bno, &lastx); | ||
3611 | if (lastx > 0) { | ||
3612 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp); | ||
3615 | } | 3613 | } |
3616 | ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, | 3614 | if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) { |
3617 | eofp, lastxp, gotp, prevp); | 3615 | xfs_bmbt_get_all(ep, gotp); |
3618 | /* Convert lastx back to file-based index */ | 3616 | *eofp = 0; |
3619 | if (ifp->if_flags & XFS_IFEXTIREC) { | 3617 | } else { |
3620 | *lastxp += erp->er_extoff; | 3618 | if (lastx > 0) { |
3619 | *gotp = *prevp; | ||
3620 | } | ||
3621 | *eofp = 1; | ||
3622 | ep = NULL; | ||
3621 | } | 3623 | } |
3624 | *lastxp = lastx; | ||
3622 | return ep; | 3625 | return ep; |
3623 | } | 3626 | } |
3624 | 3627 | ||
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 580fa0758039..a16df2d435fe 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -4266,11 +4266,80 @@ xfs_iext_destroy( | |||
4266 | } | 4266 | } |
4267 | 4267 | ||
4268 | /* | 4268 | /* |
4269 | * Return a pointer to the extent record for file system block bno. | ||
4270 | */ | ||
4271 | xfs_bmbt_rec_t * /* pointer to found extent record */ | ||
4272 | xfs_iext_bno_to_ext( | ||
4273 | xfs_ifork_t *ifp, /* inode fork pointer */ | ||
4274 | xfs_fileoff_t bno, /* block number to search for */ | ||
4275 | xfs_extnum_t *idxp) /* index of target extent */ | ||
4276 | { | ||
4277 | xfs_bmbt_rec_t *base; /* pointer to first extent */ | ||
4278 | xfs_filblks_t blockcount = 0; /* number of blocks in extent */ | ||
4279 | xfs_bmbt_rec_t *ep = NULL; /* pointer to target extent */ | ||
4280 | xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ | ||
4281 | int high; /* upper boundry in search */ | ||
4282 | xfs_extnum_t idx = 0; /* index of target extent */ | ||
4283 | int low; /* lower boundry in search */ | ||
4284 | xfs_extnum_t nextents; /* number of file extents */ | ||
4285 | xfs_fileoff_t startoff = 0; /* start offset of extent */ | ||
4286 | |||
4287 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
4288 | if (nextents == 0) { | ||
4289 | *idxp = 0; | ||
4290 | return NULL; | ||
4291 | } | ||
4292 | low = 0; | ||
4293 | if (ifp->if_flags & XFS_IFEXTIREC) { | ||
4294 | /* Find target extent list */ | ||
4295 | int erp_idx = 0; | ||
4296 | erp = xfs_iext_bno_to_irec(ifp, bno, &erp_idx); | ||
4297 | base = erp->er_extbuf; | ||
4298 | high = erp->er_extcount - 1; | ||
4299 | } else { | ||
4300 | base = ifp->if_u1.if_extents; | ||
4301 | high = nextents - 1; | ||
4302 | } | ||
4303 | /* Binary search extent records */ | ||
4304 | while (low <= high) { | ||
4305 | idx = (low + high) >> 1; | ||
4306 | ep = base + idx; | ||
4307 | startoff = xfs_bmbt_get_startoff(ep); | ||
4308 | blockcount = xfs_bmbt_get_blockcount(ep); | ||
4309 | if (bno < startoff) { | ||
4310 | high = idx - 1; | ||
4311 | } else if (bno >= startoff + blockcount) { | ||
4312 | low = idx + 1; | ||
4313 | } else { | ||
4314 | /* Convert back to file-based extent index */ | ||
4315 | if (ifp->if_flags & XFS_IFEXTIREC) { | ||
4316 | idx += erp->er_extoff; | ||
4317 | } | ||
4318 | *idxp = idx; | ||
4319 | return ep; | ||
4320 | } | ||
4321 | } | ||
4322 | /* Convert back to file-based extent index */ | ||
4323 | if (ifp->if_flags & XFS_IFEXTIREC) { | ||
4324 | idx += erp->er_extoff; | ||
4325 | } | ||
4326 | if (bno >= startoff + blockcount) { | ||
4327 | if (++idx == nextents) { | ||
4328 | ep = NULL; | ||
4329 | } else { | ||
4330 | ep = xfs_iext_get_ext(ifp, idx); | ||
4331 | } | ||
4332 | } | ||
4333 | *idxp = idx; | ||
4334 | return ep; | ||
4335 | } | ||
4336 | |||
4337 | /* | ||
4269 | * Return a pointer to the indirection array entry containing the | 4338 | * Return a pointer to the indirection array entry containing the |
4270 | * extent record for filesystem block bno. Store the index of the | 4339 | * extent record for filesystem block bno. Store the index of the |
4271 | * target irec in *erp_idxp. | 4340 | * target irec in *erp_idxp. |
4272 | */ | 4341 | */ |
4273 | xfs_ext_irec_t * | 4342 | xfs_ext_irec_t * /* pointer to found extent record */ |
4274 | xfs_iext_bno_to_irec( | 4343 | xfs_iext_bno_to_irec( |
4275 | xfs_ifork_t *ifp, /* inode fork pointer */ | 4344 | xfs_ifork_t *ifp, /* inode fork pointer */ |
4276 | xfs_fileoff_t bno, /* block number to search for */ | 4345 | xfs_fileoff_t bno, /* block number to search for */ |
@@ -4278,7 +4347,7 @@ xfs_iext_bno_to_irec( | |||
4278 | { | 4347 | { |
4279 | xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ | 4348 | xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ |
4280 | xfs_ext_irec_t *erp_next; /* next indirection array entry */ | 4349 | xfs_ext_irec_t *erp_next; /* next indirection array entry */ |
4281 | xfs_extnum_t erp_idx; /* indirection array index */ | 4350 | int erp_idx; /* indirection array index */ |
4282 | int nlists; /* number of extent irec's (lists) */ | 4351 | int nlists; /* number of extent irec's (lists) */ |
4283 | int high; /* binary search upper limit */ | 4352 | int high; /* binary search upper limit */ |
4284 | int low; /* binary search lower limit */ | 4353 | int low; /* binary search lower limit */ |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 3c1df1d642fa..006396764cbc 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -478,6 +478,7 @@ void xfs_iext_indirect_to_direct(xfs_ifork_t *); | |||
478 | void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t); | 478 | void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t); |
479 | void xfs_iext_inline_to_direct(xfs_ifork_t *, int); | 479 | void xfs_iext_inline_to_direct(xfs_ifork_t *, int); |
480 | void xfs_iext_destroy(xfs_ifork_t *); | 480 | void xfs_iext_destroy(xfs_ifork_t *); |
481 | xfs_bmbt_rec_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *); | ||
481 | xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *); | 482 | xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *); |
482 | xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int); | 483 | xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int); |
483 | void xfs_iext_irec_init(xfs_ifork_t *); | 484 | void xfs_iext_irec_init(xfs_ifork_t *); |