summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-10-10 12:58:08 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-10-19 10:39:24 -0700
commit830b3b25ea334e4e3b17863f5c9d938f6ff10452 (patch)
treefed0bffef5137ce967e60aaa2c8bbddd5eaa1b7e
parent79fa46b286e0580677545aa4571a6fab17671f09 (diff)
xfs: refactor xfs_iread_extents to use xfs_btree_visit_blocksbtree-fixes_2019-10-19
xfs_iread_extents open-codes everything in xfs_btree_visit_blocks, so refactor the btree helper to be able to iterate only the records on level 0, then port iread_extents to use it. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c191
-rw-r--r--fs/xfs/libxfs/xfs_btree.c8
-rw-r--r--fs/xfs/libxfs/xfs_btree.h4
-rw-r--r--fs/xfs/scrub/bitmap.c2
-rw-r--r--fs/xfs/scrub/rmap_repair.c10
5 files changed, 92 insertions, 123 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index a281beee664f..9695a4f6101d 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1154,6 +1154,65 @@ trans_cancel:
* Internal and external extent tree search functions.
*/
+struct xfs_iread_state {
+ struct xfs_iext_cursor icur;
+ struct xfs_ifork *ifp;
+ xfs_extnum_t loaded;
+ xfs_extnum_t nextents;
+ int state;
+};
+
+/* Stuff every bmbt record from this block into the incore extent map. */
+static int
+xfs_iread_bmbt_block(
+ struct xfs_btree_cur *cur,
+ int level,
+ void *priv)
+{
+ struct xfs_iread_state *ir = priv;
+ struct xfs_mount *mp = cur->bc_mp;
+ struct xfs_inode *ip = cur->bc_private.b.ip;
+ struct xfs_btree_block *block;
+ struct xfs_buf *bp;
+ struct xfs_bmbt_rec *frp;
+ xfs_extnum_t num_recs;
+ xfs_extnum_t j;
+ int whichfork = cur->bc_private.b.whichfork;
+
+ block = xfs_btree_get_block(cur, level, &bp);
+
+ /* Abort if we find more records than nextents. */
+ num_recs = xfs_btree_get_numrecs(block);
+ if (unlikely(ir->loaded + num_recs > ir->nextents)) {
+ xfs_warn(ip->i_mount, "corrupt dinode %Lu, (btree extents).",
+ (unsigned long long) ip->i_ino);
+ xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, block,
+ sizeof(*block), __this_address);
+ return -EFSCORRUPTED;
+ }
+
+ /* Copy records into the incore cache. */
+ frp = XFS_BMBT_REC_ADDR(mp, block, 1);
+ for (j = 0; j < num_recs; j++, frp++, ir->loaded++) {
+ struct xfs_bmbt_irec new;
+ xfs_failaddr_t fa;
+
+ xfs_bmbt_disk_get_all(frp, &new);
+ fa = xfs_bmap_validate_extent(ip, whichfork, &new);
+ if (fa) {
+ xfs_inode_verifier_error(ip, -EFSCORRUPTED,
+ "xfs_iread_extents(2)", frp,
+ sizeof(*frp), fa);
+ return -EFSCORRUPTED;
+ }
+ xfs_iext_insert(ip, &ir->icur, &new, ir->state);
+ trace_xfs_read_extent(ip, &ir->icur, ir->state, _THIS_IP_);
+ xfs_iext_next(ir->ifp, &ir->icur);
+ }
+
+ return 0;
+}
+
/*
* Read in extents from a btree-format inode.
*/
@@ -1163,136 +1222,40 @@ xfs_iread_extents(
struct xfs_inode *ip,
int whichfork)
{
+ struct xfs_iread_state ir = {
+ .state = xfs_bmap_fork_to_state(whichfork),
+ .ifp = XFS_IFORK_PTR(ip, whichfork),
+ .nextents = XFS_IFORK_NEXTENTS(ip, whichfork),
+ };
struct xfs_mount *mp = ip->i_mount;
- int state = xfs_bmap_fork_to_state(whichfork);
- struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
- xfs_extnum_t nextents = XFS_IFORK_NEXTENTS(ip, whichfork);
- struct xfs_btree_block *block = ifp->if_broot;
- struct xfs_iext_cursor icur;
- struct xfs_bmbt_irec new;
- xfs_fsblock_t bno;
- struct xfs_buf *bp;
- xfs_extnum_t i, j;
- int level;
- __be64 *pp;
+ struct xfs_btree_cur *cur;
int error;
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
- return -EFSCORRUPTED;
- }
-
- /*
- * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
- */
- level = be16_to_cpu(block->bb_level);
- if (unlikely(level == 0)) {
- XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
- return -EFSCORRUPTED;
- }
- pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
- bno = be64_to_cpu(*pp);
-
- /*
- * Go down the tree until leaf level is reached, following the first
- * pointer (leftmost) at each level.
- */
- while (level-- > 0) {
- error = xfs_btree_read_bufl(mp, tp, bno, &bp,
- XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
- if (error)
- goto out;
- block = XFS_BUF_TO_BLOCK(bp);
- if (level == 0)
- break;
- pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
- bno = be64_to_cpu(*pp);
- XFS_WANT_CORRUPTED_GOTO(mp,
- xfs_verify_fsbno(mp, bno), out_brelse);
- xfs_trans_brelse(tp, bp);
+ error = -EFSCORRUPTED;
+ goto out;
}
- /*
- * Here with bp and block set to the leftmost leaf node in the tree.
- */
- i = 0;
- xfs_iext_first(ifp, &icur);
-
- /*
- * Loop over all leaf nodes. Copy information to the extent records.
- */
- for (;;) {
- xfs_bmbt_rec_t *frp;
- xfs_fsblock_t nextbno;
- xfs_extnum_t num_recs;
-
- num_recs = xfs_btree_get_numrecs(block);
- if (unlikely(i + num_recs > nextents)) {
- xfs_warn(ip->i_mount,
- "corrupt dinode %Lu, (btree extents).",
- (unsigned long long) ip->i_ino);
- xfs_inode_verifier_error(ip, -EFSCORRUPTED,
- __func__, block, sizeof(*block),
- __this_address);
- error = -EFSCORRUPTED;
- goto out_brelse;
- }
- /*
- * Read-ahead the next leaf block, if any.
- */
- nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
- if (nextbno != NULLFSBLOCK)
- xfs_btree_reada_bufl(mp, nextbno, 1,
- &xfs_bmbt_buf_ops);
- /*
- * Copy records into the extent records.
- */
- frp = XFS_BMBT_REC_ADDR(mp, block, 1);
- for (j = 0; j < num_recs; j++, frp++, i++) {
- xfs_failaddr_t fa;
-
- xfs_bmbt_disk_get_all(frp, &new);
- fa = xfs_bmap_validate_extent(ip, whichfork, &new);
- if (fa) {
- error = -EFSCORRUPTED;
- xfs_inode_verifier_error(ip, error,
- "xfs_iread_extents(2)",
- frp, sizeof(*frp), fa);
- goto out_brelse;
- }
- xfs_iext_insert(ip, &icur, &new, state);
- trace_xfs_read_extent(ip, &icur, state, _THIS_IP_);
- xfs_iext_next(ifp, &icur);
- }
- xfs_trans_brelse(tp, bp);
- bno = nextbno;
- /*
- * If we've reached the end, stop.
- */
- if (bno == NULLFSBLOCK)
- break;
- error = xfs_btree_read_bufl(mp, tp, bno, &bp,
- XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
- if (error)
- goto out;
- block = XFS_BUF_TO_BLOCK(bp);
- }
+ cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
+ error = xfs_btree_visit_blocks(cur, xfs_iread_bmbt_block,
+ XFS_BTREE_VISIT_RECORDS_ONLY, &ir);
+ xfs_btree_del_cursor(cur, error);
+ if (error)
+ goto out;
- if (i != XFS_IFORK_NEXTENTS(ip, whichfork)) {
+ if (ir.loaded != ir.nextents) {
error = -EFSCORRUPTED;
goto out;
}
- ASSERT(i == xfs_iext_count(ifp));
+ ASSERT(ir.loaded == xfs_iext_count(ir.ifp));
- ifp->if_flags |= XFS_IFEXTENTS;
+ ir.ifp->if_flags |= XFS_IFEXTENTS;
return 0;
-
-out_brelse:
- xfs_trans_brelse(tp, bp);
out:
- xfs_iext_destroy(ifp);
+ xfs_iext_destroy(ir.ifp);
return error;
}
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 498f5cde0bb1..b9bdc46ae6a2 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -4393,6 +4393,7 @@ int
xfs_btree_visit_blocks(
struct xfs_btree_cur *cur,
xfs_btree_visit_blocks_fn fn,
+ unsigned int flags,
void *data)
{
union xfs_btree_ptr lptr;
@@ -4420,6 +4421,9 @@ xfs_btree_visit_blocks(
xfs_btree_copy_ptrs(cur, &lptr, ptr, 1);
}
+ if ((flags & XFS_BTREE_VISIT_RECORDS_ONLY) && level > 0)
+ continue;
+
/* for each buffer in the level */
do {
error = xfs_btree_visit_block(cur, level, fn, data);
@@ -4519,7 +4523,7 @@ xfs_btree_change_owner(
bbcoi.new_owner = new_owner;
bbcoi.buffer_list = buffer_list;
- return xfs_btree_visit_blocks(cur, xfs_btree_block_change_owner,
+ return xfs_btree_visit_blocks(cur, xfs_btree_block_change_owner, 0,
&bbcoi);
}
@@ -4971,7 +4975,7 @@ xfs_btree_count_blocks(
xfs_extlen_t *blocks)
{
*blocks = 0;
- return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper,
+ return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper, 0,
blocks);
}
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index e3982db5901b..870cc691d677 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -511,8 +511,10 @@ int xfs_btree_query_all(struct xfs_btree_cur *cur, xfs_btree_query_range_fn fn,
typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level,
void *data);
+/* Only visit record blocks. */
+#define XFS_BTREE_VISIT_RECORDS_ONLY (0x1)
int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
- xfs_btree_visit_blocks_fn fn, void *data);
+ xfs_btree_visit_blocks_fn fn, unsigned int flags, void *data);
int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks);
diff --git a/fs/xfs/scrub/bitmap.c b/fs/xfs/scrub/bitmap.c
index 3f6e0c72909f..d914e4c81134 100644
--- a/fs/xfs/scrub/bitmap.c
+++ b/fs/xfs/scrub/bitmap.c
@@ -252,7 +252,7 @@ xbitmap_set_btblocks(
struct xbitmap *bitmap,
struct xfs_btree_cur *cur)
{
- return xfs_btree_visit_blocks(cur, xbitmap_collect_btblock, bitmap);
+ return xfs_btree_visit_blocks(cur, xbitmap_collect_btblock, 0, bitmap);
}
/* How many bits are set in this bitmap? */
diff --git a/fs/xfs/scrub/rmap_repair.c b/fs/xfs/scrub/rmap_repair.c
index 2bae3ce405ba..241cc5db624d 100644
--- a/fs/xfs/scrub/rmap_repair.c
+++ b/fs/xfs/scrub/rmap_repair.c
@@ -427,7 +427,7 @@ xrep_rmap_scan_bmbt(
}
/* Record all the blocks in the bmbt itself. */
- error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_bmbt_block, rf);
+ error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_bmbt_block, 0, rf);
if (error)
goto out_cur;
xfs_btree_del_cursor(cur, error);
@@ -685,7 +685,7 @@ xrep_rmap_find_inode_rmaps(
if (xfs_sb_version_hasfinobt(&sc->mp->m_sb)) {
cur = xfs_inobt_init_cursor(sc->mp, sc->tp, sc->sa.agi_bp,
sc->sa.agno, XFS_BTNUM_FINO);
- error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_btblock,
+ error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_btblock, 0,
&ri.inobt_blocks);
xfs_btree_del_cursor(cur, error);
if (error)
@@ -751,7 +751,7 @@ xrep_rmap_find_refcount_rmaps(
/* refcountbt */
cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
sc->sa.agno);
- error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_btblock,
+ error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_btblock, 0,
&refcountbt_blocks);
if (error) {
xfs_btree_del_cursor(cur, error);
@@ -917,7 +917,7 @@ xrep_rmap_try_reserve(
/* Set all the bnobt blocks in the bitmap. */
cur = xfs_allocbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
sc->sa.agno, XFS_BTNUM_BNO);
- error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_btblock,
+ error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_btblock, 0,
freesp_blocks);
xfs_btree_del_cursor(cur, error);
if (error)
@@ -926,7 +926,7 @@ xrep_rmap_try_reserve(
/* Set all the cntbt blocks in the bitmap. */
cur = xfs_allocbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
sc->sa.agno, XFS_BTNUM_CNT);
- error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_btblock,
+ error = xfs_btree_visit_blocks(cur, xrep_rmap_visit_btblock, 0,
freesp_blocks);
xfs_btree_del_cursor(cur, error);
if (error)