Commit 8867bc9b authored by Mandy Kirkconnell's avatar Mandy Kirkconnell Committed by Nathan Scott

[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: default avatarMandy Kirkconnell <alkirkco@sgi.com>
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent 524fbf5d
...@@ -3575,10 +3575,11 @@ xfs_bmap_do_search_extents( ...@@ -3575,10 +3575,11 @@ xfs_bmap_do_search_extents(
} }
/* /*
* Call xfs_bmap_do_search_extents() to search for the extent * Search the extent records for the entry containing block bno.
* record containing block bno. If in multi-level in-core extent * If bno lies in a hole, point to the next entry. If bno lies
* allocation mode, find and extract the target extent buffer, * past eof, *eofp will be set, and *prevp will contain the last
* otherwise just use the direct extent list. * entry (null if none). Else, *lastxp will be set to the index
* of the found entry; *gotp will contain the entry.
*/ */
xfs_bmbt_rec_t * /* pointer to found extent entry */ xfs_bmbt_rec_t * /* pointer to found extent entry */
xfs_bmap_search_multi_extents( xfs_bmap_search_multi_extents(
...@@ -3589,36 +3590,38 @@ xfs_bmap_search_multi_extents( ...@@ -3589,36 +3590,38 @@ xfs_bmap_search_multi_extents(
xfs_bmbt_irec_t *gotp, /* out: extent entry found */ xfs_bmbt_irec_t *gotp, /* out: extent entry found */
xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */ xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
{ {
xfs_bmbt_rec_t *base; /* base of extent records */
xfs_bmbt_rec_t *ep; /* extent record pointer */ xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_ext_irec_t *erp = NULL; /* indirection array pointer */
xfs_extnum_t lastx; /* last extent index */ xfs_extnum_t lastx; /* last extent index */
xfs_extnum_t nextents; /* number of file extents */
/* /*
* For multi-level extent allocation mode, find the * Initialize the extent entry structure to catch access to
* target extent list and pass only the contiguous * uninitialized br_startblock field.
* list to xfs_bmap_do_search_extents. Convert lastx
* from a file extent index to an index within the
* target extent list.
*/ */
if (ifp->if_flags & XFS_IFEXTIREC) { gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL;
int erp_idx = 0; gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL;
erp = xfs_iext_bno_to_irec(ifp, bno, &erp_idx); gotp->br_state = XFS_EXT_INVALID;
base = erp->er_extbuf; #if XFS_BIG_BLKNOS
nextents = erp->er_extcount; gotp->br_startblock = 0xffffa5a5a5a5a5a5LL;
lastx = ifp->if_lastex - erp->er_extoff; #else
} else { gotp->br_startblock = 0xffffa5a5;
base = &ifp->if_u1.if_extents[0]; #endif
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); prevp->br_startoff = NULLFILEOFF;
lastx = ifp->if_lastex;
ep = xfs_iext_bno_to_ext(ifp, bno, &lastx);
if (lastx > 0) {
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp);
} }
ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
eofp, lastxp, gotp, prevp); xfs_bmbt_get_all(ep, gotp);
/* Convert lastx back to file-based index */ *eofp = 0;
if (ifp->if_flags & XFS_IFEXTIREC) { } else {
*lastxp += erp->er_extoff; if (lastx > 0) {
*gotp = *prevp;
}
*eofp = 1;
ep = NULL;
} }
*lastxp = lastx;
return ep; return ep;
} }
......
...@@ -4265,12 +4265,81 @@ xfs_iext_destroy( ...@@ -4265,12 +4265,81 @@ xfs_iext_destroy(
ifp->if_bytes = 0; ifp->if_bytes = 0;
} }
/*
* Return a pointer to the extent record for file system block bno.
*/
xfs_bmbt_rec_t * /* pointer to found extent record */
xfs_iext_bno_to_ext(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_fileoff_t bno, /* block number to search for */
xfs_extnum_t *idxp) /* index of target extent */
{
xfs_bmbt_rec_t *base; /* pointer to first extent */
xfs_filblks_t blockcount = 0; /* number of blocks in extent */
xfs_bmbt_rec_t *ep = NULL; /* pointer to target extent */
xfs_ext_irec_t *erp = NULL; /* indirection array pointer */
int high; /* upper boundry in search */
xfs_extnum_t idx = 0; /* index of target extent */
int low; /* lower boundry in search */
xfs_extnum_t nextents; /* number of file extents */
xfs_fileoff_t startoff = 0; /* start offset of extent */
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
if (nextents == 0) {
*idxp = 0;
return NULL;
}
low = 0;
if (ifp->if_flags & XFS_IFEXTIREC) {
/* Find target extent list */
int erp_idx = 0;
erp = xfs_iext_bno_to_irec(ifp, bno, &erp_idx);
base = erp->er_extbuf;
high = erp->er_extcount - 1;
} else {
base = ifp->if_u1.if_extents;
high = nextents - 1;
}
/* Binary search extent records */
while (low <= high) {
idx = (low + high) >> 1;
ep = base + idx;
startoff = xfs_bmbt_get_startoff(ep);
blockcount = xfs_bmbt_get_blockcount(ep);
if (bno < startoff) {
high = idx - 1;
} else if (bno >= startoff + blockcount) {
low = idx + 1;
} else {
/* Convert back to file-based extent index */
if (ifp->if_flags & XFS_IFEXTIREC) {
idx += erp->er_extoff;
}
*idxp = idx;
return ep;
}
}
/* Convert back to file-based extent index */
if (ifp->if_flags & XFS_IFEXTIREC) {
idx += erp->er_extoff;
}
if (bno >= startoff + blockcount) {
if (++idx == nextents) {
ep = NULL;
} else {
ep = xfs_iext_get_ext(ifp, idx);
}
}
*idxp = idx;
return ep;
}
/* /*
* Return a pointer to the indirection array entry containing the * Return a pointer to the indirection array entry containing the
* extent record for filesystem block bno. Store the index of the * extent record for filesystem block bno. Store the index of the
* target irec in *erp_idxp. * target irec in *erp_idxp.
*/ */
xfs_ext_irec_t * xfs_ext_irec_t * /* pointer to found extent record */
xfs_iext_bno_to_irec( xfs_iext_bno_to_irec(
xfs_ifork_t *ifp, /* inode fork pointer */ xfs_ifork_t *ifp, /* inode fork pointer */
xfs_fileoff_t bno, /* block number to search for */ xfs_fileoff_t bno, /* block number to search for */
...@@ -4278,7 +4347,7 @@ xfs_iext_bno_to_irec( ...@@ -4278,7 +4347,7 @@ xfs_iext_bno_to_irec(
{ {
xfs_ext_irec_t *erp = NULL; /* indirection array pointer */ xfs_ext_irec_t *erp = NULL; /* indirection array pointer */
xfs_ext_irec_t *erp_next; /* next indirection array entry */ xfs_ext_irec_t *erp_next; /* next indirection array entry */
xfs_extnum_t erp_idx; /* indirection array index */ int erp_idx; /* indirection array index */
int nlists; /* number of extent irec's (lists) */ int nlists; /* number of extent irec's (lists) */
int high; /* binary search upper limit */ int high; /* binary search upper limit */
int low; /* binary search lower limit */ int low; /* binary search lower limit */
......
...@@ -478,6 +478,7 @@ void xfs_iext_indirect_to_direct(xfs_ifork_t *); ...@@ -478,6 +478,7 @@ void xfs_iext_indirect_to_direct(xfs_ifork_t *);
void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t); void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t);
void xfs_iext_inline_to_direct(xfs_ifork_t *, int); void xfs_iext_inline_to_direct(xfs_ifork_t *, int);
void xfs_iext_destroy(xfs_ifork_t *); void xfs_iext_destroy(xfs_ifork_t *);
xfs_bmbt_rec_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *);
xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *); xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *);
xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int); xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int);
void xfs_iext_irec_init(xfs_ifork_t *); void xfs_iext_irec_init(xfs_ifork_t *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment