From f6b428a46d60186a38105c71fa435f31240721f9 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:31 -0700 Subject: xfs: track active state of allocation btree cursors The upcoming allocation algorithm update searches multiple allocation btree cursors concurrently. As such, it requires an active state to track when a particular cursor should continue searching. While active state will be modified based on higher level logic, we can define base functionality based on the result of allocation btree lookups. Define an active flag in the private area of the btree cursor. Update it based on the result of lookups in the existing allocation btree helpers. Finally, provide a new helper to query the current state. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 533b04aaf6f6..0ecc142c833b 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -146,9 +146,13 @@ xfs_alloc_lookup_eq( xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */ { + int error; + cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; - return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); + error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); + cur->bc_private.a.priv.abt.active = (*stat == 1); + return error; } /* @@ -162,9 +166,13 @@ xfs_alloc_lookup_ge( xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */ { + int error; + cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; - return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); + error = xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); + cur->bc_private.a.priv.abt.active = (*stat == 1); + return error; } /* @@ -178,9 +186,19 @@ xfs_alloc_lookup_le( xfs_extlen_t len, /* length of extent */ int *stat) /* success/failure */ { + int error; cur->bc_rec.a.ar_startblock = bno; cur->bc_rec.a.ar_blockcount = len; - return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); + error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); + cur->bc_private.a.priv.abt.active = (*stat == 1); + return error; +} + +static inline bool +xfs_alloc_cur_active( + struct xfs_btree_cur *cur) +{ + return cur && cur->bc_private.a.priv.abt.active; } /* -- cgit v1.2.3-70-g09d2 From f5e7dbea1e3ecc27f05e8cc83614c206903cc97a Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:31 -0700 Subject: xfs: introduce allocation cursor data structure Introduce a new allocation cursor data structure to encapsulate the various states and structures used to perform an extent allocation. This structure will eventually be used to track overall allocation state across different search algorithms on both free space btrees. To start, include the three btree cursors (one for the cntbt and two for the bnobt left/right search) used by the near mode allocation algorithm and refactor the cursor setup and teardown code into helpers. This slightly changes cursor memory allocation patterns, but otherwise makes no functional changes to the allocation algorithm. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong [darrick: fix sparse complaints] Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 318 ++++++++++++++++++++++++---------------------- 1 file changed, 163 insertions(+), 155 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 0ecc142c833b..664e2ad72542 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -710,8 +710,71 @@ xfs_alloc_update_counters( } /* - * Allocation group level functions. + * Block allocation algorithm and data structures. */ +struct xfs_alloc_cur { + struct xfs_btree_cur *cnt; /* btree cursors */ + struct xfs_btree_cur *bnolt; + struct xfs_btree_cur *bnogt; +}; + +/* + * Set up cursors, etc. in the extent allocation cursor. This function can be + * called multiple times to reset an initialized structure without having to + * reallocate cursors. + */ +static int +xfs_alloc_cur_setup( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur) +{ + int error; + int i; + + ASSERT(args->alignment == 1 || args->type != XFS_ALLOCTYPE_THIS_BNO); + + /* + * Perform an initial cntbt lookup to check for availability of maxlen + * extents. If this fails, we'll return -ENOSPC to signal the caller to + * attempt a small allocation. + */ + if (!acur->cnt) + acur->cnt = xfs_allocbt_init_cursor(args->mp, args->tp, + args->agbp, args->agno, XFS_BTNUM_CNT); + error = xfs_alloc_lookup_ge(acur->cnt, 0, args->maxlen, &i); + if (error) + return error; + + /* + * Allocate the bnobt left and right search cursors. + */ + if (!acur->bnolt) + acur->bnolt = xfs_allocbt_init_cursor(args->mp, args->tp, + args->agbp, args->agno, XFS_BTNUM_BNO); + if (!acur->bnogt) + acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp, + args->agbp, args->agno, XFS_BTNUM_BNO); + return i == 1 ? 0 : -ENOSPC; +} + +static void +xfs_alloc_cur_close( + struct xfs_alloc_cur *acur, + bool error) +{ + int cur_error = XFS_BTREE_NOERROR; + + if (error) + cur_error = XFS_BTREE_ERROR; + + if (acur->cnt) + xfs_btree_del_cursor(acur->cnt, cur_error); + if (acur->bnolt) + xfs_btree_del_cursor(acur->bnolt, cur_error); + if (acur->bnogt) + xfs_btree_del_cursor(acur->bnogt, cur_error); + acur->cnt = acur->bnolt = acur->bnogt = NULL; +} /* * Deal with the case where only small freespaces remain. Either return the @@ -1008,8 +1071,8 @@ error0: STATIC int xfs_alloc_find_best_extent( struct xfs_alloc_arg *args, /* allocation argument structure */ - struct xfs_btree_cur **gcur, /* good cursor */ - struct xfs_btree_cur **scur, /* searching cursor */ + struct xfs_btree_cur *gcur, /* good cursor */ + struct xfs_btree_cur *scur, /* searching cursor */ xfs_agblock_t gdiff, /* difference for search comparison */ xfs_agblock_t *sbno, /* extent found by search */ xfs_extlen_t *slen, /* extent length */ @@ -1031,7 +1094,7 @@ xfs_alloc_find_best_extent( * Look until we find a better one, run out of space or run off the end. */ do { - error = xfs_alloc_get_rec(*scur, sbno, slen, &i); + error = xfs_alloc_get_rec(scur, sbno, slen, &i); if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); @@ -1074,21 +1137,19 @@ xfs_alloc_find_best_extent( } if (!dir) - error = xfs_btree_increment(*scur, 0, &i); + error = xfs_btree_increment(scur, 0, &i); else - error = xfs_btree_decrement(*scur, 0, &i); + error = xfs_btree_decrement(scur, 0, &i); if (error) goto error0; } while (i); out_use_good: - xfs_btree_del_cursor(*scur, XFS_BTREE_NOERROR); - *scur = NULL; + scur->bc_private.a.priv.abt.active = false; return 0; out_use_search: - xfs_btree_del_cursor(*gcur, XFS_BTREE_NOERROR); - *gcur = NULL; + gcur->bc_private.a.priv.abt.active = false; return 0; error0: @@ -1102,13 +1163,12 @@ error0: * and of the form k * prod + mod unless there's nothing that large. * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. */ -STATIC int /* error */ +STATIC int xfs_alloc_ag_vextent_near( - xfs_alloc_arg_t *args) /* allocation argument structure */ + struct xfs_alloc_arg *args) { - xfs_btree_cur_t *bno_cur_gt; /* cursor for bno btree, right side */ - xfs_btree_cur_t *bno_cur_lt; /* cursor for bno btree, left side */ - xfs_btree_cur_t *cnt_cur; /* cursor for count btree */ + struct xfs_alloc_cur acur = {}; + struct xfs_btree_cur *bno_cur; xfs_agblock_t gtbno; /* start bno of right side entry */ xfs_agblock_t gtbnoa; /* aligned ... */ xfs_extlen_t gtdiff; /* difference to right side entry */ @@ -1148,38 +1208,29 @@ xfs_alloc_ag_vextent_near( args->agbno = args->max_agbno; restart: - bno_cur_lt = NULL; - bno_cur_gt = NULL; ltlen = 0; gtlena = 0; ltlena = 0; busy = false; /* - * Get a cursor for the by-size btree. + * Set up cursors and see if there are any free extents as big as + * maxlen. If not, pick the last entry in the tree unless the tree is + * empty. */ - cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_CNT); - - /* - * See if there are any free extents as big as maxlen. - */ - if ((error = xfs_alloc_lookup_ge(cnt_cur, 0, args->maxlen, &i))) - goto error0; - /* - * If none, then pick up the last entry in the tree unless the - * tree is empty. - */ - if (!i) { - if ((error = xfs_alloc_ag_vextent_small(args, cnt_cur, <bno, - <len, &i))) - goto error0; + error = xfs_alloc_cur_setup(args, &acur); + if (error == -ENOSPC) { + error = xfs_alloc_ag_vextent_small(args, acur.cnt, <bno, + <len, &i); + if (error) + goto out; if (i == 0 || ltlen == 0) { - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); trace_xfs_alloc_near_noentry(args); - return 0; + goto out; } ASSERT(i == 1); + } else if (error) { + goto out; } args->wasfromfl = 0; @@ -1193,7 +1244,7 @@ restart: * This is written as a while loop so we can break out of it, * but we never loop back to the top. */ - while (xfs_btree_islastblock(cnt_cur, 0)) { + while (xfs_btree_islastblock(acur.cnt, 0)) { xfs_extlen_t bdiff; int besti=0; xfs_extlen_t blen=0; @@ -1210,32 +1261,35 @@ restart: * and skip all those smaller than minlen. */ if (ltlen || args->alignment > 1) { - cnt_cur->bc_ptrs[0] = 1; + acur.cnt->bc_ptrs[0] = 1; do { - if ((error = xfs_alloc_get_rec(cnt_cur, <bno, - <len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); + error = xfs_alloc_get_rec(acur.cnt, <bno, + <len, &i); + if (error) + goto out; + XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); if (ltlen >= args->minlen) break; - if ((error = xfs_btree_increment(cnt_cur, 0, &i))) - goto error0; + error = xfs_btree_increment(acur.cnt, 0, &i); + if (error) + goto out; } while (i); ASSERT(ltlen >= args->minlen); if (!i) break; } - i = cnt_cur->bc_ptrs[0]; + i = acur.cnt->bc_ptrs[0]; for (j = 1, blen = 0, bdiff = 0; !error && j && (blen < args->maxlen || bdiff > 0); - error = xfs_btree_increment(cnt_cur, 0, &j)) { + error = xfs_btree_increment(acur.cnt, 0, &j)) { /* * For each entry, decide if it's better than * the previous best entry. */ - if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); + error = xfs_alloc_get_rec(acur.cnt, <bno, <len, &i); + if (error) + goto out; + XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); busy = xfs_alloc_compute_aligned(args, ltbno, ltlen, <bnoa, <lena, &busy_gen); if (ltlena < args->minlen) @@ -1255,7 +1309,7 @@ restart: bdiff = ltdiff; bnew = ltnew; blen = args->len; - besti = cnt_cur->bc_ptrs[0]; + besti = acur.cnt->bc_ptrs[0]; } } /* @@ -1267,10 +1321,11 @@ restart: /* * Point at the best entry, and retrieve it again. */ - cnt_cur->bc_ptrs[0] = besti; - if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); + acur.cnt->bc_ptrs[0] = besti; + error = xfs_alloc_get_rec(acur.cnt, <bno, <len, &i); + if (error) + goto out; + XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); args->len = blen; @@ -1280,23 +1335,14 @@ restart: args->agbno = bnew; ASSERT(bnew >= ltbno); ASSERT(bnew + blen <= ltbno + ltlen); - /* - * Set up a cursor for the by-bno tree. - */ - bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp, - args->agbp, args->agno, XFS_BTNUM_BNO); - /* - * Fix up the btree entries. - */ - if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, - ltlen, bnew, blen, XFSA_FIXUP_CNT_OK))) - goto error0; - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); - + error = xfs_alloc_fixup_trees(acur.cnt, acur.bnolt, ltbno, + ltlen, bnew, blen, XFSA_FIXUP_CNT_OK); + if (error) + goto out; trace_xfs_alloc_near_first(args); - return 0; + goto out; } + /* * Second algorithm. * Search in the by-bno tree to the left and to the right @@ -1309,86 +1355,57 @@ restart: * level algorithm that picks allocation groups for allocations * is not supposed to do this. */ - /* - * Allocate and initialize the cursor for the leftward search. - */ - bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, - args->agno, XFS_BTNUM_BNO); - /* - * Lookup <= bno to find the leftward search's starting point. - */ - if ((error = xfs_alloc_lookup_le(bno_cur_lt, args->agbno, args->maxlen, &i))) - goto error0; - if (!i) { - /* - * Didn't find anything; use this cursor for the rightward - * search. - */ - bno_cur_gt = bno_cur_lt; - bno_cur_lt = NULL; - } - /* - * Found something. Duplicate the cursor for the rightward search. - */ - else if ((error = xfs_btree_dup_cursor(bno_cur_lt, &bno_cur_gt))) - goto error0; - /* - * Increment the cursor, so we will point at the entry just right - * of the leftward entry if any, or to the leftmost entry. - */ - if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) - goto error0; - if (!i) { - /* - * It failed, there are no rightward entries. - */ - xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_NOERROR); - bno_cur_gt = NULL; - } + error = xfs_alloc_lookup_le(acur.bnolt, args->agbno, 0, &i); + if (error) + goto out; + error = xfs_alloc_lookup_ge(acur.bnogt, args->agbno, 0, &i); + if (error) + goto out; + /* * Loop going left with the leftward cursor, right with the * rightward cursor, until either both directions give up or * we find an entry at least as big as minlen. */ do { - if (bno_cur_lt) { - if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); + if (xfs_alloc_cur_active(acur.bnolt)) { + error = xfs_alloc_get_rec(acur.bnolt, <bno, <len, &i); + if (error) + goto out; + XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); busy |= xfs_alloc_compute_aligned(args, ltbno, ltlen, <bnoa, <lena, &busy_gen); if (ltlena >= args->minlen && ltbnoa >= args->min_agbno) break; - if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) - goto error0; - if (!i || ltbnoa < args->min_agbno) { - xfs_btree_del_cursor(bno_cur_lt, - XFS_BTREE_NOERROR); - bno_cur_lt = NULL; - } + error = xfs_btree_decrement(acur.bnolt, 0, &i); + if (error) + goto out; + if (!i || ltbnoa < args->min_agbno) + acur.bnolt->bc_private.a.priv.abt.active = false; } - if (bno_cur_gt) { - if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i))) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); + if (xfs_alloc_cur_active(acur.bnogt)) { + error = xfs_alloc_get_rec(acur.bnogt, >bno, >len, &i); + if (error) + goto out; + XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); busy |= xfs_alloc_compute_aligned(args, gtbno, gtlen, >bnoa, >lena, &busy_gen); if (gtlena >= args->minlen && gtbnoa <= args->max_agbno) break; - if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) - goto error0; - if (!i || gtbnoa > args->max_agbno) { - xfs_btree_del_cursor(bno_cur_gt, - XFS_BTREE_NOERROR); - bno_cur_gt = NULL; - } + error = xfs_btree_increment(acur.bnogt, 0, &i); + if (error) + goto out; + if (!i || gtbnoa > args->max_agbno) + acur.bnogt->bc_private.a.priv.abt.active = false; } - } while (bno_cur_lt || bno_cur_gt); + } while (xfs_alloc_cur_active(acur.bnolt) || + xfs_alloc_cur_active(acur.bnogt)); /* * Got both cursors still active, need to find better entry. */ - if (bno_cur_lt && bno_cur_gt) { + if (xfs_alloc_cur_active(acur.bnolt) && + xfs_alloc_cur_active(acur.bnogt)) { if (ltlena >= args->minlen) { /* * Left side is good, look for a right side entry. @@ -1400,7 +1417,7 @@ restart: ltlena, <new); error = xfs_alloc_find_best_extent(args, - &bno_cur_lt, &bno_cur_gt, + acur.bnolt, acur.bnogt, ltdiff, >bno, >len, >bnoa, >lena, 0 /* search right */); @@ -1417,22 +1434,21 @@ restart: gtlena, >new); error = xfs_alloc_find_best_extent(args, - &bno_cur_gt, &bno_cur_lt, + acur.bnogt, acur.bnolt, gtdiff, <bno, <len, <bnoa, <lena, 1 /* search left */); } if (error) - goto error0; + goto out; } /* * If we couldn't get anything, give up. */ - if (bno_cur_lt == NULL && bno_cur_gt == NULL) { - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - + if (!xfs_alloc_cur_active(acur.bnolt) && + !xfs_alloc_cur_active(acur.bnogt)) { if (busy) { trace_xfs_alloc_near_busy(args); xfs_extent_busy_flush(args->mp, args->pag, busy_gen); @@ -1440,7 +1456,7 @@ restart: } trace_xfs_alloc_size_neither(args); args->agbno = NULLAGBLOCK; - return 0; + goto out; } /* @@ -1449,16 +1465,17 @@ restart: * useful variables to the "left" set so we only have one * copy of this code. */ - if (bno_cur_gt) { - bno_cur_lt = bno_cur_gt; - bno_cur_gt = NULL; + if (xfs_alloc_cur_active(acur.bnogt)) { + bno_cur = acur.bnogt; ltbno = gtbno; ltbnoa = gtbnoa; ltlen = gtlen; ltlena = gtlena; j = 1; - } else + } else { + bno_cur = acur.bnolt; j = 0; + } /* * Fix up the length and compute the useful address. @@ -1474,27 +1491,18 @@ restart: ASSERT(ltnew >= args->min_agbno && ltnew <= args->max_agbno); args->agbno = ltnew; - if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, - ltnew, rlen, XFSA_FIXUP_BNO_OK))) - goto error0; + error = xfs_alloc_fixup_trees(acur.cnt, bno_cur, ltbno, ltlen, ltnew, + rlen, XFSA_FIXUP_BNO_OK); + if (error) + goto out; if (j) trace_xfs_alloc_near_greater(args); else trace_xfs_alloc_near_lesser(args); - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); - xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); - return 0; - - error0: - trace_xfs_alloc_near_error(args); - if (cnt_cur != NULL) - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); - if (bno_cur_lt != NULL) - xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_ERROR); - if (bno_cur_gt != NULL) - xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_ERROR); +out: + xfs_alloc_cur_close(&acur, error); return error; } -- cgit v1.2.3-70-g09d2 From d6d3aff20377fcb38913152d53c54e0010462ccb Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:32 -0700 Subject: xfs: track allocation busy state in allocation cursor Extend the allocation cursor to track extent busy state for an allocation attempt. No functional changes. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 664e2ad72542..81e5e4015c26 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -716,6 +716,8 @@ struct xfs_alloc_cur { struct xfs_btree_cur *cnt; /* btree cursors */ struct xfs_btree_cur *bnolt; struct xfs_btree_cur *bnogt; + unsigned int busy_gen;/* busy state */ + bool busy; }; /* @@ -733,6 +735,9 @@ xfs_alloc_cur_setup( ASSERT(args->alignment == 1 || args->type != XFS_ALLOCTYPE_THIS_BNO); + acur->busy = false; + acur->busy_gen = 0; + /* * Perform an initial cntbt lookup to check for availability of maxlen * extents. If this fails, we'll return -ENOSPC to signal the caller to @@ -1185,8 +1190,6 @@ xfs_alloc_ag_vextent_near( xfs_extlen_t ltlena; /* aligned ... */ xfs_agblock_t ltnew; /* useful start bno of left side */ xfs_extlen_t rlen; /* length of returned extent */ - bool busy; - unsigned busy_gen; #ifdef DEBUG /* * Randomly don't execute the first algorithm. @@ -1211,7 +1214,6 @@ restart: ltlen = 0; gtlena = 0; ltlena = 0; - busy = false; /* * Set up cursors and see if there are any free extents as big as @@ -1290,8 +1292,8 @@ restart: if (error) goto out; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); - busy = xfs_alloc_compute_aligned(args, ltbno, ltlen, - <bnoa, <lena, &busy_gen); + acur.busy = xfs_alloc_compute_aligned(args, ltbno, ltlen, + <bnoa, <lena, &acur.busy_gen); if (ltlena < args->minlen) continue; if (ltbnoa < args->min_agbno || ltbnoa > args->max_agbno) @@ -1373,8 +1375,8 @@ restart: if (error) goto out; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); - busy |= xfs_alloc_compute_aligned(args, ltbno, ltlen, - <bnoa, <lena, &busy_gen); + acur.busy |= xfs_alloc_compute_aligned(args, ltbno, + ltlen, <bnoa, <lena, &acur.busy_gen); if (ltlena >= args->minlen && ltbnoa >= args->min_agbno) break; error = xfs_btree_decrement(acur.bnolt, 0, &i); @@ -1388,8 +1390,8 @@ restart: if (error) goto out; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); - busy |= xfs_alloc_compute_aligned(args, gtbno, gtlen, - >bnoa, >lena, &busy_gen); + acur.busy |= xfs_alloc_compute_aligned(args, gtbno, + gtlen, >bnoa, >lena, &acur.busy_gen); if (gtlena >= args->minlen && gtbnoa <= args->max_agbno) break; error = xfs_btree_increment(acur.bnogt, 0, &i); @@ -1449,9 +1451,10 @@ restart: */ if (!xfs_alloc_cur_active(acur.bnolt) && !xfs_alloc_cur_active(acur.bnogt)) { - if (busy) { + if (acur.busy) { trace_xfs_alloc_near_busy(args); - xfs_extent_busy_flush(args->mp, args->pag, busy_gen); + xfs_extent_busy_flush(args->mp, args->pag, + acur.busy_gen); goto restart; } trace_xfs_alloc_size_neither(args); -- cgit v1.2.3-70-g09d2 From c62321a2a0ea3c53ab7a41cf4d4071ee37bcc2c0 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:32 -0700 Subject: xfs: track best extent from cntbt lastblock scan in alloc cursor If the size lookup lands in the last block of the by-size btree, the near mode algorithm scans the entire block for the extent with best available locality. In preparation for similar best available extent tracking across both btrees, extend the allocation cursor with best extent data and lift the associated state from the cntbt last block scan code. No functional changes. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 63 +++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 30 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 81e5e4015c26..4e80919fca90 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -716,6 +716,11 @@ struct xfs_alloc_cur { struct xfs_btree_cur *cnt; /* btree cursors */ struct xfs_btree_cur *bnolt; struct xfs_btree_cur *bnogt; + xfs_agblock_t rec_bno;/* extent startblock */ + xfs_extlen_t rec_len;/* extent length */ + xfs_agblock_t bno; /* alloc bno */ + xfs_extlen_t len; /* alloc len */ + xfs_extlen_t diff; /* diff from search bno */ unsigned int busy_gen;/* busy state */ bool busy; }; @@ -735,6 +740,11 @@ xfs_alloc_cur_setup( ASSERT(args->alignment == 1 || args->type != XFS_ALLOCTYPE_THIS_BNO); + acur->rec_bno = 0; + acur->rec_len = 0; + acur->bno = 0; + acur->len = 0; + acur->diff = 0; acur->busy = false; acur->busy_gen = 0; @@ -1247,10 +1257,7 @@ restart: * but we never loop back to the top. */ while (xfs_btree_islastblock(acur.cnt, 0)) { - xfs_extlen_t bdiff; - int besti=0; - xfs_extlen_t blen=0; - xfs_agblock_t bnew=0; + xfs_extlen_t diff; #ifdef DEBUG if (dofirst) @@ -1281,8 +1288,8 @@ restart: break; } i = acur.cnt->bc_ptrs[0]; - for (j = 1, blen = 0, bdiff = 0; - !error && j && (blen < args->maxlen || bdiff > 0); + for (j = 1; + !error && j && (acur.len < args->maxlen || acur.diff > 0); error = xfs_btree_increment(acur.cnt, 0, &j)) { /* * For each entry, decide if it's better than @@ -1301,44 +1308,40 @@ restart: args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); xfs_alloc_fix_len(args); ASSERT(args->len >= args->minlen); - if (args->len < blen) + if (args->len < acur.len) continue; - ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, + diff = xfs_alloc_compute_diff(args->agbno, args->len, args->alignment, args->datatype, ltbnoa, ltlena, <new); if (ltnew != NULLAGBLOCK && - (args->len > blen || ltdiff < bdiff)) { - bdiff = ltdiff; - bnew = ltnew; - blen = args->len; - besti = acur.cnt->bc_ptrs[0]; + (args->len > acur.len || diff < acur.diff)) { + acur.rec_bno = ltbno; + acur.rec_len = ltlen; + acur.diff = diff; + acur.bno = ltnew; + acur.len = args->len; } } /* * It didn't work. We COULD be in a case where * there's a good record somewhere, so try again. */ - if (blen == 0) + if (acur.len == 0) break; - /* - * Point at the best entry, and retrieve it again. - */ - acur.cnt->bc_ptrs[0] = besti; - error = xfs_alloc_get_rec(acur.cnt, <bno, <len, &i); - if (error) - goto out; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); - ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); - args->len = blen; /* - * We are allocating starting at bnew for blen blocks. + * Allocate at the bno/len tracked in the cursor. */ - args->agbno = bnew; - ASSERT(bnew >= ltbno); - ASSERT(bnew + blen <= ltbno + ltlen); - error = xfs_alloc_fixup_trees(acur.cnt, acur.bnolt, ltbno, - ltlen, bnew, blen, XFSA_FIXUP_CNT_OK); + args->agbno = acur.bno; + args->len = acur.len; + ASSERT(acur.bno >= acur.rec_bno); + ASSERT(acur.bno + acur.len <= acur.rec_bno + acur.rec_len); + ASSERT(acur.rec_bno + acur.rec_len <= + be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); + + error = xfs_alloc_fixup_trees(acur.cnt, acur.bnolt, + acur.rec_bno, acur.rec_len, acur.bno, acur.len, + 0); if (error) goto out; trace_xfs_alloc_near_first(args); -- cgit v1.2.3-70-g09d2 From 396bbf3c657e540162b7297e426e5939c2909854 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:33 -0700 Subject: xfs: refactor cntbt lastblock scan best extent logic into helper The cntbt lastblock scan checks the size, alignment, locality, etc. of each free extent in the block and compares it with the current best candidate. This logic will be reused by the upcoming optimized cntbt algorithm, so refactor it into a separate helper. Note that acur->diff is now initialized to -1 (unsigned) instead of 0 to support the more granular comparison logic in the new helper. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 115 +++++++++++++++++++++++++++++++++++----------- fs/xfs/xfs_trace.h | 26 +++++++++++ 2 files changed, 113 insertions(+), 28 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 4e80919fca90..3481489622ed 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -744,7 +744,7 @@ xfs_alloc_cur_setup( acur->rec_len = 0; acur->bno = 0; acur->len = 0; - acur->diff = 0; + acur->diff = -1; acur->busy = false; acur->busy_gen = 0; @@ -791,6 +791,89 @@ xfs_alloc_cur_close( acur->cnt = acur->bnolt = acur->bnogt = NULL; } +/* + * Check an extent for allocation and track the best available candidate in the + * allocation structure. The cursor is deactivated if it has entered an out of + * range state based on allocation arguments. Optionally return the extent + * extent geometry and allocation status if requested by the caller. + */ +static int +xfs_alloc_cur_check( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur, + struct xfs_btree_cur *cur, + int *new) +{ + int error, i; + xfs_agblock_t bno, bnoa, bnew; + xfs_extlen_t len, lena, diff = -1; + bool busy; + unsigned busy_gen = 0; + bool deactivate = false; + + *new = 0; + + error = xfs_alloc_get_rec(cur, &bno, &len, &i); + if (error) + return error; + XFS_WANT_CORRUPTED_RETURN(args->mp, i == 1); + + /* + * Check minlen and deactivate a cntbt cursor if out of acceptable size + * range (i.e., walking backwards looking for a minlen extent). + */ + if (len < args->minlen) { + deactivate = true; + goto out; + } + + busy = xfs_alloc_compute_aligned(args, bno, len, &bnoa, &lena, + &busy_gen); + acur->busy |= busy; + if (busy) + acur->busy_gen = busy_gen; + /* deactivate a bnobt cursor outside of locality range */ + if (bnoa < args->min_agbno || bnoa > args->max_agbno) + goto out; + if (lena < args->minlen) + goto out; + + args->len = XFS_EXTLEN_MIN(lena, args->maxlen); + xfs_alloc_fix_len(args); + ASSERT(args->len >= args->minlen); + if (args->len < acur->len) + goto out; + + /* + * We have an aligned record that satisfies minlen and beats or matches + * the candidate extent size. Compare locality for near allocation mode. + */ + ASSERT(args->type == XFS_ALLOCTYPE_NEAR_BNO); + diff = xfs_alloc_compute_diff(args->agbno, args->len, + args->alignment, args->datatype, + bnoa, lena, &bnew); + if (bnew == NULLAGBLOCK) + goto out; + if (diff > acur->diff) + goto out; + + ASSERT(args->len > acur->len || + (args->len == acur->len && diff <= acur->diff)); + acur->rec_bno = bno; + acur->rec_len = len; + acur->bno = bnew; + acur->len = args->len; + acur->diff = diff; + *new = 1; + +out: + if (deactivate) + cur->bc_private.a.priv.abt.active = false; + trace_xfs_alloc_cur_check(args->mp, cur->bc_btnum, bno, len, diff, + *new); + return 0; +} + /* * Deal with the case where only small freespaces remain. Either return the * contents of the last freespace record, or allocate space from the freelist if @@ -1257,8 +1340,6 @@ restart: * but we never loop back to the top. */ while (xfs_btree_islastblock(acur.cnt, 0)) { - xfs_extlen_t diff; - #ifdef DEBUG if (dofirst) break; @@ -1289,38 +1370,16 @@ restart: } i = acur.cnt->bc_ptrs[0]; for (j = 1; - !error && j && (acur.len < args->maxlen || acur.diff > 0); + !error && j && xfs_alloc_cur_active(acur.cnt) && + (acur.len < args->maxlen || acur.diff > 0); error = xfs_btree_increment(acur.cnt, 0, &j)) { /* * For each entry, decide if it's better than * the previous best entry. */ - error = xfs_alloc_get_rec(acur.cnt, <bno, <len, &i); + error = xfs_alloc_cur_check(args, &acur, acur.cnt, &i); if (error) goto out; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); - acur.busy = xfs_alloc_compute_aligned(args, ltbno, ltlen, - <bnoa, <lena, &acur.busy_gen); - if (ltlena < args->minlen) - continue; - if (ltbnoa < args->min_agbno || ltbnoa > args->max_agbno) - continue; - args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); - xfs_alloc_fix_len(args); - ASSERT(args->len >= args->minlen); - if (args->len < acur.len) - continue; - diff = xfs_alloc_compute_diff(args->agbno, args->len, - args->alignment, args->datatype, ltbnoa, - ltlena, <new); - if (ltnew != NULLAGBLOCK && - (args->len > acur.len || diff < acur.diff)) { - acur.rec_bno = ltbno; - acur.rec_len = ltlen; - acur.diff = diff; - acur.bno = ltnew; - acur.len = args->len; - } } /* * It didn't work. We COULD be in a case where diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index cbb23d7a3554..61b53a30f8f2 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1598,6 +1598,32 @@ DEFINE_ALLOC_EVENT(xfs_alloc_vextent_noagbp); DEFINE_ALLOC_EVENT(xfs_alloc_vextent_loopfailed); DEFINE_ALLOC_EVENT(xfs_alloc_vextent_allfailed); +TRACE_EVENT(xfs_alloc_cur_check, + TP_PROTO(struct xfs_mount *mp, xfs_btnum_t btnum, xfs_agblock_t bno, + xfs_extlen_t len, xfs_extlen_t diff, bool new), + TP_ARGS(mp, btnum, bno, len, diff, new), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_btnum_t, btnum) + __field(xfs_agblock_t, bno) + __field(xfs_extlen_t, len) + __field(xfs_extlen_t, diff) + __field(bool, new) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->btnum = btnum; + __entry->bno = bno; + __entry->len = len; + __entry->diff = diff; + __entry->new = new; + ), + TP_printk("dev %d:%d btree %s bno 0x%x len 0x%x diff 0x%x new %d", + MAJOR(__entry->dev), MINOR(__entry->dev), + __print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS), + __entry->bno, __entry->len, __entry->diff, __entry->new) +) + DECLARE_EVENT_CLASS(xfs_da_class, TP_PROTO(struct xfs_da_args *args), TP_ARGS(args), -- cgit v1.2.3-70-g09d2 From fec0afdaf498a9a923c3688cc9f9c91a73f5bcd8 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:33 -0700 Subject: xfs: reuse best extent tracking logic for bnobt scan The near mode bnobt scan searches left and right in the bnobt looking for the closest free extent to the allocation hint that satisfies minlen. Once such an extent is found, the left/right search terminates, we search one more time in the opposite direction and finish the allocation with the best overall extent. The left/right and find best searches are currently controlled via a combination of cursor state and local variables. Clean up this code and prepare for further improvements to the near mode fallback algorithm by reusing the allocation cursor best extent tracking mechanism. Update the tracking logic to deactivate bnobt cursors when out of allocation range and replace open-coded extent checks to calls to the common helper. In doing so, rename some misnamed local variables in the top-level near mode allocation function. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 276 +++++++++++++--------------------------------- fs/xfs/xfs_trace.h | 4 +- 2 files changed, 79 insertions(+), 201 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 3481489622ed..2b40842ef5f6 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -810,6 +810,7 @@ xfs_alloc_cur_check( bool busy; unsigned busy_gen = 0; bool deactivate = false; + bool isbnobt = cur->bc_btnum == XFS_BTNUM_BNO; *new = 0; @@ -823,7 +824,7 @@ xfs_alloc_cur_check( * range (i.e., walking backwards looking for a minlen extent). */ if (len < args->minlen) { - deactivate = true; + deactivate = !isbnobt; goto out; } @@ -833,8 +834,10 @@ xfs_alloc_cur_check( if (busy) acur->busy_gen = busy_gen; /* deactivate a bnobt cursor outside of locality range */ - if (bnoa < args->min_agbno || bnoa > args->max_agbno) + if (bnoa < args->min_agbno || bnoa > args->max_agbno) { + deactivate = isbnobt; goto out; + } if (lena < args->minlen) goto out; @@ -854,8 +857,14 @@ xfs_alloc_cur_check( bnoa, lena, &bnew); if (bnew == NULLAGBLOCK) goto out; - if (diff > acur->diff) + + /* + * Deactivate a bnobt cursor with worse locality than the current best. + */ + if (diff > acur->diff) { + deactivate = isbnobt; goto out; + } ASSERT(args->len > acur->len || (args->len == acur->len && diff <= acur->diff)); @@ -1163,96 +1172,44 @@ error0: } /* - * Search the btree in a given direction via the search cursor and compare - * the records found against the good extent we've already found. + * Search the btree in a given direction and check the records against the good + * extent we've already found. */ STATIC int xfs_alloc_find_best_extent( - struct xfs_alloc_arg *args, /* allocation argument structure */ - struct xfs_btree_cur *gcur, /* good cursor */ - struct xfs_btree_cur *scur, /* searching cursor */ - xfs_agblock_t gdiff, /* difference for search comparison */ - xfs_agblock_t *sbno, /* extent found by search */ - xfs_extlen_t *slen, /* extent length */ - xfs_agblock_t *sbnoa, /* aligned extent found by search */ - xfs_extlen_t *slena, /* aligned extent length */ - int dir) /* 0 = search right, 1 = search left */ + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur, + struct xfs_btree_cur *cur, + bool increment) { - xfs_agblock_t new; - xfs_agblock_t sdiff; int error; int i; - unsigned busy_gen; - - /* The good extent is perfect, no need to search. */ - if (!gdiff) - goto out_use_good; /* - * Look until we find a better one, run out of space or run off the end. + * Search so long as the cursor is active or we find a better extent. + * The cursor is deactivated if it extends beyond the range of the + * current allocation candidate. */ - do { - error = xfs_alloc_get_rec(scur, sbno, slen, &i); + while (xfs_alloc_cur_active(cur)) { + error = xfs_alloc_cur_check(args, acur, cur, &i); if (error) - goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); - xfs_alloc_compute_aligned(args, *sbno, *slen, - sbnoa, slena, &busy_gen); - - /* - * The good extent is closer than this one. - */ - if (!dir) { - if (*sbnoa > args->max_agbno) - goto out_use_good; - if (*sbnoa >= args->agbno + gdiff) - goto out_use_good; - } else { - if (*sbnoa < args->min_agbno) - goto out_use_good; - if (*sbnoa <= args->agbno - gdiff) - goto out_use_good; - } - - /* - * Same distance, compare length and pick the best. - */ - if (*slena >= args->minlen) { - args->len = XFS_EXTLEN_MIN(*slena, args->maxlen); - xfs_alloc_fix_len(args); - - sdiff = xfs_alloc_compute_diff(args->agbno, args->len, - args->alignment, - args->datatype, *sbnoa, - *slena, &new); - - /* - * Choose closer size and invalidate other cursor. - */ - if (sdiff < gdiff) - goto out_use_search; - goto out_use_good; - } + return error; + if (i == 1) + break; + if (!xfs_alloc_cur_active(cur)) + break; - if (!dir) - error = xfs_btree_increment(scur, 0, &i); + if (increment) + error = xfs_btree_increment(cur, 0, &i); else - error = xfs_btree_decrement(scur, 0, &i); + error = xfs_btree_decrement(cur, 0, &i); if (error) - goto error0; - } while (i); - -out_use_good: - scur->bc_private.a.priv.abt.active = false; - return 0; + return error; + if (i == 0) + cur->bc_private.a.priv.abt.active = false; + } -out_use_search: - gcur->bc_private.a.priv.abt.active = false; return 0; - -error0: - /* caller invalidates cursors */ - return error; } /* @@ -1266,23 +1223,13 @@ xfs_alloc_ag_vextent_near( struct xfs_alloc_arg *args) { struct xfs_alloc_cur acur = {}; - struct xfs_btree_cur *bno_cur; - xfs_agblock_t gtbno; /* start bno of right side entry */ - xfs_agblock_t gtbnoa; /* aligned ... */ - xfs_extlen_t gtdiff; /* difference to right side entry */ - xfs_extlen_t gtlen; /* length of right side entry */ - xfs_extlen_t gtlena; /* aligned ... */ - xfs_agblock_t gtnew; /* useful start bno of right side */ - int error; /* error code */ - int i; /* result code, temporary */ - int j; /* result code, temporary */ - xfs_agblock_t ltbno; /* start bno of left side entry */ - xfs_agblock_t ltbnoa; /* aligned ... */ - xfs_extlen_t ltdiff; /* difference to left side entry */ - xfs_extlen_t ltlen; /* length of left side entry */ - xfs_extlen_t ltlena; /* aligned ... */ - xfs_agblock_t ltnew; /* useful start bno of left side */ - xfs_extlen_t rlen; /* length of returned extent */ + struct xfs_btree_cur *fbcur = NULL; + int error; /* error code */ + int i; /* result code, temporary */ + int j; /* result code, temporary */ + xfs_agblock_t bno; + xfs_extlen_t len; + bool fbinc = false; #ifdef DEBUG /* * Randomly don't execute the first algorithm. @@ -1304,9 +1251,7 @@ xfs_alloc_ag_vextent_near( args->agbno = args->max_agbno; restart: - ltlen = 0; - gtlena = 0; - ltlena = 0; + len = 0; /* * Set up cursors and see if there are any free extents as big as @@ -1315,11 +1260,11 @@ restart: */ error = xfs_alloc_cur_setup(args, &acur); if (error == -ENOSPC) { - error = xfs_alloc_ag_vextent_small(args, acur.cnt, <bno, - <len, &i); + error = xfs_alloc_ag_vextent_small(args, acur.cnt, &bno, + &len, &i); if (error) goto out; - if (i == 0 || ltlen == 0) { + if (i == 0 || len == 0) { trace_xfs_alloc_near_noentry(args); goto out; } @@ -1350,21 +1295,21 @@ restart: * record smaller than maxlen, go to the start of this block, * and skip all those smaller than minlen. */ - if (ltlen || args->alignment > 1) { + if (len || args->alignment > 1) { acur.cnt->bc_ptrs[0] = 1; do { - error = xfs_alloc_get_rec(acur.cnt, <bno, - <len, &i); + error = xfs_alloc_get_rec(acur.cnt, &bno, &len, + &i); if (error) goto out; XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); - if (ltlen >= args->minlen) + if (len >= args->minlen) break; error = xfs_btree_increment(acur.cnt, 0, &i); if (error) goto out; } while (i); - ASSERT(ltlen >= args->minlen); + ASSERT(len >= args->minlen); if (!i) break; } @@ -1433,77 +1378,43 @@ restart: */ do { if (xfs_alloc_cur_active(acur.bnolt)) { - error = xfs_alloc_get_rec(acur.bnolt, <bno, <len, &i); + error = xfs_alloc_cur_check(args, &acur, acur.bnolt, &i); if (error) goto out; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); - acur.busy |= xfs_alloc_compute_aligned(args, ltbno, - ltlen, <bnoa, <lena, &acur.busy_gen); - if (ltlena >= args->minlen && ltbnoa >= args->min_agbno) + if (i == 1) { + trace_xfs_alloc_cur_left(args); + fbcur = acur.bnogt; + fbinc = true; break; + } error = xfs_btree_decrement(acur.bnolt, 0, &i); if (error) goto out; - if (!i || ltbnoa < args->min_agbno) + if (!i) acur.bnolt->bc_private.a.priv.abt.active = false; } if (xfs_alloc_cur_active(acur.bnogt)) { - error = xfs_alloc_get_rec(acur.bnogt, >bno, >len, &i); + error = xfs_alloc_cur_check(args, &acur, acur.bnogt, &i); if (error) goto out; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); - acur.busy |= xfs_alloc_compute_aligned(args, gtbno, - gtlen, >bnoa, >lena, &acur.busy_gen); - if (gtlena >= args->minlen && gtbnoa <= args->max_agbno) + if (i == 1) { + trace_xfs_alloc_cur_right(args); + fbcur = acur.bnolt; + fbinc = false; break; + } error = xfs_btree_increment(acur.bnogt, 0, &i); if (error) goto out; - if (!i || gtbnoa > args->max_agbno) + if (!i) acur.bnogt->bc_private.a.priv.abt.active = false; } } while (xfs_alloc_cur_active(acur.bnolt) || xfs_alloc_cur_active(acur.bnogt)); - /* - * Got both cursors still active, need to find better entry. - */ - if (xfs_alloc_cur_active(acur.bnolt) && - xfs_alloc_cur_active(acur.bnogt)) { - if (ltlena >= args->minlen) { - /* - * Left side is good, look for a right side entry. - */ - args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); - xfs_alloc_fix_len(args); - ltdiff = xfs_alloc_compute_diff(args->agbno, args->len, - args->alignment, args->datatype, ltbnoa, - ltlena, <new); - - error = xfs_alloc_find_best_extent(args, - acur.bnolt, acur.bnogt, - ltdiff, >bno, >len, - >bnoa, >lena, - 0 /* search right */); - } else { - ASSERT(gtlena >= args->minlen); - - /* - * Right side is good, look for a left side entry. - */ - args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen); - xfs_alloc_fix_len(args); - gtdiff = xfs_alloc_compute_diff(args->agbno, args->len, - args->alignment, args->datatype, gtbnoa, - gtlena, >new); - - error = xfs_alloc_find_best_extent(args, - acur.bnogt, acur.bnolt, - gtdiff, <bno, <len, - <bnoa, <lena, - 1 /* search left */); - } - + /* search the opposite direction for a better entry */ + if (fbcur) { + error = xfs_alloc_find_best_extent(args, &acur, fbcur, fbinc); if (error) goto out; } @@ -1511,8 +1422,7 @@ restart: /* * If we couldn't get anything, give up. */ - if (!xfs_alloc_cur_active(acur.bnolt) && - !xfs_alloc_cur_active(acur.bnogt)) { + if (!acur.len) { if (acur.busy) { trace_xfs_alloc_near_busy(args); xfs_extent_busy_flush(args->mp, args->pag, @@ -1524,47 +1434,15 @@ restart: goto out; } - /* - * At this point we have selected a freespace entry, either to the - * left or to the right. If it's on the right, copy all the - * useful variables to the "left" set so we only have one - * copy of this code. - */ - if (xfs_alloc_cur_active(acur.bnogt)) { - bno_cur = acur.bnogt; - ltbno = gtbno; - ltbnoa = gtbnoa; - ltlen = gtlen; - ltlena = gtlena; - j = 1; - } else { - bno_cur = acur.bnolt; - j = 0; - } - - /* - * Fix up the length and compute the useful address. - */ - args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); - xfs_alloc_fix_len(args); - rlen = args->len; - (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, - args->datatype, ltbnoa, ltlena, <new); - ASSERT(ltnew >= ltbno); - ASSERT(ltnew + rlen <= ltbnoa + ltlena); - ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); - ASSERT(ltnew >= args->min_agbno && ltnew <= args->max_agbno); - args->agbno = ltnew; - - error = xfs_alloc_fixup_trees(acur.cnt, bno_cur, ltbno, ltlen, ltnew, - rlen, XFSA_FIXUP_BNO_OK); - if (error) - goto out; + args->agbno = acur.bno; + args->len = acur.len; + ASSERT(acur.bno >= acur.rec_bno); + ASSERT(acur.bno + acur.len <= acur.rec_bno + acur.rec_len); + ASSERT(acur.rec_bno + acur.rec_len <= + be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); - if (j) - trace_xfs_alloc_near_greater(args); - else - trace_xfs_alloc_near_lesser(args); + error = xfs_alloc_fixup_trees(acur.cnt, acur.bnolt, acur.rec_bno, + acur.rec_len, acur.bno, acur.len, 0); out: xfs_alloc_cur_close(&acur, error); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 61b53a30f8f2..cdc5f000d608 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1577,8 +1577,8 @@ DEFINE_ALLOC_EVENT(xfs_alloc_exact_notfound); DEFINE_ALLOC_EVENT(xfs_alloc_exact_error); DEFINE_ALLOC_EVENT(xfs_alloc_near_nominleft); DEFINE_ALLOC_EVENT(xfs_alloc_near_first); -DEFINE_ALLOC_EVENT(xfs_alloc_near_greater); -DEFINE_ALLOC_EVENT(xfs_alloc_near_lesser); +DEFINE_ALLOC_EVENT(xfs_alloc_cur_right); +DEFINE_ALLOC_EVENT(xfs_alloc_cur_left); DEFINE_ALLOC_EVENT(xfs_alloc_near_error); DEFINE_ALLOC_EVENT(xfs_alloc_near_noentry); DEFINE_ALLOC_EVENT(xfs_alloc_near_busy); -- cgit v1.2.3-70-g09d2 From 4a65b7c2c72c3940a4472c49743fdb65a03a9935 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:34 -0700 Subject: xfs: refactor allocation tree fixup code Both algorithms duplicate the same btree allocation code. Eliminate the duplication and reuse the fallback algorithm codepath. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 2b40842ef5f6..6428d0a79213 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1333,23 +1333,8 @@ restart: if (acur.len == 0) break; - /* - * Allocate at the bno/len tracked in the cursor. - */ - args->agbno = acur.bno; - args->len = acur.len; - ASSERT(acur.bno >= acur.rec_bno); - ASSERT(acur.bno + acur.len <= acur.rec_bno + acur.rec_len); - ASSERT(acur.rec_bno + acur.rec_len <= - be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); - - error = xfs_alloc_fixup_trees(acur.cnt, acur.bnolt, - acur.rec_bno, acur.rec_len, acur.bno, acur.len, - 0); - if (error) - goto out; trace_xfs_alloc_near_first(args); - goto out; + goto alloc; } /* @@ -1434,6 +1419,7 @@ restart: goto out; } +alloc: args->agbno = acur.bno; args->len = acur.len; ASSERT(acur.bno >= acur.rec_bno); -- cgit v1.2.3-70-g09d2 From 78d7aabdeea38368dc5e0aff2d3d1c353a7ab344 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:34 -0700 Subject: xfs: refactor and reuse best extent scanning logic The bnobt "find best" helper implements a simple btree walker function. This general pattern, or a subset thereof, is reused in various parts of a near mode allocation operation. For example, the bnobt left/right scans are each iterative btree walks along with the cntbt lastblock scan. Rework this function into a generic btree walker, add a couple parameters to control termination behavior from various contexts and reuse it where applicable. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 110 +++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 55 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 6428d0a79213..63b42320c472 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -875,6 +875,13 @@ xfs_alloc_cur_check( acur->diff = diff; *new = 1; + /* + * We're done if we found a perfect allocation. This only deactivates + * the current cursor, but this is just an optimization to terminate a + * cntbt search that otherwise runs to the edge of the tree. + */ + if (acur->diff == 0 && acur->len == args->maxlen) + deactivate = true; out: if (deactivate) cur->bc_private.a.priv.abt.active = false; @@ -1172,30 +1179,38 @@ error0: } /* - * Search the btree in a given direction and check the records against the good - * extent we've already found. + * Search a given number of btree records in a given direction. Check each + * record against the good extent we've already found. */ STATIC int -xfs_alloc_find_best_extent( +xfs_alloc_walk_iter( struct xfs_alloc_arg *args, struct xfs_alloc_cur *acur, struct xfs_btree_cur *cur, - bool increment) + bool increment, + bool find_one, /* quit on first candidate */ + int count, /* rec count (-1 for infinite) */ + int *stat) { int error; int i; + *stat = 0; + /* * Search so long as the cursor is active or we find a better extent. * The cursor is deactivated if it extends beyond the range of the * current allocation candidate. */ - while (xfs_alloc_cur_active(cur)) { + while (xfs_alloc_cur_active(cur) && count) { error = xfs_alloc_cur_check(args, acur, cur, &i); if (error) return error; - if (i == 1) - break; + if (i == 1) { + *stat = 1; + if (find_one) + break; + } if (!xfs_alloc_cur_active(cur)) break; @@ -1207,6 +1222,9 @@ xfs_alloc_find_best_extent( return error; if (i == 0) cur->bc_private.a.priv.abt.active = false; + + if (count > 0) + count--; } return 0; @@ -1226,7 +1244,6 @@ xfs_alloc_ag_vextent_near( struct xfs_btree_cur *fbcur = NULL; int error; /* error code */ int i; /* result code, temporary */ - int j; /* result code, temporary */ xfs_agblock_t bno; xfs_extlen_t len; bool fbinc = false; @@ -1313,19 +1330,12 @@ restart: if (!i) break; } - i = acur.cnt->bc_ptrs[0]; - for (j = 1; - !error && j && xfs_alloc_cur_active(acur.cnt) && - (acur.len < args->maxlen || acur.diff > 0); - error = xfs_btree_increment(acur.cnt, 0, &j)) { - /* - * For each entry, decide if it's better than - * the previous best entry. - */ - error = xfs_alloc_cur_check(args, &acur, acur.cnt, &i); - if (error) - goto out; - } + + error = xfs_alloc_walk_iter(args, &acur, acur.cnt, true, false, + -1, &i); + if (error) + goto out; + /* * It didn't work. We COULD be in a case where * there's a good record somewhere, so try again. @@ -1357,49 +1367,39 @@ restart: goto out; /* - * Loop going left with the leftward cursor, right with the - * rightward cursor, until either both directions give up or - * we find an entry at least as big as minlen. + * Loop going left with the leftward cursor, right with the rightward + * cursor, until either both directions give up or we find an entry at + * least as big as minlen. */ do { - if (xfs_alloc_cur_active(acur.bnolt)) { - error = xfs_alloc_cur_check(args, &acur, acur.bnolt, &i); - if (error) - goto out; - if (i == 1) { - trace_xfs_alloc_cur_left(args); - fbcur = acur.bnogt; - fbinc = true; - break; - } - error = xfs_btree_decrement(acur.bnolt, 0, &i); - if (error) - goto out; - if (!i) - acur.bnolt->bc_private.a.priv.abt.active = false; + error = xfs_alloc_walk_iter(args, &acur, acur.bnolt, false, + true, 1, &i); + if (error) + goto out; + if (i == 1) { + trace_xfs_alloc_cur_left(args); + fbcur = acur.bnogt; + fbinc = true; + break; } - if (xfs_alloc_cur_active(acur.bnogt)) { - error = xfs_alloc_cur_check(args, &acur, acur.bnogt, &i); - if (error) - goto out; - if (i == 1) { - trace_xfs_alloc_cur_right(args); - fbcur = acur.bnolt; - fbinc = false; - break; - } - error = xfs_btree_increment(acur.bnogt, 0, &i); - if (error) - goto out; - if (!i) - acur.bnogt->bc_private.a.priv.abt.active = false; + + error = xfs_alloc_walk_iter(args, &acur, acur.bnogt, true, true, + 1, &i); + if (error) + goto out; + if (i == 1) { + trace_xfs_alloc_cur_right(args); + fbcur = acur.bnolt; + fbinc = false; + break; } } while (xfs_alloc_cur_active(acur.bnolt) || xfs_alloc_cur_active(acur.bnogt)); /* search the opposite direction for a better entry */ if (fbcur) { - error = xfs_alloc_find_best_extent(args, &acur, fbcur, fbinc); + error = xfs_alloc_walk_iter(args, &acur, fbcur, fbinc, true, -1, + &i); if (error) goto out; } -- cgit v1.2.3-70-g09d2 From 0e26d5ca4a40211a4e2acd15a5cb229184c1f867 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:35 -0700 Subject: xfs: refactor near mode alloc bnobt scan into separate function In preparation to enhance the near mode allocation bnobt scan algorithm, lift it into a separate function. No functional changes. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 128 +++++++++++++++++++++++++++------------------- 1 file changed, 74 insertions(+), 54 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 63b42320c472..facff6cb27a5 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1230,6 +1230,78 @@ xfs_alloc_walk_iter( return 0; } +/* + * Search in the by-bno btree to the left and to the right simultaneously until + * in each case we find a large enough free extent or run into the edge of the + * tree. When we run into the edge of the tree, we deactivate that cursor. + */ +STATIC int +xfs_alloc_ag_vextent_bnobt( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur, + int *stat) +{ + struct xfs_btree_cur *fbcur = NULL; + int error; + int i; + bool fbinc; + + ASSERT(acur->len == 0); + ASSERT(args->type == XFS_ALLOCTYPE_NEAR_BNO); + + *stat = 0; + + error = xfs_alloc_lookup_le(acur->bnolt, args->agbno, 0, &i); + if (error) + return error; + error = xfs_alloc_lookup_ge(acur->bnogt, args->agbno, 0, &i); + if (error) + return error; + + /* + * Loop going left with the leftward cursor, right with the rightward + * cursor, until either both directions give up or we find an entry at + * least as big as minlen. + */ + while (xfs_alloc_cur_active(acur->bnolt) || + xfs_alloc_cur_active(acur->bnogt)) { + error = xfs_alloc_walk_iter(args, acur, acur->bnolt, false, + true, 1, &i); + if (error) + return error; + if (i == 1) { + trace_xfs_alloc_cur_left(args); + fbcur = acur->bnogt; + fbinc = true; + break; + } + + error = xfs_alloc_walk_iter(args, acur, acur->bnogt, true, true, + 1, &i); + if (error) + return error; + if (i == 1) { + trace_xfs_alloc_cur_right(args); + fbcur = acur->bnolt; + fbinc = false; + break; + } + } + + /* search the opposite direction for a better entry */ + if (fbcur) { + error = xfs_alloc_walk_iter(args, acur, fbcur, fbinc, true, -1, + &i); + if (error) + return error; + } + + if (acur->len) + *stat = 1; + + return 0; +} + /* * Allocate a variable extent near bno in the allocation group agno. * Extent's length (returned in len) will be between minlen and maxlen, @@ -1241,12 +1313,10 @@ xfs_alloc_ag_vextent_near( struct xfs_alloc_arg *args) { struct xfs_alloc_cur acur = {}; - struct xfs_btree_cur *fbcur = NULL; int error; /* error code */ int i; /* result code, temporary */ xfs_agblock_t bno; xfs_extlen_t len; - bool fbinc = false; #ifdef DEBUG /* * Randomly don't execute the first algorithm. @@ -1348,62 +1418,12 @@ restart: } /* - * Second algorithm. - * Search in the by-bno tree to the left and to the right - * simultaneously, until in each case we find a space big enough, - * or run into the edge of the tree. When we run into the edge, - * we deallocate that cursor. - * If both searches succeed, we compare the two spaces and pick - * the better one. - * With alignment, it's possible for both to fail; the upper - * level algorithm that picks allocation groups for allocations - * is not supposed to do this. + * Second algorithm. Search the bnobt left and right. */ - error = xfs_alloc_lookup_le(acur.bnolt, args->agbno, 0, &i); - if (error) - goto out; - error = xfs_alloc_lookup_ge(acur.bnogt, args->agbno, 0, &i); + error = xfs_alloc_ag_vextent_bnobt(args, &acur, &i); if (error) goto out; - /* - * Loop going left with the leftward cursor, right with the rightward - * cursor, until either both directions give up or we find an entry at - * least as big as minlen. - */ - do { - error = xfs_alloc_walk_iter(args, &acur, acur.bnolt, false, - true, 1, &i); - if (error) - goto out; - if (i == 1) { - trace_xfs_alloc_cur_left(args); - fbcur = acur.bnogt; - fbinc = true; - break; - } - - error = xfs_alloc_walk_iter(args, &acur, acur.bnogt, true, true, - 1, &i); - if (error) - goto out; - if (i == 1) { - trace_xfs_alloc_cur_right(args); - fbcur = acur.bnolt; - fbinc = false; - break; - } - } while (xfs_alloc_cur_active(acur.bnolt) || - xfs_alloc_cur_active(acur.bnogt)); - - /* search the opposite direction for a better entry */ - if (fbcur) { - error = xfs_alloc_walk_iter(args, &acur, fbcur, fbinc, true, -1, - &i); - if (error) - goto out; - } - /* * If we couldn't get anything, give up. */ -- cgit v1.2.3-70-g09d2 From d29688257fd425f7c64c3525fea29658b50fc390 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:35 -0700 Subject: xfs: factor out tree fixup logic into helper Lift the btree fixup path into a helper function. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 42 ++++++++++++++++++++++++++++++++---------- fs/xfs/xfs_trace.h | 1 + 2 files changed, 33 insertions(+), 10 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index facff6cb27a5..8191301a9039 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -890,6 +890,36 @@ out: return 0; } +/* + * Complete an allocation of a candidate extent. Remove the extent from both + * trees and update the args structure. + */ +STATIC int +xfs_alloc_cur_finish( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur) +{ + int error; + + ASSERT(acur->cnt && acur->bnolt); + ASSERT(acur->bno >= acur->rec_bno); + ASSERT(acur->bno + acur->len <= acur->rec_bno + acur->rec_len); + ASSERT(acur->rec_bno + acur->rec_len <= + be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); + + error = xfs_alloc_fixup_trees(acur->cnt, acur->bnolt, acur->rec_bno, + acur->rec_len, acur->bno, acur->len, 0); + if (error) + return error; + + args->agbno = acur->bno; + args->len = acur->len; + args->wasfromfl = 0; + + trace_xfs_alloc_cur(args); + return 0; +} + /* * Deal with the case where only small freespaces remain. Either return the * contents of the last freespace record, or allocate space from the freelist if @@ -1359,7 +1389,6 @@ restart: } else if (error) { goto out; } - args->wasfromfl = 0; /* * First algorithm. @@ -1440,15 +1469,8 @@ restart: } alloc: - args->agbno = acur.bno; - args->len = acur.len; - ASSERT(acur.bno >= acur.rec_bno); - ASSERT(acur.bno + acur.len <= acur.rec_bno + acur.rec_len); - ASSERT(acur.rec_bno + acur.rec_len <= - be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); - - error = xfs_alloc_fixup_trees(acur.cnt, acur.bnolt, acur.rec_bno, - acur.rec_len, acur.bno, acur.len, 0); + /* fix up btrees on a successful allocation */ + error = xfs_alloc_cur_finish(args, &acur); out: xfs_alloc_cur_close(&acur, error); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index cdc5f000d608..2eef14791cc5 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1577,6 +1577,7 @@ DEFINE_ALLOC_EVENT(xfs_alloc_exact_notfound); DEFINE_ALLOC_EVENT(xfs_alloc_exact_error); DEFINE_ALLOC_EVENT(xfs_alloc_near_nominleft); DEFINE_ALLOC_EVENT(xfs_alloc_near_first); +DEFINE_ALLOC_EVENT(xfs_alloc_cur); DEFINE_ALLOC_EVENT(xfs_alloc_cur_right); DEFINE_ALLOC_EVENT(xfs_alloc_cur_left); DEFINE_ALLOC_EVENT(xfs_alloc_near_error); -- cgit v1.2.3-70-g09d2 From dc8e69bd721840bc22ffe5aa8598fd92b44f0334 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Sun, 13 Oct 2019 17:10:36 -0700 Subject: xfs: optimize near mode bnobt scans with concurrent cntbt lookups The near mode fallback algorithm consists of a left/right scan of the bnobt. This algorithm has very poor breakdown characteristics under worst case free space fragmentation conditions. If a suitable extent is far enough from the locality hint, each allocation may scan most or all of the bnobt before it completes. This causes pathological behavior and extremely high allocation latencies. While locality is important to near mode allocations, it is not so important as to incur pathological allocation latency to provide the asolute best available locality for every allocation. If the allocation is large enough or far enough away, there is a point of diminishing returns. As such, we can bound the overall operation by including an iterative cntbt lookup in the broader search. The cntbt lookup is optimized to immediately find the extent with best locality for the given size on each iteration. Since the cntbt is indexed by extent size, the lookup repeats with a variably aggressive increasing search key size until it runs off the edge of the tree. This approach provides a natural balance between the two algorithms for various situations. For example, the bnobt scan is able to satisfy smaller allocations such as for inode chunks or btree blocks more quickly where the cntbt search may have to search through a large set of extent sizes when the search key starts off small relative to the largest extent in the tree. On the other hand, the cntbt search more deterministically covers the set of suitable extents for larger data extent allocation requests that the bnobt scan may have to search the entire tree to locate. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 154 ++++++++++++++++++++++++++++++++++++++++++---- fs/xfs/xfs_trace.h | 2 + 2 files changed, 144 insertions(+), 12 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 8191301a9039..925eba9489d5 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -716,6 +716,7 @@ struct xfs_alloc_cur { struct xfs_btree_cur *cnt; /* btree cursors */ struct xfs_btree_cur *bnolt; struct xfs_btree_cur *bnogt; + xfs_extlen_t cur_len;/* current search length */ xfs_agblock_t rec_bno;/* extent startblock */ xfs_extlen_t rec_len;/* extent length */ xfs_agblock_t bno; /* alloc bno */ @@ -740,6 +741,7 @@ xfs_alloc_cur_setup( ASSERT(args->alignment == 1 || args->type != XFS_ALLOCTYPE_THIS_BNO); + acur->cur_len = args->maxlen; acur->rec_bno = 0; acur->rec_len = 0; acur->bno = 0; @@ -920,6 +922,76 @@ xfs_alloc_cur_finish( return 0; } +/* + * Locality allocation lookup algorithm. This expects a cntbt cursor and uses + * bno optimized lookup to search for extents with ideal size and locality. + */ +STATIC int +xfs_alloc_cntbt_iter( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur) +{ + struct xfs_btree_cur *cur = acur->cnt; + xfs_agblock_t bno; + xfs_extlen_t len, cur_len; + int error; + int i; + + if (!xfs_alloc_cur_active(cur)) + return 0; + + /* locality optimized lookup */ + cur_len = acur->cur_len; + error = xfs_alloc_lookup_ge(cur, args->agbno, cur_len, &i); + if (error) + return error; + if (i == 0) + return 0; + error = xfs_alloc_get_rec(cur, &bno, &len, &i); + if (error) + return error; + + /* check the current record and update search length from it */ + error = xfs_alloc_cur_check(args, acur, cur, &i); + if (error) + return error; + ASSERT(len >= acur->cur_len); + acur->cur_len = len; + + /* + * We looked up the first record >= [agbno, len] above. The agbno is a + * secondary key and so the current record may lie just before or after + * agbno. If it is past agbno, check the previous record too so long as + * the length matches as it may be closer. Don't check a smaller record + * because that could deactivate our cursor. + */ + if (bno > args->agbno) { + error = xfs_btree_decrement(cur, 0, &i); + if (!error && i) { + error = xfs_alloc_get_rec(cur, &bno, &len, &i); + if (!error && i && len == acur->cur_len) + error = xfs_alloc_cur_check(args, acur, cur, + &i); + } + if (error) + return error; + } + + /* + * Increment the search key until we find at least one allocation + * candidate or if the extent we found was larger. Otherwise, double the + * search key to optimize the search. Efficiency is more important here + * than absolute best locality. + */ + cur_len <<= 1; + if (!acur->len || acur->cur_len >= cur_len) + acur->cur_len++; + else + acur->cur_len = cur_len; + + return error; +} + /* * Deal with the case where only small freespaces remain. Either return the * contents of the last freespace record, or allocate space from the freelist if @@ -1261,12 +1333,11 @@ xfs_alloc_walk_iter( } /* - * Search in the by-bno btree to the left and to the right simultaneously until - * in each case we find a large enough free extent or run into the edge of the - * tree. When we run into the edge of the tree, we deactivate that cursor. + * Search the by-bno and by-size btrees in parallel in search of an extent with + * ideal locality based on the NEAR mode ->agbno locality hint. */ STATIC int -xfs_alloc_ag_vextent_bnobt( +xfs_alloc_ag_vextent_locality( struct xfs_alloc_arg *args, struct xfs_alloc_cur *acur, int *stat) @@ -1281,6 +1352,9 @@ xfs_alloc_ag_vextent_bnobt( *stat = 0; + error = xfs_alloc_lookup_ge(acur->cnt, args->agbno, acur->cur_len, &i); + if (error) + return error; error = xfs_alloc_lookup_le(acur->bnolt, args->agbno, 0, &i); if (error) return error; @@ -1289,12 +1363,37 @@ xfs_alloc_ag_vextent_bnobt( return error; /* - * Loop going left with the leftward cursor, right with the rightward - * cursor, until either both directions give up or we find an entry at - * least as big as minlen. + * Search the bnobt and cntbt in parallel. Search the bnobt left and + * right and lookup the closest extent to the locality hint for each + * extent size key in the cntbt. The entire search terminates + * immediately on a bnobt hit because that means we've found best case + * locality. Otherwise the search continues until the cntbt cursor runs + * off the end of the tree. If no allocation candidate is found at this + * point, give up on locality, walk backwards from the end of the cntbt + * and take the first available extent. + * + * The parallel tree searches balance each other out to provide fairly + * consistent performance for various situations. The bnobt search can + * have pathological behavior in the worst case scenario of larger + * allocation requests and fragmented free space. On the other hand, the + * bnobt is able to satisfy most smaller allocation requests much more + * quickly than the cntbt. The cntbt search can sift through fragmented + * free space and sets of free extents for larger allocation requests + * more quickly than the bnobt. Since the locality hint is just a hint + * and we don't want to scan the entire bnobt for perfect locality, the + * cntbt search essentially bounds the bnobt search such that we can + * find good enough locality at reasonable performance in most cases. */ while (xfs_alloc_cur_active(acur->bnolt) || - xfs_alloc_cur_active(acur->bnogt)) { + xfs_alloc_cur_active(acur->bnogt) || + xfs_alloc_cur_active(acur->cnt)) { + + trace_xfs_alloc_cur_lookup(args); + + /* + * Search the bnobt left and right. In the case of a hit, finish + * the search in the opposite direction and we're done. + */ error = xfs_alloc_walk_iter(args, acur, acur->bnolt, false, true, 1, &i); if (error) @@ -1305,7 +1404,6 @@ xfs_alloc_ag_vextent_bnobt( fbinc = true; break; } - error = xfs_alloc_walk_iter(args, acur, acur->bnogt, true, true, 1, &i); if (error) @@ -1316,9 +1414,40 @@ xfs_alloc_ag_vextent_bnobt( fbinc = false; break; } + + /* + * Check the extent with best locality based on the current + * extent size search key and keep track of the best candidate. + */ + error = xfs_alloc_cntbt_iter(args, acur); + if (error) + return error; + if (!xfs_alloc_cur_active(acur->cnt)) { + trace_xfs_alloc_cur_lookup_done(args); + break; + } + } + + /* + * If we failed to find anything due to busy extents, return empty + * handed so the caller can flush and retry. If no busy extents were + * found, walk backwards from the end of the cntbt as a last resort. + */ + if (!xfs_alloc_cur_active(acur->cnt) && !acur->len && !acur->busy) { + error = xfs_btree_decrement(acur->cnt, 0, &i); + if (error) + return error; + if (i) { + acur->cnt->bc_private.a.priv.abt.active = true; + fbcur = acur->cnt; + fbinc = false; + } } - /* search the opposite direction for a better entry */ + /* + * Search in the opposite direction for a better entry in the case of + * a bnobt hit or walk backwards from the end of the cntbt. + */ if (fbcur) { error = xfs_alloc_walk_iter(args, acur, fbcur, fbinc, true, -1, &i); @@ -1447,9 +1576,10 @@ restart: } /* - * Second algorithm. Search the bnobt left and right. + * Second algorithm. Combined cntbt and bnobt search to find ideal + * locality. */ - error = xfs_alloc_ag_vextent_bnobt(args, &acur, &i); + error = xfs_alloc_ag_vextent_locality(args, &acur, &i); if (error) goto out; diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 2eef14791cc5..926f4d10dc02 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1580,6 +1580,8 @@ DEFINE_ALLOC_EVENT(xfs_alloc_near_first); DEFINE_ALLOC_EVENT(xfs_alloc_cur); DEFINE_ALLOC_EVENT(xfs_alloc_cur_right); DEFINE_ALLOC_EVENT(xfs_alloc_cur_left); +DEFINE_ALLOC_EVENT(xfs_alloc_cur_lookup); +DEFINE_ALLOC_EVENT(xfs_alloc_cur_lookup_done); DEFINE_ALLOC_EVENT(xfs_alloc_near_error); DEFINE_ALLOC_EVENT(xfs_alloc_near_noentry); DEFINE_ALLOC_EVENT(xfs_alloc_near_busy); -- cgit v1.2.3-70-g09d2 From 1c743574de8b5a47c323c0dc3089985b38f83390 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 21 Oct 2019 09:26:34 -0700 Subject: xfs: cap longest free extent to maximum allocatable Cap longest extent to the largest we can allocate based on limits calculated at mount time. Dynamic state (such as finobt blocks) can result in the longest free extent exceeding the size we can allocate, and that results in failure to align full AG allocations when the AG is empty. Result: xfs_io-4413 [003] 426.412459: xfs_alloc_vextent_loopfailed: dev 8:96 agno 0 agbno 32 minlen 243968 maxlen 244000 mod 0 prod 1 minleft 1 total 262148 alignment 32 minalignslop 0 len 0 type NEAR_BNO otype START_BNO wasdel 0 wasfromfl 0 resv 0 datatype 0x5 firstblock 0xffffffffffffffff minlen and maxlen are now separated by the alignment size, and allocation fails because args.total > free space in the AG. [bfoster: Added xfs_bmap_btalloc() changes.] Signed-off-by: Dave Chinner Signed-off-by: Carlos Maiolino Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 3 ++- fs/xfs/libxfs/xfs_bmap.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 925eba9489d5..84866c195bfc 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2116,7 +2116,8 @@ xfs_alloc_longest_free_extent( * reservations and AGFL rules in place, we can return this extent. */ if (pag->pagf_longest > delta) - return pag->pagf_longest - delta; + return min_t(xfs_extlen_t, pag->pag_mount->m_ag_max_usable, + pag->pagf_longest - delta); /* Otherwise, let the caller try for 1 block if there's space. */ return pag->pagf_flcount > 0 || pag->pagf_longest > 0; diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index ef75e223cb70..3b300b518f69 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -3501,13 +3501,11 @@ xfs_bmap_btalloc( args.mod = args.prod - args.mod; } /* - * If we are not low on available data blocks, and the - * underlying logical volume manager is a stripe, and - * the file offset is zero then try to allocate data - * blocks on stripe unit boundary. - * NOTE: ap->aeof is only set if the allocation length - * is >= the stripe unit and the allocation offset is - * at the end of file. + * If we are not low on available data blocks, and the underlying + * logical volume manager is a stripe, and the file offset is zero then + * try to allocate data blocks on stripe unit boundary. NOTE: ap->aeof + * is only set if the allocation length is >= the stripe unit and the + * allocation offset is at the end of file. */ if (!(ap->tp->t_flags & XFS_TRANS_LOWMODE) && ap->aeof) { if (!ap->offset) { @@ -3515,9 +3513,11 @@ xfs_bmap_btalloc( atype = args.type; isaligned = 1; /* - * Adjust for alignment + * Adjust minlen to try and preserve alignment if we + * can't guarantee an aligned maxlen extent. */ - if (blen > args.alignment && blen <= args.maxlen) + if (blen > args.alignment && + blen <= args.maxlen + args.alignment) args.minlen = blen - args.alignment; args.minalignslop = 0; } else { -- cgit v1.2.3-70-g09d2 From fd638f1de1f3f736ea4debb3582999ea95506e0a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 30 Oct 2019 12:25:00 -0700 Subject: xfs: move extent zeroing to xfs_bmapi_allocate Move the extent zeroing case there for the XFS_BMAPI_ZERO flag outside the low-level allocator and into xfs_bmapi_allocate, where is still is in transaction context, but outside the very lowlevel code where it doesn't belong. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 7 ------- fs/xfs/libxfs/xfs_alloc.h | 4 +--- fs/xfs/libxfs/xfs_bmap.c | 10 ++++++---- fs/xfs/xfs_bmap_util.c | 7 ------- 4 files changed, 7 insertions(+), 21 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 84866c195bfc..0539d61ff12c 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -3084,13 +3084,6 @@ xfs_alloc_vextent( args->len); #endif - /* Zero the extent if we were asked to do so */ - if (args->datatype & XFS_ALLOC_USERDATA_ZERO) { - error = xfs_zero_extent(args->ip, args->fsbno, args->len); - if (error) - goto error0; - } - } xfs_perag_put(args->pag); return 0; diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index d6ed5d2c07c2..626384d75c9c 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -54,7 +54,6 @@ typedef struct xfs_alloc_arg { struct xfs_mount *mp; /* file system mount point */ struct xfs_buf *agbp; /* buffer for a.g. freelist header */ struct xfs_perag *pag; /* per-ag struct for this agno */ - struct xfs_inode *ip; /* for userdata zeroing method */ xfs_fsblock_t fsbno; /* file system block number */ xfs_agnumber_t agno; /* allocation group number */ xfs_agblock_t agbno; /* allocation group-relative block # */ @@ -83,8 +82,7 @@ typedef struct xfs_alloc_arg { */ #define XFS_ALLOC_USERDATA (1 << 0)/* allocation is for user data*/ #define XFS_ALLOC_INITIAL_USER_DATA (1 << 1)/* special case start of file */ -#define XFS_ALLOC_USERDATA_ZERO (1 << 2)/* zero extent on allocation */ -#define XFS_ALLOC_NOBUSY (1 << 3)/* Busy extents not allowed */ +#define XFS_ALLOC_NOBUSY (1 << 2)/* Busy extents not allowed */ static inline bool xfs_alloc_is_userdata(int datatype) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 6af74f08b1c7..3fcc91027f63 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -3518,8 +3518,6 @@ xfs_bmap_btalloc( args.wasdel = ap->wasdel; args.resv = XFS_AG_RESV_NONE; args.datatype = ap->datatype; - if (ap->datatype & XFS_ALLOC_USERDATA_ZERO) - args.ip = ap->ip; error = xfs_alloc_vextent(&args); if (error) @@ -3974,8 +3972,6 @@ xfs_bmap_alloc_userdata( * the busy list. */ bma->datatype = XFS_ALLOC_NOBUSY; - if (bma->flags & XFS_BMAPI_ZERO) - bma->datatype |= XFS_ALLOC_USERDATA_ZERO; if (whichfork == XFS_DATA_FORK) { if (bma->offset == 0) bma->datatype |= XFS_ALLOC_INITIAL_USER_DATA; @@ -4034,6 +4030,12 @@ xfs_bmapi_allocate( if (error || bma->blkno == NULLFSBLOCK) return error; + if (bma->flags & XFS_BMAPI_ZERO) { + error = xfs_zero_extent(bma->ip, bma->blkno, bma->length); + if (error) + return error; + } + if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork); /* diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 4f7bce901fea..9d731b71e84f 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -165,13 +165,6 @@ xfs_bmap_rtalloc( xfs_trans_mod_dquot_byino(ap->tp, ap->ip, ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : XFS_TRANS_DQ_RTBCOUNT, (long) ralen); - - /* Zero the extent if we were asked to do so */ - if (ap->datatype & XFS_ALLOC_USERDATA_ZERO) { - error = xfs_zero_extent(ap->ip, ap->blkno, ap->length); - if (error) - return error; - } } else { ap->length = 0; } -- cgit v1.2.3-70-g09d2 From c34d570d158699c6c812f5df653aaf2e3a83acca Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 30 Oct 2019 12:25:00 -0700 Subject: xfs: cleanup use of the XFS_ALLOC_ flags Always set XFS_ALLOC_USERDATA for data fork allocations, and check it in xfs_alloc_is_userdata instead of the current obsfucated check. Also remove the xfs_alloc_is_userdata and xfs_alloc_allow_busy_reuse helpers to make the code a little easier to understand. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 8 ++++---- fs/xfs/libxfs/xfs_alloc.h | 12 ------------ fs/xfs/libxfs/xfs_bmap.c | 11 +++++------ fs/xfs/xfs_extent_busy.c | 2 +- fs/xfs/xfs_filestream.c | 2 +- 5 files changed, 11 insertions(+), 24 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 0539d61ff12c..b8d48d5fa6a5 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -331,7 +331,7 @@ xfs_alloc_compute_diff( xfs_extlen_t newlen1=0; /* length with newbno1 */ xfs_extlen_t newlen2=0; /* length with newbno2 */ xfs_agblock_t wantend; /* end of target extent */ - bool userdata = xfs_alloc_is_userdata(datatype); + bool userdata = datatype & XFS_ALLOC_USERDATA; ASSERT(freelen >= wantlen); freeend = freebno + freelen; @@ -1041,9 +1041,9 @@ xfs_alloc_ag_vextent_small( goto out; xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, - xfs_alloc_allow_busy_reuse(args->datatype)); + (args->datatype & XFS_ALLOC_NOBUSY)); - if (xfs_alloc_is_userdata(args->datatype)) { + if (args->datatype & XFS_ALLOC_USERDATA) { struct xfs_buf *bp; bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno); @@ -2381,7 +2381,7 @@ xfs_alloc_fix_freelist( * somewhere else if we are not being asked to try harder at this * point */ - if (pag->pagf_metadata && xfs_alloc_is_userdata(args->datatype) && + if (pag->pagf_metadata && (args->datatype & XFS_ALLOC_USERDATA) && (flags & XFS_ALLOC_FLAG_TRYLOCK)) { ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); goto out_agbp_relse; diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index 626384d75c9c..7380fbe4a3ff 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -84,18 +84,6 @@ typedef struct xfs_alloc_arg { #define XFS_ALLOC_INITIAL_USER_DATA (1 << 1)/* special case start of file */ #define XFS_ALLOC_NOBUSY (1 << 2)/* Busy extents not allowed */ -static inline bool -xfs_alloc_is_userdata(int datatype) -{ - return (datatype & ~XFS_ALLOC_NOBUSY) != 0; -} - -static inline bool -xfs_alloc_allow_busy_reuse(int datatype) -{ - return (datatype & XFS_ALLOC_NOBUSY) == 0; -} - /* freespace limit calculations */ #define XFS_ALLOC_AGFL_RESERVE 4 unsigned int xfs_alloc_set_aside(struct xfs_mount *mp); diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 3fcc91027f63..bbabbb41e9d8 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -3022,7 +3022,7 @@ xfs_bmap_adjacent( mp = ap->ip->i_mount; nullfb = ap->tp->t_firstblock == NULLFSBLOCK; rt = XFS_IS_REALTIME_INODE(ap->ip) && - xfs_alloc_is_userdata(ap->datatype); + (ap->datatype & XFS_ALLOC_USERDATA); fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->tp->t_firstblock); /* @@ -3375,7 +3375,7 @@ xfs_bmap_btalloc( if (ap->flags & XFS_BMAPI_COWFORK) align = xfs_get_cowextsz_hint(ap->ip); - else if (xfs_alloc_is_userdata(ap->datatype)) + else if (ap->datatype & XFS_ALLOC_USERDATA) align = xfs_get_extsz_hint(ap->ip); if (align) { error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, @@ -3390,7 +3390,7 @@ xfs_bmap_btalloc( fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->tp->t_firstblock); if (nullfb) { - if (xfs_alloc_is_userdata(ap->datatype) && + if ((ap->datatype & XFS_ALLOC_USERDATA) && xfs_inode_is_filestream(ap->ip)) { ag = xfs_filestream_lookup_ag(ap->ip); ag = (ag != NULLAGNUMBER) ? ag : 0; @@ -3430,7 +3430,7 @@ xfs_bmap_btalloc( * enough for the request. If one isn't found, then adjust * the minimum allocation size to the largest space found. */ - if (xfs_alloc_is_userdata(ap->datatype) && + if ((ap->datatype & XFS_ALLOC_USERDATA) && xfs_inode_is_filestream(ap->ip)) error = xfs_bmap_btalloc_filestreams(ap, &args, &blen); else @@ -3973,10 +3973,9 @@ xfs_bmap_alloc_userdata( */ bma->datatype = XFS_ALLOC_NOBUSY; if (whichfork == XFS_DATA_FORK) { + bma->datatype |= XFS_ALLOC_USERDATA; if (bma->offset == 0) bma->datatype |= XFS_ALLOC_INITIAL_USER_DATA; - else - bma->datatype |= XFS_ALLOC_USERDATA; if (mp->m_dalign && bma->length >= mp->m_dalign) { error = xfs_bmap_isaeof(bma, whichfork); diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c index 2183d87be4cf..3991e59cfd18 100644 --- a/fs/xfs/xfs_extent_busy.c +++ b/fs/xfs/xfs_extent_busy.c @@ -367,7 +367,7 @@ restart: * If this is a metadata allocation, try to reuse the busy * extent instead of trimming the allocation. */ - if (!xfs_alloc_is_userdata(args->datatype) && + if (!(args->datatype & XFS_ALLOC_USERDATA) && !(busyp->flags & XFS_EXTENT_BUSY_DISCARDED)) { if (!xfs_extent_busy_update_extent(args->mp, args->pag, busyp, fbno, flen, diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 574a7a8b4736..2ae356775f63 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -374,7 +374,7 @@ xfs_filestream_new_ag( startag = (item->ag + 1) % mp->m_sb.sb_agcount; } - if (xfs_alloc_is_userdata(ap->datatype)) + if (ap->datatype & XFS_ALLOC_USERDATA) flags |= XFS_PICK_USERDATA; if (ap->tp->t_flags & XFS_TRANS_LOWMODE) flags |= XFS_PICK_LOWSPACE; -- cgit v1.2.3-70-g09d2 From a5155b870d687de1a5f07e774b49b1e8ef0f6f50 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Sat, 2 Nov 2019 09:40:53 -0700 Subject: xfs: always log corruption errors Make sure we log something to dmesg whenever we return -EFSCORRUPTED up the call stack. Signed-off-by: Darrick J. Wong Reviewed-by: Carlos Maiolino Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_alloc.c | 9 +++++++-- fs/xfs/libxfs/xfs_attr_leaf.c | 12 +++++++++--- fs/xfs/libxfs/xfs_bmap.c | 8 +++++++- fs/xfs/libxfs/xfs_btree.c | 5 ++++- fs/xfs/libxfs/xfs_da_btree.c | 24 ++++++++++++++++++------ fs/xfs/libxfs/xfs_dir2.c | 4 +++- fs/xfs/libxfs/xfs_dir2_leaf.c | 4 +++- fs/xfs/libxfs/xfs_dir2_node.c | 12 +++++++++--- fs/xfs/libxfs/xfs_inode_fork.c | 6 ++++++ fs/xfs/libxfs/xfs_refcount.c | 4 +++- fs/xfs/libxfs/xfs_rtbitmap.c | 6 ++++-- fs/xfs/xfs_acl.c | 15 ++++++++++++--- fs/xfs/xfs_attr_inactive.c | 6 +++++- fs/xfs/xfs_attr_list.c | 5 ++++- fs/xfs/xfs_bmap_item.c | 3 ++- fs/xfs/xfs_error.c | 21 +++++++++++++++++++++ fs/xfs/xfs_error.h | 1 + fs/xfs/xfs_extfree_item.c | 3 ++- fs/xfs/xfs_inode.c | 15 ++++++++++++--- fs/xfs/xfs_inode_item.c | 5 ++++- fs/xfs/xfs_iops.c | 10 +++++++--- fs/xfs/xfs_log_recover.c | 23 ++++++++++++++++++----- fs/xfs/xfs_qm.c | 13 +++++++++++-- fs/xfs/xfs_refcount_item.c | 3 ++- fs/xfs/xfs_rmap_item.c | 7 +++++-- 25 files changed, 179 insertions(+), 45 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index b8d48d5fa6a5..f7a4b54c5bc2 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -702,8 +702,10 @@ xfs_alloc_update_counters( xfs_trans_agblocks_delta(tp, len); if (unlikely(be32_to_cpu(agf->agf_freeblks) > - be32_to_cpu(agf->agf_length))) + be32_to_cpu(agf->agf_length))) { + xfs_buf_corruption_error(agbp); return -EFSCORRUPTED; + } xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); return 0; @@ -1048,6 +1050,7 @@ xfs_alloc_ag_vextent_small( bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno); if (!bp) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->mp); error = -EFSCORRUPTED; goto error; } @@ -2215,8 +2218,10 @@ xfs_free_agfl_block( return error; bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno); - if (!bp) + if (!bp) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, tp->t_mountp); return -EFSCORRUPTED; + } xfs_trans_binval(tp, bp); return 0; diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 56e62b3d9bb7..dca8840496ea 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -2346,8 +2346,10 @@ xfs_attr3_leaf_lookup_int( leaf = bp->b_addr; xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf); entries = xfs_attr3_leaf_entryp(leaf); - if (ichdr.count >= args->geo->blksize / 8) + if (ichdr.count >= args->geo->blksize / 8) { + xfs_buf_corruption_error(bp); return -EFSCORRUPTED; + } /* * Binary search. (note: small blocks will skip this loop) @@ -2363,10 +2365,14 @@ xfs_attr3_leaf_lookup_int( else break; } - if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count))) + if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count))) { + xfs_buf_corruption_error(bp); return -EFSCORRUPTED; - if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval)) + } + if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval)) { + xfs_buf_corruption_error(bp); return -EFSCORRUPTED; + } /* * Since we may have duplicate hashval's, find the first matching diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index bbabbb41e9d8..64f623d07f82 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -730,6 +730,7 @@ xfs_bmap_extents_to_btree( xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L); abp = xfs_btree_get_bufl(mp, tp, args.fsbno); if (!abp) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto out_unreserve_dquot; } @@ -1085,6 +1086,7 @@ xfs_bmap_add_attrfork( if (XFS_IFORK_Q(ip)) goto trans_cancel; if (ip->i_d.di_anextents != 0) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto trans_cancel; } @@ -1338,6 +1340,7 @@ xfs_bmap_last_before( case XFS_DINODE_FMT_EXTENTS: break; default: + ASSERT(0); return -EFSCORRUPTED; } @@ -1438,8 +1441,10 @@ xfs_bmap_last_offset( return 0; if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) { + ASSERT(0); return -EFSCORRUPTED; + } error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty); if (error || is_empty) @@ -5830,6 +5835,7 @@ xfs_bmap_insert_extents( del_cursor); if (stop_fsb >= got.br_startoff + got.br_blockcount) { + ASSERT(0); error = -EFSCORRUPTED; goto del_cursor; } diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 4fd89c80c821..98843f1258b8 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -1820,6 +1820,7 @@ xfs_btree_lookup_get_block( out_bad: *blkp = NULL; + xfs_buf_corruption_error(bp); xfs_trans_brelse(cur->bc_tp, bp); return -EFSCORRUPTED; } @@ -1867,8 +1868,10 @@ xfs_btree_lookup( XFS_BTREE_STATS_INC(cur, lookup); /* No such thing as a zero-level tree. */ - if (cur->bc_nlevels == 0) + if (cur->bc_nlevels == 0) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp); return -EFSCORRUPTED; + } block = NULL; keyno = 0; diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c index 4fd1223c1bd5..1e2dc65adeb8 100644 --- a/fs/xfs/libxfs/xfs_da_btree.c +++ b/fs/xfs/libxfs/xfs_da_btree.c @@ -504,6 +504,7 @@ xfs_da3_split( node = oldblk->bp->b_addr; if (node->hdr.info.forw) { if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) { + xfs_buf_corruption_error(oldblk->bp); error = -EFSCORRUPTED; goto out; } @@ -516,6 +517,7 @@ xfs_da3_split( node = oldblk->bp->b_addr; if (node->hdr.info.back) { if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) { + xfs_buf_corruption_error(oldblk->bp); error = -EFSCORRUPTED; goto out; } @@ -1541,8 +1543,10 @@ xfs_da3_node_lookup_int( break; } - if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC) + if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC) { + xfs_buf_corruption_error(blk->bp); return -EFSCORRUPTED; + } blk->magic = XFS_DA_NODE_MAGIC; @@ -1554,15 +1558,18 @@ xfs_da3_node_lookup_int( btree = dp->d_ops->node_tree_p(node); /* Tree taller than we can handle; bail out! */ - if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) + if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) { + xfs_buf_corruption_error(blk->bp); return -EFSCORRUPTED; + } /* Check the level from the root. */ if (blkno == args->geo->leafblk) expected_level = nodehdr.level - 1; - else if (expected_level != nodehdr.level) + else if (expected_level != nodehdr.level) { + xfs_buf_corruption_error(blk->bp); return -EFSCORRUPTED; - else + } else expected_level--; max = nodehdr.count; @@ -1612,12 +1619,17 @@ xfs_da3_node_lookup_int( } /* We can't point back to the root. */ - if (blkno == args->geo->leafblk) + if (blkno == args->geo->leafblk) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, + dp->i_mount); return -EFSCORRUPTED; + } } - if (expected_level != 0) + if (expected_level != 0) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, dp->i_mount); return -EFSCORRUPTED; + } /* * A leaf block that ends in the hashval that we are interested in diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index 867c5dee0751..452d04ae10ce 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -600,8 +600,10 @@ xfs_dir2_isblock( if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) return rval; rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize; - if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize) + if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount); return -EFSCORRUPTED; + } *vp = rval; return 0; } diff --git a/fs/xfs/libxfs/xfs_dir2_leaf.c b/fs/xfs/libxfs/xfs_dir2_leaf.c index a53e4585a2f3..388b5da12228 100644 --- a/fs/xfs/libxfs/xfs_dir2_leaf.c +++ b/fs/xfs/libxfs/xfs_dir2_leaf.c @@ -1343,8 +1343,10 @@ xfs_dir2_leaf_removename( oldbest = be16_to_cpu(bf[0].length); ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); bestsp = xfs_dir2_leaf_bests_p(ltp); - if (be16_to_cpu(bestsp[db]) != oldbest) + if (be16_to_cpu(bestsp[db]) != oldbest) { + xfs_buf_corruption_error(lbp); return -EFSCORRUPTED; + } /* * Mark the former data entry unused. */ diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 705c4f562758..72d7ed17eef5 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -373,8 +373,10 @@ xfs_dir2_leaf_to_node( leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); if (be32_to_cpu(ltp->bestcount) > - (uint)dp->i_d.di_size / args->geo->blksize) + (uint)dp->i_d.di_size / args->geo->blksize) { + xfs_buf_corruption_error(lbp); return -EFSCORRUPTED; + } /* * Copy freespace entries from the leaf block to the new block. @@ -445,8 +447,10 @@ xfs_dir2_leafn_add( * Quick check just to make sure we are not going to index * into other peoples memory */ - if (index < 0) + if (index < 0) { + xfs_buf_corruption_error(bp); return -EFSCORRUPTED; + } /* * If there are already the maximum number of leaf entries in @@ -739,8 +743,10 @@ xfs_dir2_leafn_lookup_for_entry( ents = dp->d_ops->leaf_ents_p(leaf); xfs_dir3_leaf_check(dp, bp); - if (leafhdr.count <= 0) + if (leafhdr.count <= 0) { + xfs_buf_corruption_error(bp); return -EFSCORRUPTED; + } /* * Look up the hash value in the leaf entries. diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 8fdd0424070e..15d6f947620f 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -75,11 +75,15 @@ xfs_iformat_fork( error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK); break; default: + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, + dip, sizeof(*dip), __this_address); return -EFSCORRUPTED; } break; default: + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, + sizeof(*dip), __this_address); return -EFSCORRUPTED; } if (error) @@ -110,6 +114,8 @@ xfs_iformat_fork( error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK); break; default: + xfs_inode_verifier_error(ip, error, __func__, dip, + sizeof(*dip), __this_address); error = -EFSCORRUPTED; break; } diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 9a7fadb1361c..78236bd6c64f 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1591,8 +1591,10 @@ xfs_refcount_recover_extent( struct list_head *debris = priv; struct xfs_refcount_recovery *rr; - if (be32_to_cpu(rec->refc.rc_refcount) != 1) + if (be32_to_cpu(rec->refc.rc_refcount) != 1) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp); return -EFSCORRUPTED; + } rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), 0); xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec); diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 8ea1efc97b41..d8aaa1de921c 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -15,7 +15,7 @@ #include "xfs_bmap.h" #include "xfs_trans.h" #include "xfs_rtalloc.h" - +#include "xfs_error.h" /* * Realtime allocator bitmap functions shared with userspace. @@ -70,8 +70,10 @@ xfs_rtbuf_get( if (error) return error; - if (nmap == 0 || !xfs_bmap_is_real_extent(&map)) + if (nmap == 0 || !xfs_bmap_is_real_extent(&map)) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; + } ASSERT(map.br_startblock != NULLFSBLOCK); error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 96d7071cfa46..3f2292c7835c 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -12,6 +12,7 @@ #include "xfs_inode.h" #include "xfs_attr.h" #include "xfs_trace.h" +#include "xfs_error.h" #include @@ -23,6 +24,7 @@ STATIC struct posix_acl * xfs_acl_from_disk( + struct xfs_mount *mp, const struct xfs_acl *aclp, int len, int max_entries) @@ -32,11 +34,18 @@ xfs_acl_from_disk( const struct xfs_acl_entry *ace; unsigned int count, i; - if (len < sizeof(*aclp)) + if (len < sizeof(*aclp)) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp, + len); return ERR_PTR(-EFSCORRUPTED); + } + count = be32_to_cpu(aclp->acl_cnt); - if (count > max_entries || XFS_ACL_SIZE(count) != len) + if (count > max_entries || XFS_ACL_SIZE(count) != len) { + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp, + len); return ERR_PTR(-EFSCORRUPTED); + } acl = posix_acl_alloc(count, GFP_KERNEL); if (!acl) @@ -145,7 +154,7 @@ xfs_get_acl(struct inode *inode, int type) if (error != -ENOATTR) acl = ERR_PTR(error); } else { - acl = xfs_acl_from_disk(xfs_acl, len, + acl = xfs_acl_from_disk(ip->i_mount, xfs_acl, len, XFS_ACL_MAX_ENTRIES(ip->i_mount)); kmem_free(xfs_acl); } diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index f83f11d929e4..43ae392992e7 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -22,6 +22,7 @@ #include "xfs_attr_leaf.h" #include "xfs_quota.h" #include "xfs_dir2.h" +#include "xfs_error.h" /* * Look at all the extents for this logical region, @@ -209,6 +210,7 @@ xfs_attr3_node_inactive( */ if (level > XFS_DA_NODE_MAXDEPTH) { xfs_trans_brelse(*trans, bp); /* no locks for later trans */ + xfs_buf_corruption_error(bp); return -EFSCORRUPTED; } @@ -258,8 +260,9 @@ xfs_attr3_node_inactive( error = xfs_attr3_leaf_inactive(trans, dp, child_bp); break; default: - error = -EFSCORRUPTED; + xfs_buf_corruption_error(child_bp); xfs_trans_brelse(*trans, child_bp); + error = -EFSCORRUPTED; break; } if (error) @@ -342,6 +345,7 @@ xfs_attr3_root_inactive( break; default: error = -EFSCORRUPTED; + xfs_buf_corruption_error(bp); xfs_trans_brelse(*trans, bp); break; } diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index c02f22d50e45..64f6ceba9254 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -269,8 +269,10 @@ xfs_attr_node_list_lookup( return 0; /* We can't point back to the root. */ - if (cursor->blkno == 0) + if (cursor->blkno == 0) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; + } } if (expected_level != 0) @@ -280,6 +282,7 @@ xfs_attr_node_list_lookup( return 0; out_corruptbuf: + xfs_buf_corruption_error(bp); xfs_trans_brelse(tp, bp); return -EFSCORRUPTED; } diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c index 83d24e983d4c..26c87fd9ac9f 100644 --- a/fs/xfs/xfs_bmap_item.c +++ b/fs/xfs/xfs_bmap_item.c @@ -21,7 +21,7 @@ #include "xfs_icache.h" #include "xfs_bmap_btree.h" #include "xfs_trans_space.h" - +#include "xfs_error.h" kmem_zone_t *xfs_bui_zone; kmem_zone_t *xfs_bud_zone; @@ -525,6 +525,7 @@ xfs_bui_recover( type = bui_type; break; default: + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto err_inode; } diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 0b156cc88108..d8cdb27fe6ed 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -341,6 +341,27 @@ xfs_corruption_error( xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair"); } +/* + * Complain about the kinds of metadata corruption that we can't detect from a + * verifier, such as incorrect inter-block relationship data. Does not set + * bp->b_error. + */ +void +xfs_buf_corruption_error( + struct xfs_buf *bp) +{ + struct xfs_mount *mp = bp->b_mount; + + xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR, + "Metadata corruption detected at %pS, %s block 0x%llx", + __return_address, bp->b_ops->name, bp->b_bn); + + xfs_alert(mp, "Unmount and run xfs_repair"); + + if (xfs_error_level >= XFS_ERRLEVEL_HIGH) + xfs_stack_trace(); +} + /* * Warnings specifically for verifier errors. Differentiate CRC vs. invalid * values, and omit the stack trace unless the error level is tuned high. diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index e6a22cfb542f..c319379f7d1a 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -15,6 +15,7 @@ extern void xfs_corruption_error(const char *tag, int level, struct xfs_mount *mp, const void *buf, size_t bufsize, const char *filename, int linenum, xfs_failaddr_t failaddr); +void xfs_buf_corruption_error(struct xfs_buf *bp); extern void xfs_buf_verifier_error(struct xfs_buf *bp, int error, const char *name, const void *buf, size_t bufsz, xfs_failaddr_t failaddr); diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index e44efc41a041..a6f6acc8fbb7 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c @@ -21,7 +21,7 @@ #include "xfs_alloc.h" #include "xfs_bmap.h" #include "xfs_trace.h" - +#include "xfs_error.h" kmem_zone_t *xfs_efi_zone; kmem_zone_t *xfs_efd_zone; @@ -228,6 +228,7 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) } return 0; } + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); return -EFSCORRUPTED; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index e9e4f444f8ce..a92d4521748d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2136,8 +2136,10 @@ xfs_iunlink_update_bucket( * passed in because either we're adding or removing ourselves from the * head of the list. */ - if (old_value == new_agino) + if (old_value == new_agino) { + xfs_buf_corruption_error(agibp); return -EFSCORRUPTED; + } agi->agi_unlinked[bucket_index] = cpu_to_be32(new_agino); offset = offsetof(struct xfs_agi, agi_unlinked) + @@ -2200,6 +2202,8 @@ xfs_iunlink_update_inode( /* Make sure the old pointer isn't garbage. */ old_value = be32_to_cpu(dip->di_next_unlinked); if (!xfs_verify_agino_or_null(mp, agno, old_value)) { + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, + sizeof(*dip), __this_address); error = -EFSCORRUPTED; goto out; } @@ -2211,8 +2215,11 @@ xfs_iunlink_update_inode( */ *old_next_agino = old_value; if (old_value == next_agino) { - if (next_agino != NULLAGINO) + if (next_agino != NULLAGINO) { + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, + dip, sizeof(*dip), __this_address); error = -EFSCORRUPTED; + } goto out; } @@ -2263,8 +2270,10 @@ xfs_iunlink( */ next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); if (next_agino == agino || - !xfs_verify_agino_or_null(mp, agno, next_agino)) + !xfs_verify_agino_or_null(mp, agno, next_agino)) { + xfs_buf_corruption_error(agibp); return -EFSCORRUPTED; + } if (next_agino != NULLAGINO) { struct xfs_perag *pag; diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index bb8f076805b9..726aa3bfd6e8 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -17,6 +17,7 @@ #include "xfs_trans_priv.h" #include "xfs_buf_item.h" #include "xfs_log.h" +#include "xfs_error.h" #include @@ -828,8 +829,10 @@ xfs_inode_item_format_convert( { struct xfs_inode_log_format_32 *in_f32 = buf->i_addr; - if (buf->i_len != sizeof(*in_f32)) + if (buf->i_len != sizeof(*in_f32)) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); return -EFSCORRUPTED; + } in_f->ilf_type = in_f32->ilf_type; in_f->ilf_size = in_f32->ilf_size; diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 18e45e3a3f9f..4c7962ccb0c4 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -20,6 +20,7 @@ #include "xfs_symlink.h" #include "xfs_dir2.h" #include "xfs_iomap.h" +#include "xfs_error.h" #include #include @@ -470,17 +471,20 @@ xfs_vn_get_link_inline( struct inode *inode, struct delayed_call *done) { + struct xfs_inode *ip = XFS_I(inode); char *link; - ASSERT(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE); + ASSERT(ip->i_df.if_flags & XFS_IFINLINE); /* * The VFS crashes on a NULL pointer, so return -EFSCORRUPTED if * if_data is junk. */ - link = XFS_I(inode)->i_df.if_u1.if_data; - if (!link) + link = ip->i_df.if_u1.if_data; + if (!link) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, ip->i_mount); return ERR_PTR(-EFSCORRUPTED); + } return link; } diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index c1a514ffff55..648d5ecafd91 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3537,6 +3537,7 @@ xfs_cui_copy_format( memcpy(dst_cui_fmt, src_cui_fmt, len); return 0; } + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); return -EFSCORRUPTED; } @@ -3601,8 +3602,10 @@ xlog_recover_cud_pass2( struct xfs_ail *ailp = log->l_ailp; cud_formatp = item->ri_buf[0].i_addr; - if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format)) + if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format)) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp); return -EFSCORRUPTED; + } cui_id = cud_formatp->cud_cui_id; /* @@ -3654,6 +3657,7 @@ xfs_bui_copy_format( memcpy(dst_bui_fmt, src_bui_fmt, len); return 0; } + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); return -EFSCORRUPTED; } @@ -3677,8 +3681,10 @@ xlog_recover_bui_pass2( bui_formatp = item->ri_buf[0].i_addr; - if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) + if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp); return -EFSCORRUPTED; + } buip = xfs_bui_init(mp); error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format); if (error) { @@ -3720,8 +3726,10 @@ xlog_recover_bud_pass2( struct xfs_ail *ailp = log->l_ailp; bud_formatp = item->ri_buf[0].i_addr; - if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) + if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp); return -EFSCORRUPTED; + } bui_id = bud_formatp->bud_bui_id; /* @@ -5172,8 +5180,10 @@ xlog_recover_process( * If the filesystem is CRC enabled, this mismatch becomes a * fatal log corruption failure. */ - if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) + if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp); return -EFSCORRUPTED; + } } xlog_unpack_data(rhead, dp, log); @@ -5296,8 +5306,11 @@ xlog_do_recovery_pass( "invalid iclog size (%d bytes), using lsunit (%d bytes)", h_size, log->l_mp->m_logbsize); h_size = log->l_mp->m_logbsize; - } else + } else { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, + log->l_mp); return -EFSCORRUPTED; + } } if ((be32_to_cpu(rhead->h_version) & XLOG_VERSION_2) && diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index ecd8ce152ab1..66ea8e4fca86 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -22,6 +22,7 @@ #include "xfs_qm.h" #include "xfs_trace.h" #include "xfs_icache.h" +#include "xfs_error.h" /* * The global quota manager. There is only one of these for the entire @@ -754,11 +755,19 @@ xfs_qm_qino_alloc( if ((flags & XFS_QMOPT_PQUOTA) && (mp->m_sb.sb_gquotino != NULLFSINO)) { ino = mp->m_sb.sb_gquotino; - ASSERT(mp->m_sb.sb_pquotino == NULLFSINO); + if (mp->m_sb.sb_pquotino != NULLFSINO) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, + mp); + return -EFSCORRUPTED; + } } else if ((flags & XFS_QMOPT_GQUOTA) && (mp->m_sb.sb_pquotino != NULLFSINO)) { ino = mp->m_sb.sb_pquotino; - ASSERT(mp->m_sb.sb_gquotino == NULLFSINO); + if (mp->m_sb.sb_gquotino != NULLFSINO) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, + mp); + return -EFSCORRUPTED; + } } if (ino != NULLFSINO) { error = xfs_iget(mp, NULL, ino, 0, 0, ip); diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c index 2328268e6245..576f59fe370e 100644 --- a/fs/xfs/xfs_refcount_item.c +++ b/fs/xfs/xfs_refcount_item.c @@ -17,7 +17,7 @@ #include "xfs_refcount_item.h" #include "xfs_log.h" #include "xfs_refcount.h" - +#include "xfs_error.h" kmem_zone_t *xfs_cui_zone; kmem_zone_t *xfs_cud_zone; @@ -536,6 +536,7 @@ xfs_cui_recover( type = refc_type; break; default: + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto abort_error; } diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c index 8939e0ea09cd..1d72e4b3ebf1 100644 --- a/fs/xfs/xfs_rmap_item.c +++ b/fs/xfs/xfs_rmap_item.c @@ -17,7 +17,7 @@ #include "xfs_rmap_item.h" #include "xfs_log.h" #include "xfs_rmap.h" - +#include "xfs_error.h" kmem_zone_t *xfs_rui_zone; kmem_zone_t *xfs_rud_zone; @@ -171,8 +171,10 @@ xfs_rui_copy_format( src_rui_fmt = buf->i_addr; len = xfs_rui_log_format_sizeof(src_rui_fmt->rui_nextents); - if (buf->i_len != len) + if (buf->i_len != len) { + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); return -EFSCORRUPTED; + } memcpy(dst_rui_fmt, src_rui_fmt, len); return 0; @@ -581,6 +583,7 @@ xfs_rui_recover( type = XFS_RMAP_FREE; break; default: + XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL); error = -EFSCORRUPTED; goto abort_error; } -- cgit v1.2.3-70-g09d2 From cf085a1b5d221448c0c7425f3b9b9a9e2134e53e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 7 Nov 2019 13:24:52 -0800 Subject: xfs: Correct comment tyops -> typos Just fix the typos checkpatch notices... Signed-off-by: Joe Perches Reviewed-by: Bill O'Donnell Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/kmem.c | 2 +- fs/xfs/libxfs/xfs_alloc.c | 2 +- fs/xfs/libxfs/xfs_attr_leaf.c | 2 +- fs/xfs/libxfs/xfs_da_format.h | 2 +- fs/xfs/libxfs/xfs_fs.h | 2 +- fs/xfs/libxfs/xfs_log_format.h | 4 ++-- fs/xfs/xfs_buf.c | 2 +- fs/xfs/xfs_log_cil.c | 4 ++-- fs/xfs/xfs_symlink.h | 2 +- fs/xfs/xfs_trans_ail.c | 8 ++++---- 10 files changed, 15 insertions(+), 15 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c index da031b93e182..1da94237a8cf 100644 --- a/fs/xfs/kmem.c +++ b/fs/xfs/kmem.c @@ -32,7 +32,7 @@ kmem_alloc(size_t size, xfs_km_flags_t flags) /* - * __vmalloc() will allocate data pages and auxillary structures (e.g. + * __vmalloc() will allocate data pages and auxiliary structures (e.g. * pagetables) with GFP_KERNEL, yet we may be under GFP_NOFS context here. Hence * we need to tell memory reclaim that we are in such a context via * PF_MEMALLOC_NOFS to prevent memory reclaim re-entering the filesystem here diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index f7a4b54c5bc2..b39bd81d78bd 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1488,7 +1488,7 @@ xfs_alloc_ag_vextent_near( dofirst = prandom_u32() & 1; #endif - /* handle unitialized agbno range so caller doesn't have to */ + /* handle uninitialized agbno range so caller doesn't have to */ if (!args->min_agbno && !args->max_agbno) args->max_agbno = args->mp->m_sb.sb_agblocks - 1; ASSERT(args->min_agbno <= args->max_agbno); diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index dca8840496ea..8ba3ae89f07e 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -829,7 +829,7 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args) } /* - * Retreive the attribute value and length. + * Retrieve the attribute value and length. * * If ATTR_KERNOVAL is specified, only the length needs to be returned. * Unlike a lookup, we only return an error if the attribute does not diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index ae654e06b2fb..6702a0849f75 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -482,7 +482,7 @@ xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp) } /* - * Free space block defintions for the node format. + * Free space block definitions for the node format. */ /* diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 39dd2b908106..45f9e93ac570 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -416,7 +416,7 @@ struct xfs_bulkstat { /* * Project quota id helpers (previously projid was 16bit only - * and using two 16bit values to hold new 32bit projid was choosen + * and using two 16bit values to hold new 32bit projid was chosen * to retain compatibility with "old" filesystems). */ static inline uint32_t diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index e5f97c69b320..8ef31d71a9c7 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -432,9 +432,9 @@ static inline uint xfs_log_dinode_size(int version) } /* - * Buffer Log Format defintions + * Buffer Log Format definitions * - * These are the physical dirty bitmap defintions for the log format structure. + * These are the physical dirty bitmap definitions for the log format structure. */ #define XFS_BLF_CHUNK 128 #define XFS_BLF_SHIFT 7 diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 1e63dd3d1257..2ed3c65c602f 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -461,7 +461,7 @@ _xfs_buf_map_pages( unsigned nofs_flag; /* - * vm_map_ram() will allocate auxillary structures (e.g. + * vm_map_ram() will allocate auxiliary structures (e.g. * pagetables) with GFP_KERNEL, yet we are likely to be under * GFP_NOFS context here. Hence we need to tell memory reclaim * that we are in such a context via PF_MEMALLOC_NOFS to prevent diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index a1204424a938..48435cf2aa16 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -179,7 +179,7 @@ xlog_cil_alloc_shadow_bufs( /* * We free and allocate here as a realloc would copy - * unecessary data. We don't use kmem_zalloc() for the + * unnecessary data. We don't use kmem_zalloc() for the * same reason - we don't need to zero the data area in * the buffer, only the log vector header and the iovec * storage. @@ -682,7 +682,7 @@ xlog_cil_push( } - /* check for a previously pushed seqeunce */ + /* check for a previously pushed sequence */ if (push_seq < cil->xc_ctx->sequence) { spin_unlock(&cil->xc_push_lock); goto out_skip; diff --git a/fs/xfs/xfs_symlink.h b/fs/xfs/xfs_symlink.h index 9743d8c9394b..b1fa091427e6 100644 --- a/fs/xfs/xfs_symlink.h +++ b/fs/xfs/xfs_symlink.h @@ -5,7 +5,7 @@ #ifndef __XFS_SYMLINK_H #define __XFS_SYMLINK_H 1 -/* Kernel only symlink defintions */ +/* Kernel only symlink definitions */ int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, const char *target_path, umode_t mode, struct xfs_inode **ipp); diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index aea71ee189f5..00cc5b8734be 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -427,15 +427,15 @@ xfsaild_push( case XFS_ITEM_FLUSHING: /* - * The item or its backing buffer is already beeing + * The item or its backing buffer is already being * flushed. The typical reason for that is that an * inode buffer is locked because we already pushed the * updates to it as part of inode clustering. * * We do not want to to stop flushing just because lots - * of items are already beeing flushed, but we need to + * of items are already being flushed, but we need to * re-try the flushing relatively soon if most of the - * AIL is beeing flushed. + * AIL is being flushed. */ XFS_STATS_INC(mp, xs_push_ail_flushing); trace_xfs_ail_flushing(lip); @@ -612,7 +612,7 @@ xfsaild( * The push is run asynchronously in a workqueue, which means the caller needs * to handle waiting on the async flush for space to become available. * We don't want to interrupt any push that is in progress, hence we only queue - * work if we set the pushing bit approriately. + * work if we set the pushing bit appropriately. * * We do this unlocked - we only need to know whether there is anything in the * AIL at the time we are called. We don't need to access the contents of -- cgit v1.2.3-70-g09d2 From 5113f8ec3753ed4d68a5d54d3345fee33a914bfe Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 7 Nov 2019 12:29:00 -0800 Subject: xfs: clean up weird while loop in xfs_alloc_ag_vextent_near Refactor the weird while loop out of existence. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_alloc.c | 117 +++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 52 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index b39bd81d78bd..675613c7bacb 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1464,6 +1464,64 @@ xfs_alloc_ag_vextent_locality( return 0; } +/* Check the last block of the cnt btree for allocations. */ +static int +xfs_alloc_ag_vextent_lastblock( + struct xfs_alloc_arg *args, + struct xfs_alloc_cur *acur, + xfs_agblock_t *bno, + xfs_extlen_t *len, + bool *allocated) +{ + int error; + int i; + +#ifdef DEBUG + /* Randomly don't execute the first algorithm. */ + if (prandom_u32() & 1) + return 0; +#endif + + /* + * Start from the entry that lookup found, sequence through all larger + * free blocks. If we're actually pointing at a record smaller than + * maxlen, go to the start of this block, and skip all those smaller + * than minlen. + */ + if (len || args->alignment > 1) { + acur->cnt->bc_ptrs[0] = 1; + do { + error = xfs_alloc_get_rec(acur->cnt, bno, len, &i); + if (error) + return error; + XFS_WANT_CORRUPTED_RETURN(args->mp, i == 1); + if (*len >= args->minlen) + break; + error = xfs_btree_increment(acur->cnt, 0, &i); + if (error) + return error; + } while (i); + ASSERT(*len >= args->minlen); + if (!i) + return 0; + } + + error = xfs_alloc_walk_iter(args, acur, acur->cnt, true, false, -1, &i); + if (error) + return error; + + /* + * It didn't work. We COULD be in a case where there's a good record + * somewhere, so try again. + */ + if (acur->len == 0) + return 0; + + trace_xfs_alloc_near_first(args); + *allocated = true; + return 0; +} + /* * Allocate a variable extent near bno in the allocation group agno. * Extent's length (returned in len) will be between minlen and maxlen, @@ -1479,14 +1537,6 @@ xfs_alloc_ag_vextent_near( int i; /* result code, temporary */ xfs_agblock_t bno; xfs_extlen_t len; -#ifdef DEBUG - /* - * Randomly don't execute the first algorithm. - */ - int dofirst; /* set to do first algorithm */ - - dofirst = prandom_u32() & 1; -#endif /* handle uninitialized agbno range so caller doesn't have to */ if (!args->min_agbno && !args->max_agbno) @@ -1529,53 +1579,16 @@ restart: * near the right edge of the tree. If it's in the last btree leaf * block, then we just examine all the entries in that block * that are big enough, and pick the best one. - * This is written as a while loop so we can break out of it, - * but we never loop back to the top. */ - while (xfs_btree_islastblock(acur.cnt, 0)) { -#ifdef DEBUG - if (dofirst) - break; -#endif - /* - * Start from the entry that lookup found, sequence through - * all larger free blocks. If we're actually pointing at a - * record smaller than maxlen, go to the start of this block, - * and skip all those smaller than minlen. - */ - if (len || args->alignment > 1) { - acur.cnt->bc_ptrs[0] = 1; - do { - error = xfs_alloc_get_rec(acur.cnt, &bno, &len, - &i); - if (error) - goto out; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out); - if (len >= args->minlen) - break; - error = xfs_btree_increment(acur.cnt, 0, &i); - if (error) - goto out; - } while (i); - ASSERT(len >= args->minlen); - if (!i) - break; - } + if (xfs_btree_islastblock(acur.cnt, 0)) { + bool allocated = false; - error = xfs_alloc_walk_iter(args, &acur, acur.cnt, true, false, - -1, &i); + error = xfs_alloc_ag_vextent_lastblock(args, &acur, &bno, &len, + &allocated); if (error) goto out; - - /* - * It didn't work. We COULD be in a case where - * there's a good record somewhere, so try again. - */ - if (acur.len == 0) - break; - - trace_xfs_alloc_near_first(args); - goto alloc; + if (allocated) + goto alloc_finish; } /* @@ -1601,7 +1614,7 @@ restart: goto out; } -alloc: +alloc_finish: /* fix up btrees on a successful allocation */ error = xfs_alloc_cur_finish(args, &acur); -- cgit v1.2.3-70-g09d2 From f9e0370648b9f9908ec97f44459a1152aecbbf45 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 11 Nov 2019 12:52:18 -0800 Subject: xfs: kill the XFS_WANT_CORRUPT_* macros The XFS_WANT_CORRUPT_* macros conceal subtle side effects such as the creation of local variables and redirections of the code flow. This is pretty ugly, so replace them with explicit XFS_IS_CORRUPT tests that remove both of those ugly points. The change was performed with the following coccinelle script: @@ expression mp, test; identifier label; @@ - XFS_WANT_CORRUPTED_GOTO(mp, test, label); + if (XFS_IS_CORRUPT(mp, !test)) { error = -EFSCORRUPTED; goto label; } @@ expression mp, test; @@ - XFS_WANT_CORRUPTED_RETURN(mp, test); + if (XFS_IS_CORRUPT(mp, !test)) return -EFSCORRUPTED; @@ expression mp, lval, rval; @@ - XFS_IS_CORRUPT(mp, !(lval == rval)) + XFS_IS_CORRUPT(mp, lval != rval) @@ expression mp, e1, e2; @@ - XFS_IS_CORRUPT(mp, !(e1 && e2)) + XFS_IS_CORRUPT(mp, !e1 || !e2) @@ expression e1, e2; @@ - !(e1 == e2) + e1 != e2 @@ expression e1, e2, e3, e4, e5, e6; @@ - !(e1 == e2 && e3 == e4) || e5 != e6 + e1 != e2 || e3 != e4 || e5 != e6 @@ expression e1, e2, e3, e4, e5, e6; @@ - !(e1 == e2 || (e3 <= e4 && e5 <= e6)) + e1 != e2 && (e3 > e4 || e5 > e6) @@ expression mp, e1, e2; @@ - XFS_IS_CORRUPT(mp, !(e1 <= e2)) + XFS_IS_CORRUPT(mp, e1 > e2) @@ expression mp, e1, e2; @@ - XFS_IS_CORRUPT(mp, !(e1 < e2)) + XFS_IS_CORRUPT(mp, e1 >= e2) @@ expression mp, e1; @@ - XFS_IS_CORRUPT(mp, !!e1) + XFS_IS_CORRUPT(mp, e1) @@ expression mp, e1, e2; @@ - XFS_IS_CORRUPT(mp, !(e1 || e2)) + XFS_IS_CORRUPT(mp, !e1 && !e2) @@ expression mp, e1, e2, e3, e4; @@ - XFS_IS_CORRUPT(mp, !(e1 == e2) && !(e3 == e4)) + XFS_IS_CORRUPT(mp, e1 != e2 && e3 != e4) @@ expression mp, e1, e2, e3, e4; @@ - XFS_IS_CORRUPT(mp, !(e1 <= e2) || !(e3 >= e4)) + XFS_IS_CORRUPT(mp, e1 > e2 || e3 < e4) @@ expression mp, e1, e2, e3, e4; @@ - XFS_IS_CORRUPT(mp, !(e1 == e2) && !(e3 <= e4)) + XFS_IS_CORRUPT(mp, e1 != e2 && e3 > e4) Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_alloc.c | 240 ++++++++++++++++++++------- fs/xfs/libxfs/xfs_bmap.c | 299 ++++++++++++++++++++++++++-------- fs/xfs/libxfs/xfs_btree.c | 53 ++++-- fs/xfs/libxfs/xfs_ialloc.c | 117 ++++++++++---- fs/xfs/libxfs/xfs_refcount.c | 167 +++++++++++++------ fs/xfs/libxfs/xfs_rmap.c | 375 +++++++++++++++++++++++++++++++++---------- fs/xfs/xfs_discard.c | 5 +- fs/xfs/xfs_error.h | 26 --- fs/xfs/xfs_iwalk.c | 3 +- 9 files changed, 956 insertions(+), 329 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 675613c7bacb..fcee5e8f1a5b 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -451,13 +451,17 @@ xfs_alloc_fixup_trees( #ifdef DEBUG if ((error = xfs_alloc_get_rec(cnt_cur, &nfbno1, &nflen1, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, - i == 1 && nfbno1 == fbno && nflen1 == flen); + if (XFS_IS_CORRUPT(mp, + i != 1 || + nfbno1 != fbno || + nflen1 != flen)) + return -EFSCORRUPTED; #endif } else { if ((error = xfs_alloc_lookup_eq(cnt_cur, fbno, flen, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; } /* * Look up the record in the by-block tree if necessary. @@ -466,13 +470,17 @@ xfs_alloc_fixup_trees( #ifdef DEBUG if ((error = xfs_alloc_get_rec(bno_cur, &nfbno1, &nflen1, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, - i == 1 && nfbno1 == fbno && nflen1 == flen); + if (XFS_IS_CORRUPT(mp, + i != 1 || + nfbno1 != fbno || + nflen1 != flen)) + return -EFSCORRUPTED; #endif } else { if ((error = xfs_alloc_lookup_eq(bno_cur, fbno, flen, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; } #ifdef DEBUG @@ -483,8 +491,10 @@ xfs_alloc_fixup_trees( bnoblock = XFS_BUF_TO_BLOCK(bno_cur->bc_bufs[0]); cntblock = XFS_BUF_TO_BLOCK(cnt_cur->bc_bufs[0]); - XFS_WANT_CORRUPTED_RETURN(mp, - bnoblock->bb_numrecs == cntblock->bb_numrecs); + if (XFS_IS_CORRUPT(mp, + bnoblock->bb_numrecs != + cntblock->bb_numrecs)) + return -EFSCORRUPTED; } #endif @@ -514,25 +524,30 @@ xfs_alloc_fixup_trees( */ if ((error = xfs_btree_delete(cnt_cur, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; /* * Add new by-size btree entry(s). */ if (nfbno1 != NULLAGBLOCK) { if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno1, nflen1, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 0); + if (XFS_IS_CORRUPT(mp, i != 0)) + return -EFSCORRUPTED; if ((error = xfs_btree_insert(cnt_cur, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; } if (nfbno2 != NULLAGBLOCK) { if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno2, nflen2, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 0); + if (XFS_IS_CORRUPT(mp, i != 0)) + return -EFSCORRUPTED; if ((error = xfs_btree_insert(cnt_cur, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; } /* * Fix up the by-block btree entry(s). @@ -543,7 +558,8 @@ xfs_alloc_fixup_trees( */ if ((error = xfs_btree_delete(bno_cur, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; } else { /* * Update the by-block entry to start later|be shorter. @@ -557,10 +573,12 @@ xfs_alloc_fixup_trees( */ if ((error = xfs_alloc_lookup_eq(bno_cur, nfbno2, nflen2, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 0); + if (XFS_IS_CORRUPT(mp, i != 0)) + return -EFSCORRUPTED; if ((error = xfs_btree_insert(bno_cur, &i))) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; } return 0; } @@ -821,7 +839,8 @@ xfs_alloc_cur_check( error = xfs_alloc_get_rec(cur, &bno, &len, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(args->mp, i == 1); + if (XFS_IS_CORRUPT(args->mp, i != 1)) + return -EFSCORRUPTED; /* * Check minlen and deactivate a cntbt cursor if out of acceptable size @@ -1026,7 +1045,10 @@ xfs_alloc_ag_vextent_small( error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i); if (error) goto error; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error); + if (XFS_IS_CORRUPT(args->mp, i != 1)) { + error = -EFSCORRUPTED; + goto error; + } goto out; } @@ -1058,9 +1080,12 @@ xfs_alloc_ag_vextent_small( } *fbnop = args->agbno = fbno; *flenp = args->len = 1; - XFS_WANT_CORRUPTED_GOTO(args->mp, - fbno < be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), - error); + if (XFS_IS_CORRUPT(args->mp, + fbno >= be32_to_cpu( + XFS_BUF_TO_AGF(args->agbp)->agf_length))) { + error = -EFSCORRUPTED; + goto error; + } args->wasfromfl = 1; trace_xfs_alloc_small_freelist(args); @@ -1215,7 +1240,10 @@ xfs_alloc_ag_vextent_exact( error = xfs_alloc_get_rec(bno_cur, &fbno, &flen, &i); if (error) goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); + if (XFS_IS_CORRUPT(args->mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } ASSERT(fbno <= args->agbno); /* @@ -1494,7 +1522,8 @@ xfs_alloc_ag_vextent_lastblock( error = xfs_alloc_get_rec(acur->cnt, bno, len, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(args->mp, i == 1); + if (XFS_IS_CORRUPT(args->mp, i != 1)) + return -EFSCORRUPTED; if (*len >= args->minlen) break; error = xfs_btree_increment(acur->cnt, 0, &i); @@ -1688,7 +1717,10 @@ restart: error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i); if (error) goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); + if (XFS_IS_CORRUPT(args->mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } busy = xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen, &busy_gen); @@ -1722,8 +1754,13 @@ restart: * This can't happen in the second case above. */ rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); - XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 || - (rlen <= flen && rbno + rlen <= fbno + flen), error0); + if (XFS_IS_CORRUPT(args->mp, + rlen != 0 && + (rlen > flen || + rbno + rlen > fbno + flen))) { + error = -EFSCORRUPTED; + goto error0; + } if (rlen < args->maxlen) { xfs_agblock_t bestfbno; xfs_extlen_t bestflen; @@ -1742,15 +1779,22 @@ restart: if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); + if (XFS_IS_CORRUPT(args->mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } if (flen < bestrlen) break; busy = xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen, &busy_gen); rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); - XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 || - (rlen <= flen && rbno + rlen <= fbno + flen), - error0); + if (XFS_IS_CORRUPT(args->mp, + rlen != 0 && + (rlen > flen || + rbno + rlen > fbno + flen))) { + error = -EFSCORRUPTED; + goto error0; + } if (rlen > bestrlen) { bestrlen = rlen; bestrbno = rbno; @@ -1763,7 +1807,10 @@ restart: if ((error = xfs_alloc_lookup_eq(cnt_cur, bestfbno, bestflen, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); + if (XFS_IS_CORRUPT(args->mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } rlen = bestrlen; rbno = bestrbno; flen = bestflen; @@ -1786,7 +1833,10 @@ restart: xfs_alloc_fix_len(args); rlen = args->len; - XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0); + if (XFS_IS_CORRUPT(args->mp, rlen > flen)) { + error = -EFSCORRUPTED; + goto error0; + } /* * Allocate and initialize a cursor for the by-block tree. */ @@ -1800,10 +1850,13 @@ restart: cnt_cur = bno_cur = NULL; args->len = rlen; args->agbno = rbno; - XFS_WANT_CORRUPTED_GOTO(args->mp, - args->agbno + args->len <= - be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length), - error0); + if (XFS_IS_CORRUPT(args->mp, + args->agbno + args->len > + be32_to_cpu( + XFS_BUF_TO_AGF(args->agbp)->agf_length))) { + error = -EFSCORRUPTED; + goto error0; + } trace_xfs_alloc_size_done(args); return 0; @@ -1875,7 +1928,10 @@ xfs_free_ag_extent( */ if ((error = xfs_alloc_get_rec(bno_cur, <bno, <len, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* * It's not contiguous, though. */ @@ -1887,8 +1943,10 @@ xfs_free_ag_extent( * space was invalid, it's (partly) already free. * Very bad. */ - XFS_WANT_CORRUPTED_GOTO(mp, - ltbno + ltlen <= bno, error0); + if (XFS_IS_CORRUPT(mp, ltbno + ltlen > bno)) { + error = -EFSCORRUPTED; + goto error0; + } } } /* @@ -1903,7 +1961,10 @@ xfs_free_ag_extent( */ if ((error = xfs_alloc_get_rec(bno_cur, >bno, >len, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* * It's not contiguous, though. */ @@ -1915,7 +1976,10 @@ xfs_free_ag_extent( * space was invalid, it's (partly) already free. * Very bad. */ - XFS_WANT_CORRUPTED_GOTO(mp, gtbno >= bno + len, error0); + if (XFS_IS_CORRUPT(mp, bno + len > gtbno)) { + error = -EFSCORRUPTED; + goto error0; + } } } /* @@ -1932,31 +1996,49 @@ xfs_free_ag_extent( */ if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } if ((error = xfs_btree_delete(cnt_cur, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* * Delete the old by-size entry on the right. */ if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } if ((error = xfs_btree_delete(cnt_cur, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* * Delete the old by-block entry for the right block. */ if ((error = xfs_btree_delete(bno_cur, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* * Move the by-block cursor back to the left neighbor. */ if ((error = xfs_btree_decrement(bno_cur, 0, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } #ifdef DEBUG /* * Check that this is the right record: delete didn't @@ -1969,9 +2051,13 @@ xfs_free_ag_extent( if ((error = xfs_alloc_get_rec(bno_cur, &xxbno, &xxlen, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, - i == 1 && xxbno == ltbno && xxlen == ltlen, - error0); + if (XFS_IS_CORRUPT(mp, + i != 1 || + xxbno != ltbno || + xxlen != ltlen)) { + error = -EFSCORRUPTED; + goto error0; + } } #endif /* @@ -1992,17 +2078,26 @@ xfs_free_ag_extent( */ if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } if ((error = xfs_btree_delete(cnt_cur, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* * Back up the by-block cursor to the left neighbor, and * update its length. */ if ((error = xfs_btree_decrement(bno_cur, 0, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } nbno = ltbno; nlen = len + ltlen; if ((error = xfs_alloc_update(bno_cur, nbno, nlen))) @@ -2018,10 +2113,16 @@ xfs_free_ag_extent( */ if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } if ((error = xfs_btree_delete(cnt_cur, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* * Update the starting block and length of the right * neighbor in the by-block tree. @@ -2040,7 +2141,10 @@ xfs_free_ag_extent( nlen = len; if ((error = xfs_btree_insert(bno_cur, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } } xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); bno_cur = NULL; @@ -2049,10 +2153,16 @@ xfs_free_ag_extent( */ if ((error = xfs_alloc_lookup_eq(cnt_cur, nbno, nlen, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, error0); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto error0; + } if ((error = xfs_btree_insert(cnt_cur, &i))) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); cnt_cur = NULL; @@ -3177,12 +3287,18 @@ __xfs_free_extent( if (error) return error; - XFS_WANT_CORRUPTED_GOTO(mp, agbno < mp->m_sb.sb_agblocks, err); + if (XFS_IS_CORRUPT(mp, agbno >= mp->m_sb.sb_agblocks)) { + error = -EFSCORRUPTED; + goto err; + } /* validate the extent size is legal now we have the agf locked */ - XFS_WANT_CORRUPTED_GOTO(mp, - agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), - err); + if (XFS_IS_CORRUPT(mp, + agbno + len > + be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length))) { + error = -EFSCORRUPTED; + goto err; + } error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, type); if (error) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index b7cc2f9eae7b..97b6a1fd3246 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -384,8 +384,10 @@ xfs_bmap_check_leaf_extents( xfs_check_block(block, mp, 0, 0); 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), error0); + if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbno(mp, bno))) { + error = -EFSCORRUPTED; + goto error0; + } if (bp_release) { bp_release = 0; xfs_trans_brelse(NULL, bp); @@ -612,8 +614,8 @@ xfs_bmap_btree_to_extents( pp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, ifp->if_broot_bytes); cbno = be64_to_cpu(*pp); #ifdef DEBUG - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, - xfs_btree_check_lptr(cur, cbno, 1)); + if (XFS_IS_CORRUPT(cur->bc_mp, !xfs_btree_check_lptr(cur, cbno, 1))) + return -EFSCORRUPTED; #endif error = xfs_btree_read_bufl(mp, tp, cbno, &cbp, XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops); @@ -938,7 +940,10 @@ xfs_bmap_add_attrfork_btree( if (error) goto error0; /* must be at least one entry */ - XFS_WANT_CORRUPTED_GOTO(mp, stat == 1, error0); + if (XFS_IS_CORRUPT(mp, stat != 1)) { + error = -EFSCORRUPTED; + goto error0; + } if ((error = xfs_btree_new_iroot(cur, flags, &stat))) goto error0; if (stat == 0) { @@ -1619,15 +1624,24 @@ xfs_bmap_add_extent_delay_real( error = xfs_bmbt_lookup_eq(bma->cur, &RIGHT, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_delete(bma->cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_decrement(bma->cur, 0, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(bma->cur, &LEFT); if (error) goto done; @@ -1653,7 +1667,10 @@ xfs_bmap_add_extent_delay_real( error = xfs_bmbt_lookup_eq(bma->cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(bma->cur, &LEFT); if (error) goto done; @@ -1683,7 +1700,10 @@ xfs_bmap_add_extent_delay_real( error = xfs_bmbt_lookup_eq(bma->cur, &RIGHT, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(bma->cur, &PREV); if (error) goto done; @@ -1708,11 +1728,17 @@ xfs_bmap_add_extent_delay_real( error = xfs_bmbt_lookup_eq(bma->cur, new, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_insert(bma->cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } break; @@ -1743,7 +1769,10 @@ xfs_bmap_add_extent_delay_real( error = xfs_bmbt_lookup_eq(bma->cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(bma->cur, &LEFT); if (error) goto done; @@ -1764,11 +1793,17 @@ xfs_bmap_add_extent_delay_real( error = xfs_bmbt_lookup_eq(bma->cur, new, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_insert(bma->cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } if (xfs_bmap_needs_btree(bma->ip, whichfork)) { @@ -1809,7 +1844,10 @@ xfs_bmap_add_extent_delay_real( error = xfs_bmbt_lookup_eq(bma->cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(bma->cur, &RIGHT); if (error) goto done; @@ -1841,11 +1879,17 @@ xfs_bmap_add_extent_delay_real( error = xfs_bmbt_lookup_eq(bma->cur, new, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_insert(bma->cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } if (xfs_bmap_needs_btree(bma->ip, whichfork)) { @@ -1921,11 +1965,17 @@ xfs_bmap_add_extent_delay_real( error = xfs_bmbt_lookup_eq(bma->cur, new, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_insert(bma->cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } if (xfs_bmap_needs_btree(bma->ip, whichfork)) { @@ -2119,19 +2169,34 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, &RIGHT, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } if ((error = xfs_btree_delete(cur, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } if ((error = xfs_btree_decrement(cur, 0, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } if ((error = xfs_btree_delete(cur, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } if ((error = xfs_btree_decrement(cur, 0, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &LEFT); if (error) goto done; @@ -2157,13 +2222,22 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, &PREV, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } if ((error = xfs_btree_delete(cur, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } if ((error = xfs_btree_decrement(cur, 0, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &LEFT); if (error) goto done; @@ -2192,13 +2266,22 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, &RIGHT, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } if ((error = xfs_btree_delete(cur, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } if ((error = xfs_btree_decrement(cur, 0, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &PREV); if (error) goto done; @@ -2221,7 +2304,10 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, new, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &PREV); if (error) goto done; @@ -2251,7 +2337,10 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &PREV); if (error) goto done; @@ -2285,14 +2374,20 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &PREV); if (error) goto done; cur->bc_rec.b = *new; if ((error = xfs_btree_insert(cur, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } break; @@ -2319,7 +2414,10 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &PREV); if (error) goto done; @@ -2353,17 +2451,26 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &PREV); if (error) goto done; error = xfs_bmbt_lookup_eq(cur, new, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } if ((error = xfs_btree_insert(cur, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } break; @@ -2397,7 +2504,10 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } /* new right extent - oldext */ error = xfs_bmbt_update(cur, &r[1]); if (error) @@ -2406,7 +2516,10 @@ xfs_bmap_add_extent_unwritten_real( cur->bc_rec.b = PREV; if ((error = xfs_btree_insert(cur, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } /* * Reset the cursor to the position of the new extent * we are about to insert as we can't trust it after @@ -2415,11 +2528,17 @@ xfs_bmap_add_extent_unwritten_real( error = xfs_bmbt_lookup_eq(cur, new, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } /* new middle extent - newext */ if ((error = xfs_btree_insert(cur, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } break; @@ -2702,15 +2821,24 @@ xfs_bmap_add_extent_hole_real( error = xfs_bmbt_lookup_eq(cur, &right, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_delete(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &left); if (error) goto done; @@ -2736,7 +2864,10 @@ xfs_bmap_add_extent_hole_real( error = xfs_bmbt_lookup_eq(cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &left); if (error) goto done; @@ -2763,7 +2894,10 @@ xfs_bmap_add_extent_hole_real( error = xfs_bmbt_lookup_eq(cur, &old, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_bmbt_update(cur, &right); if (error) goto done; @@ -2786,11 +2920,17 @@ xfs_bmap_add_extent_hole_real( error = xfs_bmbt_lookup_eq(cur, new, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_insert(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } break; } @@ -4980,7 +5120,10 @@ xfs_bmap_del_extent_real( error = xfs_bmbt_lookup_eq(cur, &got, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } if (got.br_startoff == del->br_startoff) @@ -5004,7 +5147,10 @@ xfs_bmap_del_extent_real( } if ((error = xfs_btree_delete(cur, &i))) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } break; case BMAP_LEFT_FILLING: /* @@ -5075,7 +5221,10 @@ xfs_bmap_del_extent_real( error = xfs_bmbt_lookup_eq(cur, &got, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } /* * Update the btree record back * to the original value. @@ -5092,7 +5241,10 @@ xfs_bmap_del_extent_real( error = -ENOSPC; goto done; } - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } } else flags |= xfs_ilog_fext(whichfork); XFS_IFORK_NEXT_SET(ip, whichfork, @@ -5575,18 +5727,21 @@ xfs_bmse_merge( error = xfs_bmbt_lookup_eq(cur, got, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; error = xfs_btree_delete(cur, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; /* lookup and update size of the previous extent */ error = xfs_bmbt_lookup_eq(cur, left, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; error = xfs_bmbt_update(cur, &new); if (error) @@ -5634,7 +5789,8 @@ xfs_bmap_shift_update_extent( error = xfs_bmbt_lookup_eq(cur, &prev, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(mp, i == 1); + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; error = xfs_bmbt_update(cur, got); if (error) @@ -5697,8 +5853,10 @@ xfs_bmap_collapse_extents( *done = true; goto del_cursor; } - XFS_WANT_CORRUPTED_GOTO(mp, !isnullstartblock(got.br_startblock), - del_cursor); + if (XFS_IS_CORRUPT(mp, isnullstartblock(got.br_startblock))) { + error = -EFSCORRUPTED; + goto del_cursor; + } new_startoff = got.br_startoff - offset_shift_fsb; if (xfs_iext_peek_prev_extent(ifp, &icur, &prev)) { @@ -5823,8 +5981,10 @@ xfs_bmap_insert_extents( goto del_cursor; } } - XFS_WANT_CORRUPTED_GOTO(mp, !isnullstartblock(got.br_startblock), - del_cursor); + if (XFS_IS_CORRUPT(mp, isnullstartblock(got.br_startblock))) { + error = -EFSCORRUPTED; + goto del_cursor; + } if (stop_fsb >= got.br_startoff + got.br_blockcount) { ASSERT(0); @@ -5931,7 +6091,10 @@ xfs_bmap_split_extent_at( error = xfs_bmbt_lookup_eq(cur, &got, &i); if (error) goto del_cursor; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto del_cursor; + } } got.br_blockcount = gotblkcnt; @@ -5956,11 +6119,17 @@ xfs_bmap_split_extent_at( error = xfs_bmbt_lookup_eq(cur, &new, &i); if (error) goto del_cursor; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, del_cursor); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto del_cursor; + } error = xfs_btree_insert(cur, &i); if (error) goto del_cursor; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto del_cursor; + } } /* diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 1fd4850c0181..897dfb9e4682 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -1971,7 +1971,8 @@ xfs_btree_lookup( error = xfs_btree_increment(cur, 0, &i); if (error) goto error0; - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) + return -EFSCORRUPTED; *stat = 1; return 0; } @@ -2426,7 +2427,10 @@ xfs_btree_lshift( if (error) goto error0; i = xfs_btree_firstrec(tcur, level); - XFS_WANT_CORRUPTED_GOTO(tcur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(tcur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } error = xfs_btree_decrement(tcur, level, &i); if (error) @@ -2593,7 +2597,10 @@ xfs_btree_rshift( if (error) goto error0; i = xfs_btree_lastrec(tcur, level); - XFS_WANT_CORRUPTED_GOTO(tcur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(tcur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } error = xfs_btree_increment(tcur, level, &i); if (error) @@ -3447,7 +3454,10 @@ xfs_btree_insert( goto error0; } - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } level++; /* @@ -3851,15 +3861,24 @@ xfs_btree_delrec( * Actually any entry but the first would suffice. */ i = xfs_btree_lastrec(tcur, level); - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } error = xfs_btree_increment(tcur, level, &i); if (error) goto error0; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } i = xfs_btree_lastrec(tcur, level); - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* Grab a pointer to the block. */ right = xfs_btree_get_block(tcur, level, &rbp); @@ -3903,12 +3922,18 @@ xfs_btree_delrec( rrecs = xfs_btree_get_numrecs(right); if (!xfs_btree_ptr_is_null(cur, &lptr)) { i = xfs_btree_firstrec(tcur, level); - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } error = xfs_btree_decrement(tcur, level, &i); if (error) goto error0; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } } } @@ -3922,13 +3947,19 @@ xfs_btree_delrec( * previous block. */ i = xfs_btree_firstrec(tcur, level); - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } error = xfs_btree_decrement(tcur, level, &i); if (error) goto error0; i = xfs_btree_firstrec(tcur, level); - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* Grab a pointer to the block. */ left = xfs_btree_get_block(tcur, level, &lbp); diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 588d44613094..988cde7744e6 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -544,7 +544,10 @@ xfs_inobt_insert_sprec( nrec->ir_free, &i); if (error) goto error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error; + } goto out; } @@ -557,17 +560,23 @@ xfs_inobt_insert_sprec( error = xfs_inobt_get_rec(cur, &rec, &i); if (error) goto error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error); - XFS_WANT_CORRUPTED_GOTO(mp, - rec.ir_startino == nrec->ir_startino, - error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error; + } + if (XFS_IS_CORRUPT(mp, rec.ir_startino != nrec->ir_startino)) { + error = -EFSCORRUPTED; + goto error; + } /* * This should never fail. If we have coexisting records that * cannot merge, something is seriously wrong. */ - XFS_WANT_CORRUPTED_GOTO(mp, __xfs_inobt_can_merge(nrec, &rec), - error); + if (XFS_IS_CORRUPT(mp, !__xfs_inobt_can_merge(nrec, &rec))) { + error = -EFSCORRUPTED; + goto error; + } trace_xfs_irec_merge_pre(mp, agno, rec.ir_startino, rec.ir_holemask, nrec->ir_startino, @@ -1057,7 +1066,8 @@ xfs_ialloc_next_rec( error = xfs_inobt_get_rec(cur, rec, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) + return -EFSCORRUPTED; } return 0; @@ -1081,7 +1091,8 @@ xfs_ialloc_get_rec( error = xfs_inobt_get_rec(cur, rec, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) + return -EFSCORRUPTED; } return 0; @@ -1161,12 +1172,18 @@ xfs_dialloc_ag_inobt( error = xfs_inobt_lookup(cur, pagino, XFS_LOOKUP_LE, &i); if (error) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } error = xfs_inobt_get_rec(cur, &rec, &j); if (error) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, j == 1, error0); + if (XFS_IS_CORRUPT(mp, j != 1)) { + error = -EFSCORRUPTED; + goto error0; + } if (rec.ir_freecount > 0) { /* @@ -1321,19 +1338,28 @@ xfs_dialloc_ag_inobt( error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); if (error) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } for (;;) { error = xfs_inobt_get_rec(cur, &rec, &i); if (error) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } if (rec.ir_freecount > 0) break; error = xfs_btree_increment(cur, 0, &i); if (error) goto error0; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } } alloc_inode: @@ -1393,7 +1419,8 @@ xfs_dialloc_ag_finobt_near( error = xfs_inobt_get_rec(lcur, rec, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(lcur->bc_mp, i == 1); + if (XFS_IS_CORRUPT(lcur->bc_mp, i != 1)) + return -EFSCORRUPTED; /* * See if we've landed in the parent inode record. The finobt @@ -1416,10 +1443,16 @@ xfs_dialloc_ag_finobt_near( error = xfs_inobt_get_rec(rcur, &rrec, &j); if (error) goto error_rcur; - XFS_WANT_CORRUPTED_GOTO(lcur->bc_mp, j == 1, error_rcur); + if (XFS_IS_CORRUPT(lcur->bc_mp, j != 1)) { + error = -EFSCORRUPTED; + goto error_rcur; + } } - XFS_WANT_CORRUPTED_GOTO(lcur->bc_mp, i == 1 || j == 1, error_rcur); + if (XFS_IS_CORRUPT(lcur->bc_mp, i != 1 && j != 1)) { + error = -EFSCORRUPTED; + goto error_rcur; + } if (i == 1 && j == 1) { /* * Both the left and right records are valid. Choose the closer @@ -1472,7 +1505,8 @@ xfs_dialloc_ag_finobt_newino( error = xfs_inobt_get_rec(cur, rec, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) + return -EFSCORRUPTED; return 0; } } @@ -1483,12 +1517,14 @@ xfs_dialloc_ag_finobt_newino( error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) + return -EFSCORRUPTED; error = xfs_inobt_get_rec(cur, rec, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) + return -EFSCORRUPTED; return 0; } @@ -1510,20 +1546,24 @@ xfs_dialloc_ag_update_inobt( error = xfs_inobt_lookup(cur, frec->ir_startino, XFS_LOOKUP_EQ, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) + return -EFSCORRUPTED; error = xfs_inobt_get_rec(cur, &rec, &i); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) + return -EFSCORRUPTED; ASSERT((XFS_AGINO_TO_OFFSET(cur->bc_mp, rec.ir_startino) % XFS_INODES_PER_CHUNK) == 0); rec.ir_free &= ~XFS_INOBT_MASK(offset); rec.ir_freecount--; - XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, (rec.ir_free == frec->ir_free) && - (rec.ir_freecount == frec->ir_freecount)); + if (XFS_IS_CORRUPT(cur->bc_mp, + rec.ir_free != frec->ir_free || + rec.ir_freecount != frec->ir_freecount)) + return -EFSCORRUPTED; return xfs_inobt_update(cur, &rec); } @@ -1933,14 +1973,20 @@ xfs_difree_inobt( __func__, error); goto error0; } - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } error = xfs_inobt_get_rec(cur, &rec, &i); if (error) { xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.", __func__, error); goto error0; } - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error0; + } /* * Get the offset in the inode chunk. */ @@ -2052,7 +2098,10 @@ xfs_difree_finobt( * freed an inode in a previously fully allocated chunk. If not, * something is out of sync. */ - XFS_WANT_CORRUPTED_GOTO(mp, ibtrec->ir_freecount == 1, error); + if (XFS_IS_CORRUPT(mp, ibtrec->ir_freecount != 1)) { + error = -EFSCORRUPTED; + goto error; + } error = xfs_inobt_insert_rec(cur, ibtrec->ir_holemask, ibtrec->ir_count, @@ -2075,14 +2124,20 @@ xfs_difree_finobt( error = xfs_inobt_get_rec(cur, &rec, &i); if (error) goto error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto error; + } rec.ir_free |= XFS_INOBT_MASK(offset); rec.ir_freecount++; - XFS_WANT_CORRUPTED_GOTO(mp, (rec.ir_free == ibtrec->ir_free) && - (rec.ir_freecount == ibtrec->ir_freecount), - error); + if (XFS_IS_CORRUPT(mp, + rec.ir_free != ibtrec->ir_free || + rec.ir_freecount != ibtrec->ir_freecount)) { + error = -EFSCORRUPTED; + goto error; + } /* * The content of inobt records should always match between the inobt diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 78236bd6c64f..af7fc4f6f62b 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -200,7 +200,10 @@ xfs_refcount_insert( error = xfs_btree_insert(cur, i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, *i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } out_error: if (error) @@ -227,10 +230,16 @@ xfs_refcount_delete( error = xfs_refcount_get_rec(cur, &irec, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } trace_xfs_refcount_delete(cur->bc_mp, cur->bc_private.a.agno, &irec); error = xfs_btree_delete(cur, i); - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, *i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } if (error) goto out_error; error = xfs_refcount_lookup_ge(cur, irec.rc_startblock, &found_rec); @@ -349,7 +358,10 @@ xfs_refcount_split_extent( error = xfs_refcount_get_rec(cur, &rcext, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } if (rcext.rc_startblock == agbno || xfs_refc_next(&rcext) <= agbno) return 0; @@ -371,7 +383,10 @@ xfs_refcount_split_extent( error = xfs_refcount_insert(cur, &tmp, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } return error; out_error: @@ -410,19 +425,27 @@ xfs_refcount_merge_center_extents( &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } if (center->rc_refcount > 1) { error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, - out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } } /* Enlarge the left extent. */ @@ -430,7 +453,10 @@ xfs_refcount_merge_center_extents( &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } left->rc_blockcount = extlen; error = xfs_refcount_update(cur, left); @@ -469,14 +495,18 @@ xfs_refcount_merge_left_extent( &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, - out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, - out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } } /* Enlarge the left extent. */ @@ -484,7 +514,10 @@ xfs_refcount_merge_left_extent( &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } left->rc_blockcount += cleft->rc_blockcount; error = xfs_refcount_update(cur, left); @@ -526,14 +559,18 @@ xfs_refcount_merge_right_extent( &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, - out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, - out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } } /* Enlarge the right extent. */ @@ -541,7 +578,10 @@ xfs_refcount_merge_right_extent( &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } right->rc_startblock -= cright->rc_blockcount; right->rc_blockcount += cright->rc_blockcount; @@ -587,7 +627,10 @@ xfs_refcount_find_left_extents( error = xfs_refcount_get_rec(cur, &tmp, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } if (xfs_refc_next(&tmp) != agbno) return 0; @@ -605,8 +648,10 @@ xfs_refcount_find_left_extents( error = xfs_refcount_get_rec(cur, &tmp, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, - out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } /* if tmp starts at the end of our range, just use that */ if (tmp.rc_startblock == agbno) @@ -671,7 +716,10 @@ xfs_refcount_find_right_extents( error = xfs_refcount_get_rec(cur, &tmp, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } if (tmp.rc_startblock != agbno + aglen) return 0; @@ -689,8 +737,10 @@ xfs_refcount_find_right_extents( error = xfs_refcount_get_rec(cur, &tmp, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, - out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } /* if tmp ends at the end of our range, just use that */ if (xfs_refc_next(&tmp) == agbno + aglen) @@ -913,8 +963,11 @@ xfs_refcount_adjust_extents( &found_tmp); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, - found_tmp == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, + found_tmp != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } cur->bc_private.a.priv.refc.nr_ops++; } else { fsbno = XFS_AGB_TO_FSB(cur->bc_mp, @@ -955,8 +1008,10 @@ xfs_refcount_adjust_extents( error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, - found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } cur->bc_private.a.priv.refc.nr_ops++; goto advloop; } else { @@ -1272,7 +1327,10 @@ xfs_refcount_find_shared( error = xfs_refcount_get_rec(cur, &tmp, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } /* If the extent ends before the start, look at the next one */ if (tmp.rc_startblock + tmp.rc_blockcount <= agbno) { @@ -1284,7 +1342,10 @@ xfs_refcount_find_shared( error = xfs_refcount_get_rec(cur, &tmp, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } } /* If the extent starts after the range we want, bail out */ @@ -1312,7 +1373,10 @@ xfs_refcount_find_shared( error = xfs_refcount_get_rec(cur, &tmp, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } if (tmp.rc_startblock >= agbno + aglen || tmp.rc_startblock != *fbno + *flen) break; @@ -1413,8 +1477,11 @@ xfs_refcount_adjust_cow_extents( switch (adj) { case XFS_REFCOUNT_ADJUST_COW_ALLOC: /* Adding a CoW reservation, there should be nothing here. */ - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, - ext.rc_startblock >= agbno + aglen, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, + agbno + aglen > ext.rc_startblock)) { + error = -EFSCORRUPTED; + goto out_error; + } tmp.rc_startblock = agbno; tmp.rc_blockcount = aglen; @@ -1426,17 +1493,25 @@ xfs_refcount_adjust_cow_extents( &found_tmp); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, - found_tmp == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_tmp != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } break; case XFS_REFCOUNT_ADJUST_COW_FREE: /* Removing a CoW reservation, there should be one extent. */ - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, - ext.rc_startblock == agbno, out_error); - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, - ext.rc_blockcount == aglen, out_error); - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, - ext.rc_refcount == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_startblock != agbno)) { + error = -EFSCORRUPTED; + goto out_error; + } + if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_blockcount != aglen)) { + error = -EFSCORRUPTED; + goto out_error; + } + if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_refcount != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } ext.rc_refcount = 0; trace_xfs_refcount_modify_extent(cur->bc_mp, @@ -1444,8 +1519,10 @@ xfs_refcount_adjust_cow_extents( error = xfs_refcount_delete(cur, &found_rec); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, - found_rec == 1, out_error); + if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } break; default: ASSERT(0); diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 38e9414878b3..9488cbe5a80f 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -113,7 +113,10 @@ xfs_rmap_insert( error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done); + if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } rcur->bc_rec.r.rm_startblock = agbno; rcur->bc_rec.r.rm_blockcount = len; @@ -123,7 +126,10 @@ xfs_rmap_insert( error = xfs_btree_insert(rcur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); + if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } done: if (error) trace_xfs_rmap_insert_error(rcur->bc_mp, @@ -149,12 +155,18 @@ xfs_rmap_delete( error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); + if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_delete(rcur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); + if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } done: if (error) trace_xfs_rmap_delete_error(rcur->bc_mp, @@ -406,24 +418,39 @@ xfs_rmap_free_check_owner( return 0; /* Make sure the unwritten flag matches. */ - XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == - (rec->rm_flags & XFS_RMAP_UNWRITTEN), out); + if (XFS_IS_CORRUPT(mp, + (flags & XFS_RMAP_UNWRITTEN) != + (rec->rm_flags & XFS_RMAP_UNWRITTEN))) { + error = -EFSCORRUPTED; + goto out; + } /* Make sure the owner matches what we expect to find in the tree. */ - XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out); + if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) { + error = -EFSCORRUPTED; + goto out; + } /* Check the offset, if necessary. */ if (XFS_RMAP_NON_INODE_OWNER(owner)) goto out; if (flags & XFS_RMAP_BMBT_BLOCK) { - XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK, - out); + if (XFS_IS_CORRUPT(mp, + !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) { + error = -EFSCORRUPTED; + goto out; + } } else { - XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out); - XFS_WANT_CORRUPTED_GOTO(mp, - ltoff + rec->rm_blockcount >= offset + len, - out); + if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) { + error = -EFSCORRUPTED; + goto out; + } + if (XFS_IS_CORRUPT(mp, + offset + len > ltoff + rec->rm_blockcount)) { + error = -EFSCORRUPTED; + goto out; + } } out: @@ -482,12 +509,18 @@ xfs_rmap_unmap( error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } error = xfs_rmap_get_rec(cur, <rec, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, cur->bc_private.a.agno, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, @@ -502,8 +535,12 @@ xfs_rmap_unmap( * be the case that the "left" extent goes all the way to EOFS. */ if (owner == XFS_RMAP_OWN_NULL) { - XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock + - ltrec.rm_blockcount, out_error); + if (XFS_IS_CORRUPT(mp, + bno < + ltrec.rm_startblock + ltrec.rm_blockcount)) { + error = -EFSCORRUPTED; + goto out_error; + } goto out_done; } @@ -526,15 +563,22 @@ xfs_rmap_unmap( error = xfs_rmap_get_rec(cur, &rtrec, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } if (rtrec.rm_startblock >= bno + len) goto out_done; } /* Make sure the extent we found covers the entire freeing range. */ - XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && - ltrec.rm_startblock + ltrec.rm_blockcount >= - bno + len, out_error); + if (XFS_IS_CORRUPT(mp, + ltrec.rm_startblock > bno || + ltrec.rm_startblock + ltrec.rm_blockcount < + bno + len)) { + error = -EFSCORRUPTED; + goto out_error; + } /* Check owner information. */ error = xfs_rmap_free_check_owner(mp, ltoff, <rec, len, owner, @@ -551,7 +595,10 @@ xfs_rmap_unmap( error = xfs_btree_delete(cur, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } } else if (ltrec.rm_startblock == bno) { /* * overlap left hand side of extent: move the start, trim the @@ -743,7 +790,10 @@ xfs_rmap_map( error = xfs_rmap_get_rec(cur, <rec, &have_lt); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); + if (XFS_IS_CORRUPT(mp, have_lt != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, cur->bc_private.a.agno, ltrec.rm_startblock, ltrec.rm_blockcount, ltrec.rm_owner, @@ -753,9 +803,12 @@ xfs_rmap_map( have_lt = 0; } - XFS_WANT_CORRUPTED_GOTO(mp, - have_lt == 0 || - ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error); + if (XFS_IS_CORRUPT(mp, + have_lt != 0 && + ltrec.rm_startblock + ltrec.rm_blockcount > bno)) { + error = -EFSCORRUPTED; + goto out_error; + } /* * Increment the cursor to see if we have a right-adjacent record to our @@ -769,9 +822,14 @@ xfs_rmap_map( error = xfs_rmap_get_rec(cur, >rec, &have_gt); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); - XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock, - out_error); + if (XFS_IS_CORRUPT(mp, have_gt != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } + if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) { + error = -EFSCORRUPTED; + goto out_error; + } trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, gtrec.rm_startblock, gtrec.rm_blockcount, gtrec.rm_owner, @@ -821,7 +879,10 @@ xfs_rmap_map( error = xfs_btree_delete(cur, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } } /* point the cursor back to the left record and update */ @@ -865,7 +926,10 @@ xfs_rmap_map( error = xfs_btree_insert(cur, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } } trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, @@ -957,12 +1021,18 @@ xfs_rmap_convert( error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_rmap_get_rec(cur, &PREV, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, cur->bc_private.a.agno, PREV.rm_startblock, PREV.rm_blockcount, PREV.rm_owner, @@ -995,10 +1065,16 @@ xfs_rmap_convert( error = xfs_rmap_get_rec(cur, &LEFT, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); - XFS_WANT_CORRUPTED_GOTO(mp, - LEFT.rm_startblock + LEFT.rm_blockcount <= bno, - done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } + if (XFS_IS_CORRUPT(mp, + LEFT.rm_startblock + LEFT.rm_blockcount > + bno)) { + error = -EFSCORRUPTED; + goto done; + } trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, LEFT.rm_startblock, LEFT.rm_blockcount, LEFT.rm_owner, @@ -1017,7 +1093,10 @@ xfs_rmap_convert( error = xfs_btree_increment(cur, 0, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_increment(cur, 0, &i); if (error) goto done; @@ -1026,9 +1105,14 @@ xfs_rmap_convert( error = xfs_rmap_get_rec(cur, &RIGHT, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); - XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, - done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } + if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) { + error = -EFSCORRUPTED; + goto done; + } trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, @@ -1055,7 +1139,10 @@ xfs_rmap_convert( error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } /* * Switch out based on the FILLING and CONTIG state bits. @@ -1071,7 +1158,10 @@ xfs_rmap_convert( error = xfs_btree_increment(cur, 0, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, RIGHT.rm_offset, @@ -1079,11 +1169,17 @@ xfs_rmap_convert( error = xfs_btree_delete(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, PREV.rm_startblock, PREV.rm_blockcount, PREV.rm_owner, PREV.rm_offset, @@ -1091,11 +1187,17 @@ xfs_rmap_convert( error = xfs_btree_delete(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW = LEFT; NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; error = xfs_rmap_update(cur, &NEW); @@ -1115,11 +1217,17 @@ xfs_rmap_convert( error = xfs_btree_delete(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW = LEFT; NEW.rm_blockcount += PREV.rm_blockcount; error = xfs_rmap_update(cur, &NEW); @@ -1135,7 +1243,10 @@ xfs_rmap_convert( error = xfs_btree_increment(cur, 0, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } trace_xfs_rmap_delete(mp, cur->bc_private.a.agno, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, RIGHT.rm_offset, @@ -1143,11 +1254,17 @@ xfs_rmap_convert( error = xfs_btree_delete(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } error = xfs_btree_decrement(cur, 0, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW = PREV; NEW.rm_blockcount = len + RIGHT.rm_blockcount; NEW.rm_flags = newext; @@ -1214,7 +1331,10 @@ xfs_rmap_convert( error = xfs_btree_insert(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } break; case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: @@ -1253,7 +1373,10 @@ xfs_rmap_convert( oldext, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } NEW.rm_startblock = bno; NEW.rm_owner = owner; NEW.rm_offset = offset; @@ -1265,7 +1388,10 @@ xfs_rmap_convert( error = xfs_btree_insert(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } break; case 0: @@ -1295,7 +1421,10 @@ xfs_rmap_convert( error = xfs_btree_insert(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } /* * Reset the cursor to the position of the new extent * we are about to insert as we can't trust it after @@ -1305,7 +1434,10 @@ xfs_rmap_convert( oldext, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + if (XFS_IS_CORRUPT(mp, i != 0)) { + error = -EFSCORRUPTED; + goto done; + } /* new middle extent - newext */ cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN; cur->bc_rec.r.rm_flags |= newext; @@ -1314,7 +1446,10 @@ xfs_rmap_convert( error = xfs_btree_insert(cur, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } break; case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: @@ -1383,7 +1518,10 @@ xfs_rmap_convert_shared( &PREV, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } ASSERT(PREV.rm_offset <= offset); ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); @@ -1406,9 +1544,12 @@ xfs_rmap_convert_shared( goto done; if (i) { state |= RMAP_LEFT_VALID; - XFS_WANT_CORRUPTED_GOTO(mp, - LEFT.rm_startblock + LEFT.rm_blockcount <= bno, - done); + if (XFS_IS_CORRUPT(mp, + LEFT.rm_startblock + LEFT.rm_blockcount > + bno)) { + error = -EFSCORRUPTED; + goto done; + } if (xfs_rmap_is_mergeable(&LEFT, owner, newext)) state |= RMAP_LEFT_CONTIG; } @@ -1423,9 +1564,14 @@ xfs_rmap_convert_shared( error = xfs_rmap_get_rec(cur, &RIGHT, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); - XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, - done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } + if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) { + error = -EFSCORRUPTED; + goto done; + } trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, RIGHT.rm_startblock, RIGHT.rm_blockcount, RIGHT.rm_owner, @@ -1472,7 +1618,10 @@ xfs_rmap_convert_shared( NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; error = xfs_rmap_update(cur, &NEW); if (error) @@ -1495,7 +1644,10 @@ xfs_rmap_convert_shared( NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW.rm_blockcount += PREV.rm_blockcount; error = xfs_rmap_update(cur, &NEW); if (error) @@ -1518,7 +1670,10 @@ xfs_rmap_convert_shared( NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW.rm_blockcount += RIGHT.rm_blockcount; NEW.rm_flags = RIGHT.rm_flags; error = xfs_rmap_update(cur, &NEW); @@ -1538,7 +1693,10 @@ xfs_rmap_convert_shared( NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW.rm_flags = newext; error = xfs_rmap_update(cur, &NEW); if (error) @@ -1570,7 +1728,10 @@ xfs_rmap_convert_shared( NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW.rm_blockcount += len; error = xfs_rmap_update(cur, &NEW); if (error) @@ -1612,7 +1773,10 @@ xfs_rmap_convert_shared( NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW.rm_blockcount = offset - NEW.rm_offset; error = xfs_rmap_update(cur, &NEW); if (error) @@ -1644,7 +1808,10 @@ xfs_rmap_convert_shared( NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW.rm_blockcount -= len; error = xfs_rmap_update(cur, &NEW); if (error) @@ -1679,7 +1846,10 @@ xfs_rmap_convert_shared( NEW.rm_offset, NEW.rm_flags, &i); if (error) goto done; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto done; + } NEW.rm_blockcount = offset - NEW.rm_offset; error = xfs_rmap_update(cur, &NEW); if (error) @@ -1765,25 +1935,44 @@ xfs_rmap_unmap_shared( <rec, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } ltoff = ltrec.rm_offset; /* Make sure the extent we found covers the entire freeing range. */ - XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && - ltrec.rm_startblock + ltrec.rm_blockcount >= - bno + len, out_error); + if (XFS_IS_CORRUPT(mp, + ltrec.rm_startblock > bno || + ltrec.rm_startblock + ltrec.rm_blockcount < + bno + len)) { + error = -EFSCORRUPTED; + goto out_error; + } /* Make sure the owner matches what we expect to find in the tree. */ - XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error); + if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) { + error = -EFSCORRUPTED; + goto out_error; + } /* Make sure the unwritten flag matches. */ - XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == - (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); + if (XFS_IS_CORRUPT(mp, + (flags & XFS_RMAP_UNWRITTEN) != + (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) { + error = -EFSCORRUPTED; + goto out_error; + } /* Check the offset. */ - XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error); - XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount, - out_error); + if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) { + error = -EFSCORRUPTED; + goto out_error; + } + if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) { + error = -EFSCORRUPTED; + goto out_error; + } if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { /* Exact match, simply remove the record from rmap tree. */ @@ -1836,7 +2025,10 @@ xfs_rmap_unmap_shared( ltrec.rm_offset, ltrec.rm_flags, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } ltrec.rm_blockcount -= len; error = xfs_rmap_update(cur, <rec); if (error) @@ -1862,7 +2054,10 @@ xfs_rmap_unmap_shared( ltrec.rm_offset, ltrec.rm_flags, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } ltrec.rm_blockcount = bno - ltrec.rm_startblock; error = xfs_rmap_update(cur, <rec); if (error) @@ -1938,7 +2133,10 @@ xfs_rmap_map_shared( error = xfs_rmap_get_rec(cur, >rec, &have_gt); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); + if (XFS_IS_CORRUPT(mp, have_gt != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp, cur->bc_private.a.agno, gtrec.rm_startblock, gtrec.rm_blockcount, gtrec.rm_owner, @@ -1987,7 +2185,10 @@ xfs_rmap_map_shared( ltrec.rm_offset, ltrec.rm_flags, &i); if (error) goto out_error; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_error; + } error = xfs_rmap_update(cur, <rec); if (error) diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c index 50966a9912cd..cae613620175 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -71,7 +71,10 @@ xfs_trim_extents( error = xfs_alloc_get_rec(cur, &fbno, &flen, &i); if (error) goto out_del_cursor; - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_del_cursor); + if (XFS_IS_CORRUPT(mp, i != 1)) { + error = -EFSCORRUPTED; + goto out_del_cursor; + } ASSERT(flen <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest)); /* diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index c319379f7d1a..31a5d321ba9a 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -38,32 +38,6 @@ extern void xfs_inode_verifier_error(struct xfs_inode *ip, int error, /* Dump 128 bytes of any corrupt buffer */ #define XFS_CORRUPTION_DUMP_LEN (128) -/* - * Macros to set EFSCORRUPTED & return/branch. - */ -#define XFS_WANT_CORRUPTED_GOTO(mp, x, l) \ - { \ - int fs_is_ok = (x); \ - ASSERT(fs_is_ok); \ - if (unlikely(!fs_is_ok)) { \ - XFS_ERROR_REPORT("XFS_WANT_CORRUPTED_GOTO", \ - XFS_ERRLEVEL_LOW, mp); \ - error = -EFSCORRUPTED; \ - goto l; \ - } \ - } - -#define XFS_WANT_CORRUPTED_RETURN(mp, x) \ - { \ - int fs_is_ok = (x); \ - ASSERT(fs_is_ok); \ - if (unlikely(!fs_is_ok)) { \ - XFS_ERROR_REPORT("XFS_WANT_CORRUPTED_RETURN", \ - XFS_ERRLEVEL_LOW, mp); \ - return -EFSCORRUPTED; \ - } \ - } - #ifdef DEBUG extern int xfs_errortag_init(struct xfs_mount *mp); extern void xfs_errortag_del(struct xfs_mount *mp); diff --git a/fs/xfs/xfs_iwalk.c b/fs/xfs/xfs_iwalk.c index aa375cf53021..233dcc8784db 100644 --- a/fs/xfs/xfs_iwalk.c +++ b/fs/xfs/xfs_iwalk.c @@ -298,7 +298,8 @@ xfs_iwalk_ag_start( error = xfs_inobt_get_rec(*curpp, irec, has_more); if (error) return error; - XFS_WANT_CORRUPTED_RETURN(mp, *has_more == 1); + if (XFS_IS_CORRUPT(mp, *has_more != 1)) + return -EFSCORRUPTED; /* * If the LE lookup yielded an inobt record before the cursor position, -- cgit v1.2.3-70-g09d2 From a71895c5dad1ab8cf30622e208d148298ab602e5 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 11 Nov 2019 12:53:22 -0800 Subject: xfs: convert open coded corruption check to use XFS_IS_CORRUPT Convert the last of the open coded corruption check and report idioms to use the XFS_IS_CORRUPT macro. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_alloc.c | 7 ++--- fs/xfs/libxfs/xfs_bmap.c | 68 +++++++++++++++-------------------------- fs/xfs/libxfs/xfs_btree.c | 14 +++------ fs/xfs/libxfs/xfs_da_btree.c | 50 +++++++++--------------------- fs/xfs/libxfs/xfs_dir2.c | 10 +++--- fs/xfs/libxfs/xfs_dir2_node.c | 12 ++++---- fs/xfs/libxfs/xfs_refcount.c | 9 +++--- fs/xfs/libxfs/xfs_rmap.c | 2 +- fs/xfs/libxfs/xfs_rtbitmap.c | 4 +-- fs/xfs/xfs_attr_list.c | 23 ++++++-------- fs/xfs/xfs_dir2_readdir.c | 19 ++++++------ fs/xfs/xfs_iomap.c | 6 ++-- fs/xfs/xfs_iops.c | 4 +-- fs/xfs/xfs_log_recover.c | 71 ++++++++++++++++--------------------------- fs/xfs/xfs_mount.c | 7 ++--- fs/xfs/xfs_qm.c | 12 +++----- 16 files changed, 116 insertions(+), 202 deletions(-) (limited to 'fs/xfs/libxfs/xfs_alloc.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index fcee5e8f1a5b..c284e10af491 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1071,8 +1071,7 @@ xfs_alloc_ag_vextent_small( struct xfs_buf *bp; bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno); - if (!bp) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->mp); + if (XFS_IS_CORRUPT(args->mp, !bp)) { error = -EFSCORRUPTED; goto error; } @@ -2341,10 +2340,8 @@ xfs_free_agfl_block( return error; bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno); - if (!bp) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, tp->t_mountp); + if (XFS_IS_CORRUPT(tp->t_mountp, !bp)) return -EFSCORRUPTED; - } xfs_trans_binval(tp, bp); return 0; diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 97b6a1fd3246..4acc6e37c31d 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -731,8 +731,7 @@ xfs_bmap_extents_to_btree( ip->i_d.di_nblocks++; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L); abp = xfs_btree_get_bufl(mp, tp, args.fsbno); - if (!abp) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, !abp)) { error = -EFSCORRUPTED; goto out_unreserve_dquot; } @@ -1090,8 +1089,7 @@ xfs_bmap_add_attrfork( goto trans_cancel; if (XFS_IFORK_Q(ip)) goto trans_cancel; - if (ip->i_d.di_anextents != 0) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, ip->i_d.di_anextents != 0)) { error = -EFSCORRUPTED; goto trans_cancel; } @@ -1238,8 +1236,9 @@ xfs_iread_extents( 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); + if (XFS_IS_CORRUPT(mp, + XFS_IFORK_FORMAT(ip, whichfork) != + XFS_DINODE_FMT_BTREE)) { error = -EFSCORRUPTED; goto out; } @@ -1253,8 +1252,8 @@ xfs_iread_extents( if (error) goto out; - if (ir.loaded != XFS_IFORK_NEXTENTS(ip, whichfork)) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, + ir.loaded != XFS_IFORK_NEXTENTS(ip, whichfork))) { error = -EFSCORRUPTED; goto out; } @@ -1444,10 +1443,8 @@ xfs_bmap_last_offset( if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) return 0; - if (!xfs_ifork_has_extents(ip, whichfork)) { - ASSERT(0); + if (XFS_IS_CORRUPT(ip->i_mount, !xfs_ifork_has_extents(ip, whichfork))) return -EFSCORRUPTED; - } error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty); if (error || is_empty) @@ -3906,10 +3903,8 @@ xfs_bmapi_read( XFS_BMAPI_COWFORK))); ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)); - if (unlikely(XFS_TEST_ERROR( - !xfs_ifork_has_extents(ip, whichfork), - mp, XFS_ERRTAG_BMAPIFORMAT))) { - XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) { return -EFSCORRUPTED; } @@ -4417,10 +4412,8 @@ xfs_bmapi_write( ASSERT((flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)) != (XFS_BMAPI_PREALLOC | XFS_BMAPI_ZERO)); - if (unlikely(XFS_TEST_ERROR( - !xfs_ifork_has_extents(ip, whichfork), - mp, XFS_ERRTAG_BMAPIFORMAT))) { - XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) { return -EFSCORRUPTED; } @@ -4686,10 +4679,8 @@ xfs_bmapi_remap( ASSERT((flags & (XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC)) != (XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC)); - if (unlikely(XFS_TEST_ERROR( - !xfs_ifork_has_extents(ip, whichfork), - mp, XFS_ERRTAG_BMAPIFORMAT))) { - XFS_ERROR_REPORT("xfs_bmapi_remap", XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) { return -EFSCORRUPTED; } @@ -5311,7 +5302,7 @@ __xfs_bunmapi( int isrt; /* freeing in rt area */ int logflags; /* transaction logging flags */ xfs_extlen_t mod; /* rt extent offset */ - struct xfs_mount *mp; /* mount structure */ + struct xfs_mount *mp = ip->i_mount; int tmp_logflags; /* partial logging flags */ int wasdel; /* was a delayed alloc extent */ int whichfork; /* data or attribute fork */ @@ -5328,12 +5319,8 @@ __xfs_bunmapi( whichfork = xfs_bmapi_whichfork(flags); ASSERT(whichfork != XFS_COW_FORK); ifp = XFS_IFORK_PTR(ip, whichfork); - if (unlikely(!xfs_ifork_has_extents(ip, whichfork))) { - XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW, - ip->i_mount); + if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork))) return -EFSCORRUPTED; - } - mp = ip->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; @@ -5826,10 +5813,8 @@ xfs_bmap_collapse_extents( int error = 0; int logflags = 0; - if (unlikely(XFS_TEST_ERROR( - !xfs_ifork_has_extents(ip, whichfork), - mp, XFS_ERRTAG_BMAPIFORMAT))) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) { return -EFSCORRUPTED; } @@ -5945,10 +5930,8 @@ xfs_bmap_insert_extents( int error = 0; int logflags = 0; - if (unlikely(XFS_TEST_ERROR( - !xfs_ifork_has_extents(ip, whichfork), - mp, XFS_ERRTAG_BMAPIFORMAT))) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) { return -EFSCORRUPTED; } @@ -5986,8 +5969,8 @@ xfs_bmap_insert_extents( goto del_cursor; } - if (stop_fsb >= got.br_startoff + got.br_blockcount) { - ASSERT(0); + if (XFS_IS_CORRUPT(mp, + stop_fsb >= got.br_startoff + got.br_blockcount)) { error = -EFSCORRUPTED; goto del_cursor; } @@ -6053,11 +6036,8 @@ xfs_bmap_split_extent_at( int logflags = 0; int i = 0; - if (unlikely(XFS_TEST_ERROR( - !xfs_ifork_has_extents(ip, whichfork), - mp, XFS_ERRTAG_BMAPIFORMAT))) { - XFS_ERROR_REPORT("xfs_bmap_split_extent_at", - XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, whichfork)) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) { return -EFSCORRUPTED; } diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 897dfb9e4682..8f0e3a368f38 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -105,11 +105,10 @@ xfs_btree_check_lblock( xfs_failaddr_t fa; fa = __xfs_btree_check_lblock(cur, block, level, bp); - if (unlikely(XFS_TEST_ERROR(fa != NULL, mp, - XFS_ERRTAG_BTREE_CHECK_LBLOCK))) { + if (XFS_IS_CORRUPT(mp, fa != NULL) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK)) { if (bp) trace_xfs_btree_corrupt(bp, _RET_IP_); - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } return 0; @@ -169,11 +168,10 @@ xfs_btree_check_sblock( xfs_failaddr_t fa; fa = __xfs_btree_check_sblock(cur, block, level, bp); - if (unlikely(XFS_TEST_ERROR(fa != NULL, mp, - XFS_ERRTAG_BTREE_CHECK_SBLOCK))) { + if (XFS_IS_CORRUPT(mp, fa != NULL) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BTREE_CHECK_SBLOCK)) { if (bp) trace_xfs_btree_corrupt(bp, _RET_IP_); - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } return 0; @@ -1849,10 +1847,8 @@ xfs_btree_lookup( XFS_BTREE_STATS_INC(cur, lookup); /* No such thing as a zero-level tree. */ - if (cur->bc_nlevels == 0) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp); + if (XFS_IS_CORRUPT(cur->bc_mp, cur->bc_nlevels == 0)) return -EFSCORRUPTED; - } block = NULL; keyno = 0; diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c index 46b1c3fb305c..418189498234 100644 --- a/fs/xfs/libxfs/xfs_da_btree.c +++ b/fs/xfs/libxfs/xfs_da_btree.c @@ -1663,17 +1663,12 @@ xfs_da3_node_lookup_int( } /* We can't point back to the root. */ - if (blkno == args->geo->leafblk) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, - dp->i_mount); + if (XFS_IS_CORRUPT(dp->i_mount, blkno == args->geo->leafblk)) return -EFSCORRUPTED; - } } - if (expected_level != 0) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, dp->i_mount); + if (XFS_IS_CORRUPT(dp->i_mount, expected_level != 0)) return -EFSCORRUPTED; - } /* * A leaf block that ends in the hashval that we are interested in @@ -2267,11 +2262,8 @@ xfs_da3_swap_lastblock( error = xfs_bmap_last_before(tp, dp, &lastoff, w); if (error) return error; - if (unlikely(lastoff == 0)) { - XFS_ERROR_REPORT("xfs_da_swap_lastblock(1)", XFS_ERRLEVEL_LOW, - mp); + if (XFS_IS_CORRUPT(mp, lastoff == 0)) return -EFSCORRUPTED; - } /* * Read the last block in the btree space. */ @@ -2317,11 +2309,9 @@ xfs_da3_swap_lastblock( if (error) goto done; sib_info = sib_buf->b_addr; - if (unlikely( - be32_to_cpu(sib_info->forw) != last_blkno || - sib_info->magic != dead_info->magic)) { - XFS_ERROR_REPORT("xfs_da_swap_lastblock(2)", - XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, + be32_to_cpu(sib_info->forw) != last_blkno || + sib_info->magic != dead_info->magic)) { error = -EFSCORRUPTED; goto done; } @@ -2339,11 +2329,9 @@ xfs_da3_swap_lastblock( if (error) goto done; sib_info = sib_buf->b_addr; - if (unlikely( - be32_to_cpu(sib_info->back) != last_blkno || - sib_info->magic != dead_info->magic)) { - XFS_ERROR_REPORT("xfs_da_swap_lastblock(3)", - XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, + be32_to_cpu(sib_info->back) != last_blkno || + sib_info->magic != dead_info->magic)) { error = -EFSCORRUPTED; goto done; } @@ -2364,9 +2352,8 @@ xfs_da3_swap_lastblock( goto done; par_node = par_buf->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &par_hdr, par_node); - if (level >= 0 && level != par_hdr.level + 1) { - XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)", - XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, + level >= 0 && level != par_hdr.level + 1)) { error = -EFSCORRUPTED; goto done; } @@ -2377,9 +2364,7 @@ xfs_da3_swap_lastblock( be32_to_cpu(btree[entno].hashval) < dead_hash; entno++) continue; - if (entno == par_hdr.count) { - XFS_ERROR_REPORT("xfs_da_swap_lastblock(5)", - XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, entno == par_hdr.count)) { error = -EFSCORRUPTED; goto done; } @@ -2404,9 +2389,7 @@ xfs_da3_swap_lastblock( par_blkno = par_hdr.forw; xfs_trans_brelse(tp, par_buf); par_buf = NULL; - if (unlikely(par_blkno == 0)) { - XFS_ERROR_REPORT("xfs_da_swap_lastblock(6)", - XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, par_blkno == 0)) { error = -EFSCORRUPTED; goto done; } @@ -2415,9 +2398,7 @@ xfs_da3_swap_lastblock( goto done; par_node = par_buf->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &par_hdr, par_node); - if (par_hdr.level != level) { - XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)", - XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, par_hdr.level != level)) { error = -EFSCORRUPTED; goto done; } @@ -2611,7 +2592,7 @@ xfs_dabuf_map( if (!xfs_da_map_covers_blocks(nirecs, irecs, bno, nfsb)) { /* Caller ok with no mapping. */ - if (mappedbno == -2) { + if (!XFS_IS_CORRUPT(mp, mappedbno != -2)) { error = -1; goto out; } @@ -2632,7 +2613,6 @@ xfs_dabuf_map( irecs[i].br_state); } } - XFS_ERROR_REPORT("xfs_da_do_buf(1)", XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto out; } diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index 624c05e77ab4..83cc8770f0ca 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -208,10 +208,10 @@ xfs_dir_ino_validate( { bool ino_ok = xfs_verify_dir_ino(mp, ino); - if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE))) { + if (XFS_IS_CORRUPT(mp, !ino_ok) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) { xfs_warn(mp, "Invalid inode number 0x%Lx", (unsigned long long) ino); - XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } return 0; @@ -617,10 +617,10 @@ xfs_dir2_isblock( if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK))) return rval; rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize; - if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount); + if (XFS_IS_CORRUPT(args->dp->i_mount, + rval != 0 && + args->dp->i_d.di_size != args->geo->blksize)) return -EFSCORRUPTED; - } *vp = rval; return 0; } diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 5f30a1953a52..560b7e9d210d 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c @@ -728,10 +728,9 @@ xfs_dir2_leafn_lookup_for_addname( * If it has room, return it. */ xfs_dir2_free_hdr_from_disk(mp, &freehdr, free); - if (unlikely( - freehdr.bests[fi] == cpu_to_be16(NULLDATAOFF))) { - XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", - XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, + freehdr.bests[fi] == + cpu_to_be16(NULLDATAOFF))) { if (curfdb != newfdb) xfs_trans_brelse(tp, curbp); return -EFSCORRUPTED; @@ -1722,7 +1721,9 @@ xfs_dir2_node_add_datablk( if (error) return error; - if (xfs_dir2_db_to_fdb(args->geo, *dbno) != fbno) { + if (XFS_IS_CORRUPT(mp, + xfs_dir2_db_to_fdb(args->geo, *dbno) != + fbno)) { xfs_alert(mp, "%s: dir ino %llu needed freesp block %lld for data block %lld, got %lld", __func__, (unsigned long long)dp->i_ino, @@ -1736,7 +1737,6 @@ xfs_dir2_node_add_datablk( } else { xfs_alert(mp, " ... fblk is NULL"); } - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index af7fc4f6f62b..d7d702ee4d1a 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1177,7 +1177,7 @@ xfs_refcount_finish_one( XFS_ALLOC_FLAG_FREEING, &agbp); if (error) return error; - if (!agbp) + if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) return -EFSCORRUPTED; rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno); @@ -1661,17 +1661,16 @@ struct xfs_refcount_recovery { /* Stuff an extent on the recovery list. */ STATIC int xfs_refcount_recover_extent( - struct xfs_btree_cur *cur, + struct xfs_btree_cur *cur, union xfs_btree_rec *rec, void *priv) { struct list_head *debris = priv; struct xfs_refcount_recovery *rr; - if (be32_to_cpu(rec->refc.rc_refcount) != 1) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp); + if (XFS_IS_CORRUPT(cur->bc_mp, + be32_to_cpu(rec->refc.rc_refcount) != 1)) return -EFSCORRUPTED; - } rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), 0); xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec); diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 9488cbe5a80f..ff9412f113c4 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -2400,7 +2400,7 @@ xfs_rmap_finish_one( error = xfs_free_extent_fix_freelist(tp, agno, &agbp); if (error) return error; - if (!agbp) + if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) return -EFSCORRUPTED; rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index d8aaa1de921c..f42c74cb8be5 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -70,10 +70,8 @@ xfs_rtbuf_get( if (error) return error; - if (nmap == 0 || !xfs_bmap_is_real_extent(&map)) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_real_extent(&map))) return -EFSCORRUPTED; - } ASSERT(map.br_startblock != NULLFSBLOCK); error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c index 0ec6606149a2..7a099df88a0c 100644 --- a/fs/xfs/xfs_attr_list.c +++ b/fs/xfs/xfs_attr_list.c @@ -86,11 +86,10 @@ xfs_attr_shortform_list( (XFS_ISRESET_CURSOR(cursor) && (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) { for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { - if (!xfs_attr_namecheck(sfe->nameval, sfe->namelen)) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, - context->dp->i_mount); + if (XFS_IS_CORRUPT(context->dp->i_mount, + !xfs_attr_namecheck(sfe->nameval, + sfe->namelen))) return -EFSCORRUPTED; - } context->put_listent(context, sfe->flags, sfe->nameval, @@ -179,9 +178,9 @@ xfs_attr_shortform_list( cursor->hashval = sbp->hash; cursor->offset = 0; } - if (!xfs_attr_namecheck(sbp->name, sbp->namelen)) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, - context->dp->i_mount); + if (XFS_IS_CORRUPT(context->dp->i_mount, + !xfs_attr_namecheck(sbp->name, + sbp->namelen))) { error = -EFSCORRUPTED; goto out; } @@ -269,10 +268,8 @@ xfs_attr_node_list_lookup( return 0; /* We can't point back to the root. */ - if (cursor->blkno == 0) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, cursor->blkno == 0)) return -EFSCORRUPTED; - } } if (expected_level != 0) @@ -473,11 +470,9 @@ xfs_attr3_leaf_list_int( valuelen = be32_to_cpu(name_rmt->valuelen); } - if (!xfs_attr_namecheck(name, namelen)) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, - context->dp->i_mount); + if (XFS_IS_CORRUPT(context->dp->i_mount, + !xfs_attr_namecheck(name, namelen))) return -EFSCORRUPTED; - } context->put_listent(context, entry->flags, name, namelen, valuelen); if (context->seen_enough) diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index b149cb4a4d86..95bc9ef8f5f9 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -117,11 +117,10 @@ xfs_dir2_sf_getdents( ino = xfs_dir2_sf_get_ino(mp, sfp, sfep); filetype = xfs_dir2_sf_get_ftype(mp, sfep); ctx->pos = off & 0x7fffffff; - if (!xfs_dir2_namecheck(sfep->name, sfep->namelen)) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, - dp->i_mount); + if (XFS_IS_CORRUPT(dp->i_mount, + !xfs_dir2_namecheck(sfep->name, + sfep->namelen))) return -EFSCORRUPTED; - } if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino, xfs_dir3_get_dtype(mp, filetype))) return 0; @@ -207,9 +206,9 @@ xfs_dir2_block_getdents( /* * If it didn't fit, set the final offset to here & return. */ - if (!xfs_dir2_namecheck(dep->name, dep->namelen)) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, - dp->i_mount); + if (XFS_IS_CORRUPT(dp->i_mount, + !xfs_dir2_namecheck(dep->name, + dep->namelen))) { error = -EFSCORRUPTED; goto out_rele; } @@ -459,9 +458,9 @@ xfs_dir2_leaf_getdents( filetype = xfs_dir2_data_get_ftype(mp, dep); ctx->pos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff; - if (!xfs_dir2_namecheck(dep->name, dep->namelen)) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, - dp->i_mount); + if (XFS_IS_CORRUPT(dp->i_mount, + !xfs_dir2_namecheck(dep->name, + dep->namelen))) { error = -EFSCORRUPTED; break; } diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index d1960ff0a396..28e2d1f37267 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -856,10 +856,8 @@ xfs_buffered_write_iomap_begin( xfs_ilock(ip, XFS_ILOCK_EXCL); - if (unlikely(XFS_TEST_ERROR( - !xfs_ifork_has_extents(ip, XFS_DATA_FORK), - mp, XFS_ERRTAG_BMAPIFORMAT))) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp); + if (XFS_IS_CORRUPT(mp, !xfs_ifork_has_extents(ip, XFS_DATA_FORK)) || + XFS_TEST_ERROR(false, mp, XFS_ERRTAG_BMAPIFORMAT)) { error = -EFSCORRUPTED; goto out_unlock; } diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 57e6e44123a9..b129e077a5fa 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -481,10 +481,8 @@ xfs_vn_get_link_inline( * if_data is junk. */ link = ip->i_df.if_u1.if_data; - if (!link) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, ip->i_mount); + if (XFS_IS_CORRUPT(ip->i_mount, !link)) return ERR_PTR(-EFSCORRUPTED); - } return link; } diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 02f2147952b3..a008e3349483 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -103,10 +103,9 @@ xlog_alloc_buffer( * Pass log block 0 since we don't have an addr yet, buffer will be * verified on read. */ - if (!xlog_verify_bno(log, 0, nbblks)) { + if (XFS_IS_CORRUPT(log->l_mp, !xlog_verify_bno(log, 0, nbblks))) { xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer", nbblks); - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return NULL; } @@ -152,11 +151,10 @@ xlog_do_io( { int error; - if (!xlog_verify_bno(log, blk_no, nbblks)) { + if (XFS_IS_CORRUPT(log->l_mp, !xlog_verify_bno(log, blk_no, nbblks))) { xfs_warn(log->l_mp, "Invalid log block/length (0x%llx, 0x%x) for buffer", blk_no, nbblks); - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return -EFSCORRUPTED; } @@ -244,19 +242,17 @@ xlog_header_check_recover( * (XLOG_FMT_UNKNOWN). This stops us from trying to recover * a dirty log created in IRIX. */ - if (unlikely(head->h_fmt != cpu_to_be32(XLOG_FMT))) { + if (XFS_IS_CORRUPT(mp, head->h_fmt != cpu_to_be32(XLOG_FMT))) { xfs_warn(mp, "dirty log written in incompatible format - can't recover"); xlog_header_check_dump(mp, head); - XFS_ERROR_REPORT("xlog_header_check_recover(1)", - XFS_ERRLEVEL_HIGH, mp); return -EFSCORRUPTED; - } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { + } + if (XFS_IS_CORRUPT(mp, !uuid_equal(&mp->m_sb.sb_uuid, + &head->h_fs_uuid))) { xfs_warn(mp, "dirty log entry has mismatched uuid - can't recover"); xlog_header_check_dump(mp, head); - XFS_ERROR_REPORT("xlog_header_check_recover(2)", - XFS_ERRLEVEL_HIGH, mp); return -EFSCORRUPTED; } return 0; @@ -279,11 +275,10 @@ xlog_header_check_mount( * by IRIX and continue. */ xfs_warn(mp, "null uuid in log - IRIX style log"); - } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { + } else if (XFS_IS_CORRUPT(mp, !uuid_equal(&mp->m_sb.sb_uuid, + &head->h_fs_uuid))) { xfs_warn(mp, "log has mismatched uuid - can't recover"); xlog_header_check_dump(mp, head); - XFS_ERROR_REPORT("xlog_header_check_mount", - XFS_ERRLEVEL_HIGH, mp); return -EFSCORRUPTED; } return 0; @@ -1699,11 +1694,10 @@ xlog_clear_stale_blocks( * the distance from the beginning of the log to the * tail. */ - if (unlikely(head_block < tail_block || head_block >= log->l_logBBsize)) { - XFS_ERROR_REPORT("xlog_clear_stale_blocks(1)", - XFS_ERRLEVEL_LOW, log->l_mp); + if (XFS_IS_CORRUPT(log->l_mp, + head_block < tail_block || + head_block >= log->l_logBBsize)) return -EFSCORRUPTED; - } tail_distance = tail_block + (log->l_logBBsize - head_block); } else { /* @@ -1711,11 +1705,10 @@ xlog_clear_stale_blocks( * so the distance from the head to the tail is just * the tail block minus the head block. */ - if (unlikely(head_block >= tail_block || head_cycle != (tail_cycle + 1))){ - XFS_ERROR_REPORT("xlog_clear_stale_blocks(2)", - XFS_ERRLEVEL_LOW, log->l_mp); + if (XFS_IS_CORRUPT(log->l_mp, + head_block >= tail_block || + head_cycle != tail_cycle + 1)) return -EFSCORRUPTED; - } tail_distance = tail_block - head_block; } @@ -2135,13 +2128,11 @@ xlog_recover_do_inode_buffer( */ logged_nextp = item->ri_buf[item_index].i_addr + next_unlinked_offset - reg_buf_offset; - if (unlikely(*logged_nextp == 0)) { + if (XFS_IS_CORRUPT(mp, *logged_nextp == 0)) { xfs_alert(mp, "Bad inode buffer log record (ptr = "PTR_FMT", bp = "PTR_FMT"). " "Trying to replay bad (0) inode di_next_unlinked field.", item, bp); - XFS_ERROR_REPORT("xlog_recover_do_inode_buf", - XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; } @@ -2969,22 +2960,18 @@ xlog_recover_inode_pass2( * Make sure the place we're flushing out to really looks * like an inode! */ - if (unlikely(!xfs_verify_magic16(bp, dip->di_magic))) { + if (XFS_IS_CORRUPT(mp, !xfs_verify_magic16(bp, dip->di_magic))) { xfs_alert(mp, "%s: Bad inode magic number, dip = "PTR_FMT", dino bp = "PTR_FMT", ino = %Ld", __func__, dip, bp, in_f->ilf_ino); - XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)", - XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto out_release; } ldip = item->ri_buf[1].i_addr; - if (unlikely(ldip->di_magic != XFS_DINODE_MAGIC)) { + if (XFS_IS_CORRUPT(mp, ldip->di_magic != XFS_DINODE_MAGIC)) { xfs_alert(mp, "%s: Bad inode log record, rec ptr "PTR_FMT", ino %Ld", __func__, item, in_f->ilf_ino); - XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)", - XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto out_release; } @@ -5209,14 +5196,13 @@ xlog_valid_rec_header( { int hlen; - if (unlikely(rhead->h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM))) { - XFS_ERROR_REPORT("xlog_valid_rec_header(1)", - XFS_ERRLEVEL_LOW, log->l_mp); + if (XFS_IS_CORRUPT(log->l_mp, + rhead->h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM))) return -EFSCORRUPTED; - } - if (unlikely( - (!rhead->h_version || - (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) { + if (XFS_IS_CORRUPT(log->l_mp, + (!rhead->h_version || + (be32_to_cpu(rhead->h_version) & + (~XLOG_VERSION_OKBITS))))) { xfs_warn(log->l_mp, "%s: unrecognised log version (%d).", __func__, be32_to_cpu(rhead->h_version)); return -EFSCORRUPTED; @@ -5224,16 +5210,11 @@ xlog_valid_rec_header( /* LR body must have data or it wouldn't have been written */ hlen = be32_to_cpu(rhead->h_len); - if (unlikely( hlen <= 0 || hlen > INT_MAX )) { - XFS_ERROR_REPORT("xlog_valid_rec_header(2)", - XFS_ERRLEVEL_LOW, log->l_mp); + if (XFS_IS_CORRUPT(log->l_mp, hlen <= 0 || hlen > INT_MAX)) return -EFSCORRUPTED; - } - if (unlikely( blkno > log->l_logBBsize || blkno > INT_MAX )) { - XFS_ERROR_REPORT("xlog_valid_rec_header(3)", - XFS_ERRLEVEL_LOW, log->l_mp); + if (XFS_IS_CORRUPT(log->l_mp, + blkno > log->l_logBBsize || blkno > INT_MAX)) return -EFSCORRUPTED; - } return 0; } diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 5ea95247a37f..fca65109cf24 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -761,9 +761,8 @@ xfs_mountfs( goto out_free_dir; } - if (!sbp->sb_logblocks) { + if (XFS_IS_CORRUPT(mp, !sbp->sb_logblocks)) { xfs_warn(mp, "no log defined"); - XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp); error = -EFSCORRUPTED; goto out_free_perag; } @@ -801,12 +800,10 @@ xfs_mountfs( ASSERT(rip != NULL); - if (unlikely(!S_ISDIR(VFS_I(rip)->i_mode))) { + if (XFS_IS_CORRUPT(mp, !S_ISDIR(VFS_I(rip)->i_mode))) { xfs_warn(mp, "corrupted root inode %llu: not a directory", (unsigned long long)rip->i_ino); xfs_iunlock(rip, XFS_ILOCK_EXCL); - XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, - mp); error = -EFSCORRUPTED; goto out_rele_rip; } diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 66ea8e4fca86..7e264cbd15b9 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -755,19 +755,15 @@ xfs_qm_qino_alloc( if ((flags & XFS_QMOPT_PQUOTA) && (mp->m_sb.sb_gquotino != NULLFSINO)) { ino = mp->m_sb.sb_gquotino; - if (mp->m_sb.sb_pquotino != NULLFSINO) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, - mp); + if (XFS_IS_CORRUPT(mp, + mp->m_sb.sb_pquotino != NULLFSINO)) return -EFSCORRUPTED; - } } else if ((flags & XFS_QMOPT_GQUOTA) && (mp->m_sb.sb_pquotino != NULLFSINO)) { ino = mp->m_sb.sb_pquotino; - if (mp->m_sb.sb_gquotino != NULLFSINO) { - XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, - mp); + if (XFS_IS_CORRUPT(mp, + mp->m_sb.sb_gquotino != NULLFSINO)) return -EFSCORRUPTED; - } } if (ino != NULLFSINO) { error = xfs_iget(mp, NULL, ino, 0, 0, ip); -- cgit v1.2.3-70-g09d2