xfs: introduce xfs_bmapi_read()
authorDave Chinner <dchinner@redhat.com>
Sun, 18 Sep 2011 20:40:45 +0000 (20:40 +0000)
committerAlex Elder <aelder@sgi.com>
Wed, 12 Oct 2011 02:15:03 +0000 (21:15 -0500)
xfs_bmapi() currently handles both extent map reading and
allocation. As a result, the code is littered with "if (wr)"
branches to conditionally do allocation operations if required.
This makes the code much harder to follow and causes significant
indent issues with the code.

Given that read mapping is much simpler than allocation, we can
split out read mapping from xfs_bmapi() and reuse the logic that
we have already factored out do do all the hard work of handling the
extent map manipulations. The results in a much simpler function for
the common extent read operations, and will allow the allocation
code to be simplified in another commit.

Once xfs_bmapi_read() is implemented, convert all the callers of
xfs_bmapi() that are only reading extents to use the new function.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
13 files changed:
fs/xfs/xfs_aops.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap.h
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_dir2_leaf.c
fs/xfs/xfs_dquot.c
fs/xfs/xfs_file.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_vnodeops.c

index 22aadf667862d28cd3e6856b73264e4888e60373..11b2aad982d46b0704ade9aa02347d712c0cc23f 100644 (file)
@@ -315,8 +315,8 @@ xfs_map_blocks(
                count = mp->m_maxioffset - offset;
        end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
        offset_fsb = XFS_B_TO_FSBT(mp, offset);
-       error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb,
-                         bmapi_flags,  NULL, 0, imap, &nimaps, NULL);
+       error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
+                               imap, &nimaps, bmapi_flags);
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
        if (error)
@@ -1138,8 +1138,8 @@ __xfs_get_blocks(
        end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
        offset_fsb = XFS_B_TO_FSBT(mp, offset);
 
-       error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb,
-                         XFS_BMAPI_ENTIRE,  NULL, 0, &imap, &nimaps, NULL);
+       error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
+                               &imap, &nimaps, XFS_BMAPI_ENTIRE);
        if (error)
                goto out_unlock;
 
index c7dab0c0bdda3d3cd45a2317849c090c8811cbf8..41ef02b7185abb4762161a429b82d91fc67b1de7 100644 (file)
@@ -1963,10 +1963,9 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
        lblkno = args->rmtblkno;
        while (valuelen > 0) {
                nmap = ATTR_RMTVALUE_MAPSIZE;
-               error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno,
-                                 args->rmtblkcnt,
-                                 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
-                                 NULL, 0, map, &nmap, NULL);
+               error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
+                                      args->rmtblkcnt, map, &nmap,
+                                      XFS_BMAPI_ATTRFORK);
                if (error)
                        return(error);
                ASSERT(nmap >= 1);
@@ -2092,14 +2091,11 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
                 */
                xfs_bmap_init(args->flist, args->firstblock);
                nmap = 1;
-               error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno,
-                                 args->rmtblkcnt,
-                                 XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
-                                 args->firstblock, 0, &map, &nmap,
-                                 NULL);
-               if (error) {
+               error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
+                                      args->rmtblkcnt, &map, &nmap,
+                                      XFS_BMAPI_ATTRFORK);
+               if (error)
                        return(error);
-               }
                ASSERT(nmap == 1);
                ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
                       (map.br_startblock != HOLESTARTBLOCK));
@@ -2155,16 +2151,12 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
                /*
                 * Try to remember where we decided to put the value.
                 */
-               xfs_bmap_init(args->flist, args->firstblock);
                nmap = 1;
-               error = xfs_bmapi(NULL, args->dp, (xfs_fileoff_t)lblkno,
-                                       args->rmtblkcnt,
-                                       XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
-                                       args->firstblock, 0, &map, &nmap,
-                                       args->flist);
-               if (error) {
+               error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
+                                      args->rmtblkcnt, &map, &nmap,
+                                      XFS_BMAPI_ATTRFORK);
+               if (error)
                        return(error);
-               }
                ASSERT(nmap == 1);
                ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
                       (map.br_startblock != HOLESTARTBLOCK));
index 58c3add07b65b9c68beb55db81c69b79f86046da..d4906e7c97873b302201cddf442bdc5eeb54a29d 100644 (file)
@@ -2926,9 +2926,8 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
                 * Try to remember where we decided to put the value.
                 */
                nmap = 1;
-               error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt,
-                                       XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
-                                       NULL, 0, &map, &nmap, NULL);
+               error = xfs_bmapi_read(dp, (xfs_fileoff_t)tblkno, tblkcnt,
+                                      &map, &nmap, XFS_BMAPI_ATTRFORK);
                if (error) {
                        return(error);
                }
