aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorMandy Kirkconnell <alkirkco@sgi.com>2006-03-17 01:25:04 -0500
committerNathan Scott <nathans@sgi.com>2006-03-17 01:25:04 -0500
commit8867bc9bf0aed7181aa72c7c938c6ce830b75166 (patch)
treeae2dcc3a986e4e48fd81605f109be44c29362edd /fs/xfs
parent524fbf5dd1b25acffe6f8a4ed5f3cce1023cfdb8 (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>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_bmap.c57
-rw-r--r--fs/xfs/xfs_inode.c73
-rw-r--r--fs/xfs/xfs_inode.h1
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 */
3583xfs_bmbt_rec_t * /* pointer to found extent entry */ 3584xfs_bmbt_rec_t * /* pointer to found extent entry */
3584xfs_bmap_search_multi_extents( 3585xfs_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 */
4271xfs_bmbt_rec_t * /* pointer to found extent record */
4272xfs_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 */
4273xfs_ext_irec_t * 4342xfs_ext_irec_t * /* pointer to found extent record */
4274xfs_iext_bno_to_irec( 4343xfs_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 *);
478void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t); 478void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t);
479void xfs_iext_inline_to_direct(xfs_ifork_t *, int); 479void xfs_iext_inline_to_direct(xfs_ifork_t *, int);
480void xfs_iext_destroy(xfs_ifork_t *); 480void xfs_iext_destroy(xfs_ifork_t *);
481xfs_bmbt_rec_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *);
481xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *); 482xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *);
482xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int); 483xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int);
483void xfs_iext_irec_init(xfs_ifork_t *); 484void xfs_iext_irec_init(xfs_ifork_t *);