[XFS] There are a few problems with the new
authorMandy Kirkconnell <alkirkco@sgi.com>
Fri, 17 Mar 2006 06:25:04 +0000 (17:25 +1100)
committerNathan Scott <nathans@sgi.com>
Fri, 17 Mar 2006 06:25:04 +0000 (17:25 +1100)
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>
fs/xfs/xfs_bmap.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h

index 64a02eaf1dfedce1dd8731575750550fbedfc965..2d702e4a74a359235cc622c08d8ff64477d7a60c 100644 (file)
@@ -3575,10 +3575,11 @@ xfs_bmap_do_search_extents(
 }
 
 /*
- * Call xfs_bmap_do_search_extents() to search for the extent
- * record containing block bno. If in multi-level in-core extent
- * allocation mode, find and extract the target extent buffer,
- * otherwise just use the direct extent list.
+ * Search the extent records for the entry containing block bno.
+ * If bno lies in a hole, point to the next entry.  If bno lies
+ * past eof, *eofp will be set, and *prevp will contain the last
+ * 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_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 *prevp)         /* out: previous extent entry found */
 {
-       xfs_bmbt_rec_t  *base;          /* base of extent records */
        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    nextents;       /* number of file extents */
 
        /*
-        * For multi-level extent allocation mode, find the
-        * target extent list and pass only the contiguous
-        * list to xfs_bmap_do_search_extents. Convert lastx
-        * from a file extent index to an index within the
-        * target extent list.
+        * Initialize the extent entry structure to catch access to
+        * uninitialized br_startblock field.
         */
-       if (ifp->if_flags & XFS_IFEXTIREC) {
-               int     erp_idx = 0;
-               erp = xfs_iext_bno_to_irec(ifp, bno, &erp_idx);
-               base = erp->er_extbuf;
-               nextents = erp->er_extcount;
-               lastx = ifp->if_lastex - erp->er_extoff;
-       } else {
-               base = &ifp->if_u1.if_extents[0];
-               nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
-               lastx = ifp->if_lastex;
+       gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL;
+       gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL;
+       gotp->br_state = XFS_EXT_INVALID;
+#if XFS_BIG_BLKNOS
+       gotp->br_startblock = 0xffffa5a5a5a5a5a5LL;
+#else
+       gotp->br_startblock = 0xffffa5a5;
+#endif
+       prevp->br_startoff = NULLFILEOFF;
+
+       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,
-                                       eofp, lastxp, gotp, prevp);
-       /* Convert lastx back to file-based index */
-       if (ifp->if_flags & XFS_IFEXTIREC) {
-               *lastxp += erp->er_extoff;
+       if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
+               xfs_bmbt_get_all(ep, gotp);
+               *eofp = 0;
+       } else {
+               if (lastx > 0) {
+                       *gotp = *prevp;
+               }
+               *eofp = 1;
+               ep = NULL;
        }
+       *lastxp = lastx;
        return ep;
 }
 
index 580fa07580395631e80b0f3b613c72dcf0907a10..a16df2d435fe328ec42c36128a4bdd1f0633f930 100644 (file)
@@ -4265,12 +4265,81 @@ xfs_iext_destroy(
        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
  * extent record for filesystem block bno. Store the index of the
  * target irec in *erp_idxp.
  */
-xfs_ext_irec_t *
+xfs_ext_irec_t *                       /* pointer to found extent record */
 xfs_iext_bno_to_irec(
        xfs_ifork_t     *ifp,           /* inode fork pointer */
        xfs_fileoff_t   bno,            /* block number to search for */
@@ -4278,7 +4347,7 @@ xfs_iext_bno_to_irec(
 {
        xfs_ext_irec_t  *erp = NULL;    /* indirection array pointer */
        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             high;           /* binary search upper limit */
        int             low;            /* binary search lower limit */
index 3c1df1d642fa82fa608cd9d53248ba599baddc8b..006396764cbc1a2e9d85f53e07713a7390e4ac1f 100644 (file)
@@ -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_inline_to_direct(xfs_ifork_t *, int);
 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_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int);
 void           xfs_iext_irec_init(xfs_ifork_t *);