index 59f63949d3bc6ea1058bd0eae0f966ebdfaad00a..fc5acf0b921e252bc6f27d8866c66af23296a8d1 100644 (file)
@@ -4349,6 +4349,98 @@ xfs_bmapi_update_map(
        *map = mval;
 }
 
+/*
+ * Map file blocks to filesystem blocks without allocation.
+ */
+int
+xfs_bmapi_read(
+       struct xfs_inode        *ip,
+       xfs_fileoff_t           bno,
+       xfs_filblks_t           len,
+       struct xfs_bmbt_irec    *mval,
+       int                     *nmap,
+       int                     flags)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_ifork        *ifp;
+       struct xfs_bmbt_irec    got;
+       struct xfs_bmbt_irec    prev;
+       xfs_fileoff_t           obno;
+       xfs_fileoff_t           end;
+       xfs_extnum_t            lastx;
+       int                     error;
+       int                     eof;
+       int                     n = 0;
+       int                     whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
+                                               XFS_ATTR_FORK : XFS_DATA_FORK;
+
+       ASSERT(*nmap >= 1);
+       ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE|
+                          XFS_BMAPI_IGSTATE)));
+
+       if (unlikely(XFS_TEST_ERROR(
+           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
+            mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
+               XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp);
+               return XFS_ERROR(EFSCORRUPTED);
+       }
+
+       if (XFS_FORCED_SHUTDOWN(mp))
+               return XFS_ERROR(EIO);
+
+       XFS_STATS_INC(xs_blk_mapr);
+
+       ifp = XFS_IFORK_PTR(ip, whichfork);
+       ASSERT(ifp->if_ext_max ==
+              XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
+
+       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
+               error = xfs_iread_extents(NULL, ip, whichfork);
+               if (error)
+                       return error;
+       }
+
+       xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev);
+       end = bno + len;
+       obno = bno;
+
+       while (bno < end && n < *nmap) {
+               /* Reading past eof, act as though there's a hole up to end. */
+               if (eof)
+                       got.br_startoff = end;
+               if (got.br_startoff > bno) {
+                       /* Reading in a hole.  */
+                       mval->br_startoff = bno;
+                       mval->br_startblock = HOLESTARTBLOCK;
+                       mval->br_blockcount =
+                               XFS_FILBLKS_MIN(len, got.br_startoff - bno);
+                       mval->br_state = XFS_EXT_NORM;
+                       bno += mval->br_blockcount;
+                       len -= mval->br_blockcount;
+                       mval++;
+                       n++;
+                       continue;
+               }
+
+               /* set up the extent map to return. */
+               xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags);
+               xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags);
+
+               /* If we're done, stop now. */
+               if (bno >= end || n >= *nmap)
+                       break;
+
+               /* Else go on to the next record. */
+               if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t))
+                       xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got);
+               else
+                       eof = 1;
+       }
+       *nmap = n;
+       return 0;
+}
+
 /*
  * Map file blocks to filesystem blocks.
  * File range is given by the bno/len pair.
@@ -5490,10 +5582,9 @@ xfs_getbmap(
 
        do {
                nmap = (nexleft > subnex) ? subnex : nexleft;
-               error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
-                                 XFS_BB_TO_FSB(mp, bmv->bmv_length),
-                                 bmapi_flags, NULL, 0, map, &nmap,
-                                 NULL);
+               error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
+                                      XFS_BB_TO_FSB(mp, bmv->bmv_length),
+                                      map, &nmap, bmapi_flags);
                if (error)
                        goto out_free_map;
                ASSERT(nmap <= subnex);
@@ -6084,9 +6175,8 @@ xfs_bmap_punch_delalloc_range(
                 * trying to remove a real extent (which requires a
                 * transaction) or a hole, which is probably a bad idea...
                 */
-               error = xfs_bmapi(NULL, ip, start_fsb, 1,
-                               XFS_BMAPI_ENTIRE,  NULL, 0, &imap,
-                               &nimaps, NULL);
+               error = xfs_bmapi_read(ip, start_fsb, 1, &imap, &nimaps,
+                                      XFS_BMAPI_ENTIRE);
 
                if (error) {
                        /* something screwed, just bail */
index c62234bde053de008d13d41d40d92f133649e446..16257c6eba71781f61c99307d08291ebba50287f 100644 (file)
@@ -294,6 +294,10 @@ xfs_bmapi(
        int                     *nmap,          /* i/o: mval size/count */
        xfs_bmap_free_t         *flist);        /* i/o: list extents to free */
 
+int    xfs_bmapi_read(struct xfs_inode *ip, xfs_fileoff_t bno,
+               xfs_filblks_t len, struct xfs_bmbt_irec *mval,
+               int *nmap, int flags);
+
 /*
  * Map file blocks to filesystem blocks, simple version.
  * One block only, read-only.
index ee9d5427fcd4c2892577824417a186a59d8e9d88..44dfa39099efbc9aa15f839645f5a70822185d1c 100644 (file)
@@ -1995,11 +1995,10 @@ xfs_da_do_buf(
                } else {
                        mapp = kmem_alloc(sizeof(*mapp) * nfsb, KM_SLEEP);
                        nmap = nfsb;
-                       if ((error = xfs_bmapi(trans, dp, (xfs_fileoff_t)bno,
-                                       nfsb,
-                                       XFS_BMAPI_METADATA |
-                                               xfs_bmapi_aflag(whichfork),
-                                       NULL, 0, mapp, &nmap, NULL)))
+                       error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb,
+                                              mapp, &nmap,
+                                              xfs_bmapi_aflag(whichfork));
+                       if (error)
                                goto exit0;
                }
        } else {
index ca2386d82cdfce8817d723eba11ea7da9fa27ed7..66e108f561a39aa9efcc1d4199bce74e0068855d 100644 (file)
@@ -888,12 +888,10 @@ xfs_dir2_leaf_getdents(
                                 * we already have in the table.
                                 */
                                nmap = map_size - map_valid;
-                               error = xfs_bmapi(NULL, dp,
-                                       map_off,
+                               error = xfs_bmapi_read(dp, map_off,
                                        xfs_dir2_byte_to_da(mp,
                                                XFS_DIR2_LEAF_OFFSET) - map_off,
-                                       XFS_BMAPI_METADATA, NULL, 0,
-                                       &map[map_valid], &nmap, NULL);
+                                       &map[map_valid], &nmap, 0);
                                /*
                                 * Don't know if we should ignore this or
                                 * try to return an error.
index 0c5fe66ce92be75d3b337cdd27b99ae09a6b0b7e..c377961657ee24245703a1f1c74d0a193eb33846 100644 (file)
@@ -488,9 +488,8 @@ xfs_qm_dqtobp(
        /*
         * Find the block map; no allocations yet
         */
-       error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset,
-                         XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
-                         NULL, 0, &map, &nmaps, NULL);
+       error = xfs_bmapi_read(quotip, dqp->q_fileoffset,
+                              XFS_DQUOT_CLUSTER_SIZE_FSB, &map, &nmaps, 0);
 
        xfs_iunlock(quotip, XFS_ILOCK_SHARED);
        if (error)
index 06fe97e56e487090062947b0c704ccda6ce00800..558543c146b3a0c0450dfc35b3fe94fef1259aff 100644 (file)
@@ -509,11 +509,9 @@ xfs_zero_last_block(
 
        last_fsb = XFS_B_TO_FSBT(mp, isize);
        nimaps = 1;
-       error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap,
-                         &nimaps, NULL);
-       if (error) {
+       error = xfs_bmapi_read(ip, last_fsb, 1, &imap, &nimaps, 0);
+       if (error)
                return error;
-       }
        ASSERT(nimaps > 0);
        /*
         * If the block underlying isize is just a hole, then there
@@ -604,8 +602,8 @@ xfs_zero_eof(
        while (start_zero_fsb <= end_zero_fsb) {
                nimaps = 1;
                zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
-               error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb,
-                                 0, NULL, 0, &imap, &nimaps, NULL);
+               error = xfs_bmapi_read(ip, start_zero_fsb, zero_count_fsb,
+                                         &imap, &nimaps, 0);
                if (error) {
                        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
                        return error;
index d689253fdfdad3760ec1f4226d1cbec55477d217..f690d3a10b34a96bc3057ea40640a073eaac0f7f 100644 (file)
@@ -1187,6 +1187,7 @@ xfs_isize_check(
        xfs_fileoff_t           map_first;
        int                     nimaps;
        xfs_bmbt_irec_t         imaps[2];
+       int                     error;
 
        if (!S_ISREG(ip->i_d.di_mode))
                return;
@@ -1203,13 +1204,12 @@ xfs_isize_check(
         * The filesystem could be shutting down, so bmapi may return
         * an error.
         */
-       if (xfs_bmapi(NULL, ip, map_first,
+       error = xfs_bmapi_read(ip, map_first,
                         (XFS_B_TO_FSB(mp,
-                                      (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) -
-                         map_first),
-                        XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps,
-                        NULL))
-           return;
+                              (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - map_first),
+                        imaps, &nimaps, XFS_BMAPI_ENTIRE);
+       if (error)
+               return;
        ASSERT(nimaps == 1);
        ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK);
 }
index 091d82b94c4de518208d8eebc37abe4a7f3d4f1d..544f053860f15bff7d5730ee28970cb17f8080aa 100644 (file)
@@ -300,8 +300,8 @@ xfs_iomap_eof_want_preallocate(
        while (count_fsb > 0) {
                imaps = nimaps;
                firstblock = NULLFSBLOCK;
-               error = xfs_bmapi(NULL, ip, start_fsb, count_fsb, 0,
-                                 &firstblock, 0, imap, &imaps, NULL);
+               error = xfs_bmapi_read(ip, start_fsb, count_fsb, imap, &imaps,
+                                      0);
                if (error)
                        return error;
                for (n = 0; n < imaps; n++) {
index f51bef885e6d3c5b1761c205f5ddccd81eb01616..ddaf97a57ec68471ce664e6a0724bfdd185ea113 100644 (file)
@@ -1347,11 +1347,8 @@ xfs_qm_dqiterate(
                 * the inode is never added to the transaction.
                 */
                xfs_ilock(qip, XFS_ILOCK_SHARED);
-               error = xfs_bmapi(NULL, qip, lblkno,
-                                 maxlblkcnt - lblkno,
-                                 XFS_BMAPI_METADATA,
-                                 NULL,
-                                 0, map, &nmaps, NULL);
+               error = xfs_bmapi_read(qip, lblkno, maxlblkcnt - lblkno,
+                                      map, &nmaps, 0);
                xfs_iunlock(qip, XFS_ILOCK_SHARED);
                if (error)
                        break;
index 0d1caec873a13f237b84d79eb4cada61d386d1d1..63874a87b3782fd83ff2138e01ce2fb75d215374 100644 (file)
@@ -72,8 +72,8 @@ xfs_readlink_bmap(
        xfs_buf_t       *bp;
        int             error = 0;
 
-       error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0,
-                       mval, &nmaps, NULL);
+       error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, pathlen), mval, &nmaps,
+                              0);
        if (error)
                goto out;
 
@@ -178,8 +178,7 @@ xfs_free_eofblocks(
 
        nimaps = 1;
        xfs_ilock(ip, XFS_ILOCK_SHARED);
-       error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0,
-                         NULL, 0, &imap, &nimaps, NULL);
+       error = xfs_bmapi_read(ip, end_fsb, map_len, &imap, &nimaps, 0);
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
        if (!error && (nimaps != 0) &&
@@ -297,9 +296,9 @@ xfs_inactive_symlink_rmt(
        done = 0;
        xfs_bmap_init(&free_list, &first_block);
        nmaps = ARRAY_SIZE(mval);
-       if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size),
-                       XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps,
-                       &free_list)))
+       error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, size),
+                               mval, &nmaps, 0);
+       if (error)
                goto error0;
        /*
         * Invalidate the block(s).
@@ -1981,8 +1980,7 @@ xfs_zero_remaining_bytes(
        for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
                offset_fsb = XFS_B_TO_FSBT(mp, offset);
                nimap = 1;
-               error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0,
-                       NULL, 0, &imap, &nimap, NULL);
+               error = xfs_bmapi_read(ip, offset_fsb, 1, &imap, &nimap, 0);
                if (error || nimap < 1)
                        break;
                ASSERT(imap.br_blockcount >= 1);
@@ -2101,8 +2099,8 @@ xfs_free_file_space(
         */
        if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
                nimap = 1;
-               error = xfs_bmapi(NULL, ip, startoffset_fsb,
-                       1, 0, NULL, 0, &imap, &nimap, NULL);
+               error = xfs_bmapi_read(ip, startoffset_fsb, 1,
+                                       &imap, &nimap, 0);
                if (error)
                        goto out_unlock_iolock;
                ASSERT(nimap == 0 || nimap == 1);
@@ -2116,8 +2114,8 @@ xfs_free_file_space(
                                startoffset_fsb += mp->m_sb.sb_rextsize - mod;
                }
                nimap = 1;
-               error = xfs_bmapi(NULL, ip, endoffset_fsb - 1,
-                       1, 0, NULL, 0, &imap, &nimap, NULL);
+               error = xfs_bmapi_read(ip, endoffset_fsb - 1, 1,
+                                       &imap, &nimap, 0);
                if (error)
                        goto out_unlock_iolock;
                ASSERT(nimap == 0 || nimap == 1);