diff options
| author | Ingo Molnar <mingo@kernel.org> | 2024-03-25 13:32:29 +0300 | 
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2024-03-25 13:32:29 +0300 | 
| commit | f4566a1e73957800df75a3dd2dccee8a4697f327 (patch) | |
| tree | b043b875228c0b25988af66c680d60cae69d761d /fs/xfs/libxfs/xfs_alloc.c | |
| parent | b9e6e28663928cab836a19abbdec3d036a07db3b (diff) | |
| parent | 4cece764965020c22cff7665b18a012006359095 (diff) | |
| download | linux-f4566a1e73957800df75a3dd2dccee8a4697f327.tar.xz | |
Merge tag 'v6.9-rc1' into sched/core, to pick up fixes and to refresh the branch
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'fs/xfs/libxfs/xfs_alloc.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_alloc.c | 258 | 
1 files changed, 161 insertions, 97 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 3bd0a33fee0a..9da52e92172a 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -26,6 +26,7 @@  #include "xfs_ag.h"  #include "xfs_ag_resv.h"  #include "xfs_bmap.h" +#include "xfs_health.h"  struct kmem_cache	*xfs_extfree_item_cache; @@ -150,23 +151,38 @@ xfs_alloc_ag_max_usable(  	return mp->m_sb.sb_agblocks - blocks;  } + +static int +xfs_alloc_lookup( +	struct xfs_btree_cur	*cur, +	xfs_lookup_t		dir, +	xfs_agblock_t		bno, +	xfs_extlen_t		len, +	int			*stat) +{ +	int			error; + +	cur->bc_rec.a.ar_startblock = bno; +	cur->bc_rec.a.ar_blockcount = len; +	error = xfs_btree_lookup(cur, dir, stat); +	if (*stat == 1) +		cur->bc_flags |= XFS_BTREE_ALLOCBT_ACTIVE; +	else +		cur->bc_flags &= ~XFS_BTREE_ALLOCBT_ACTIVE; +	return error; +} +  /*   * Lookup the record equal to [bno, len] in the btree given by cur.   */ -STATIC int				/* error */ +static inline int				/* error */  xfs_alloc_lookup_eq(  	struct xfs_btree_cur	*cur,	/* btree cursor */  	xfs_agblock_t		bno,	/* starting block of extent */  	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; -	error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); -	cur->bc_ag.abt.active = (*stat == 1); -	return error; +	return xfs_alloc_lookup(cur, XFS_LOOKUP_EQ, bno, len, stat);  }  /* @@ -180,13 +196,7 @@ 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; -	error = xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); -	cur->bc_ag.abt.active = (*stat == 1); -	return error; +	return xfs_alloc_lookup(cur, XFS_LOOKUP_GE, bno, len, stat);  }  /* @@ -200,19 +210,14 @@ 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; -	error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); -	cur->bc_ag.abt.active = (*stat == 1); -	return error; +	return xfs_alloc_lookup(cur, XFS_LOOKUP_LE, bno, len, stat);  }  static inline bool  xfs_alloc_cur_active(  	struct xfs_btree_cur	*cur)  { -	return cur && cur->bc_ag.abt.active; +	return cur && (cur->bc_flags & XFS_BTREE_ALLOCBT_ACTIVE);  }  /* @@ -268,12 +273,12 @@ xfs_alloc_complain_bad_rec(  	struct xfs_mount		*mp = cur->bc_mp;  	xfs_warn(mp, -		"%s Freespace BTree record corruption in AG %d detected at %pS!", -		cur->bc_btnum == XFS_BTNUM_BNO ? "Block" : "Size", -		cur->bc_ag.pag->pag_agno, fa); +		"%sbt record corruption in AG %d detected at %pS!", +		cur->bc_ops->name, cur->bc_ag.pag->pag_agno, fa);  	xfs_warn(mp,  		"start block 0x%x block count 0x%x", irec->ar_startblock,  		irec->ar_blockcount); +	xfs_btree_mark_sick(cur);  	return -EFSCORRUPTED;  } @@ -497,14 +502,18 @@ xfs_alloc_fixup_trees(  		if (XFS_IS_CORRUPT(mp,  				   i != 1 ||  				   nfbno1 != fbno || -				   nflen1 != flen)) +				   nflen1 != flen)) { +			xfs_btree_mark_sick(cnt_cur);  			return -EFSCORRUPTED; +		}  #endif  	} else {  		if ((error = xfs_alloc_lookup_eq(cnt_cur, fbno, flen, &i)))  			return error; -		if (XFS_IS_CORRUPT(mp, i != 1)) +		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			return -EFSCORRUPTED; +		}  	}  	/*  	 * Look up the record in the by-block tree if necessary. @@ -516,14 +525,18 @@ xfs_alloc_fixup_trees(  		if (XFS_IS_CORRUPT(mp,  				   i != 1 ||  				   nfbno1 != fbno || -				   nflen1 != flen)) +				   nflen1 != flen)) { +			xfs_btree_mark_sick(bno_cur);  			return -EFSCORRUPTED; +		}  #endif  	} else {  		if ((error = xfs_alloc_lookup_eq(bno_cur, fbno, flen, &i)))  			return error; -		if (XFS_IS_CORRUPT(mp, i != 1)) +		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(bno_cur);  			return -EFSCORRUPTED; +		}  	}  #ifdef DEBUG @@ -536,8 +549,10 @@ xfs_alloc_fixup_trees(  		if (XFS_IS_CORRUPT(mp,  				   bnoblock->bb_numrecs != -				   cntblock->bb_numrecs)) +				   cntblock->bb_numrecs)) { +			xfs_btree_mark_sick(bno_cur);  			return -EFSCORRUPTED; +		}  	}  #endif @@ -567,30 +582,40 @@ xfs_alloc_fixup_trees(  	 */  	if ((error = xfs_btree_delete(cnt_cur, &i)))  		return error; -	if (XFS_IS_CORRUPT(mp, i != 1)) +	if (XFS_IS_CORRUPT(mp, i != 1)) { +		xfs_btree_mark_sick(cnt_cur);  		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; -		if (XFS_IS_CORRUPT(mp, i != 0)) +		if (XFS_IS_CORRUPT(mp, i != 0)) { +			xfs_btree_mark_sick(cnt_cur);  			return -EFSCORRUPTED; +		}  		if ((error = xfs_btree_insert(cnt_cur, &i)))  			return error; -		if (XFS_IS_CORRUPT(mp, i != 1)) +		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			return -EFSCORRUPTED; +		}  	}  	if (nfbno2 != NULLAGBLOCK) {  		if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno2, nflen2, &i)))  			return error; -		if (XFS_IS_CORRUPT(mp, i != 0)) +		if (XFS_IS_CORRUPT(mp, i != 0)) { +			xfs_btree_mark_sick(cnt_cur);  			return -EFSCORRUPTED; +		}  		if ((error = xfs_btree_insert(cnt_cur, &i)))  			return error; -		if (XFS_IS_CORRUPT(mp, i != 1)) +		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			return -EFSCORRUPTED; +		}  	}  	/*  	 * Fix up the by-block btree entry(s). @@ -601,8 +626,10 @@ xfs_alloc_fixup_trees(  		 */  		if ((error = xfs_btree_delete(bno_cur, &i)))  			return error; -		if (XFS_IS_CORRUPT(mp, i != 1)) +		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(bno_cur);  			return -EFSCORRUPTED; +		}  	} else {  		/*  		 * Update the by-block entry to start later|be shorter. @@ -616,12 +643,16 @@ xfs_alloc_fixup_trees(  		 */  		if ((error = xfs_alloc_lookup_eq(bno_cur, nfbno2, nflen2, &i)))  			return error; -		if (XFS_IS_CORRUPT(mp, i != 0)) +		if (XFS_IS_CORRUPT(mp, i != 0)) { +			xfs_btree_mark_sick(bno_cur);  			return -EFSCORRUPTED; +		}  		if ((error = xfs_btree_insert(bno_cur, &i)))  			return error; -		if (XFS_IS_CORRUPT(mp, i != 1)) +		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(bno_cur);  			return -EFSCORRUPTED; +		}  	}  	return 0;  } @@ -755,6 +786,8 @@ xfs_alloc_read_agfl(  			mp, tp, mp->m_ddev_targp,  			XFS_AG_DADDR(mp, pag->pag_agno, XFS_AGFL_DADDR(mp)),  			XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops); +	if (xfs_metadata_is_sick(error)) +		xfs_ag_mark_sick(pag, XFS_SICK_AG_AGFL);  	if (error)  		return error;  	xfs_buf_set_ref(bp, XFS_AGFL_REF); @@ -776,6 +809,7 @@ xfs_alloc_update_counters(  	if (unlikely(be32_to_cpu(agf->agf_freeblks) >  		     be32_to_cpu(agf->agf_length))) {  		xfs_buf_mark_corrupt(agbp); +		xfs_ag_mark_sick(agbp->b_pag, XFS_SICK_AG_AGF);  		return -EFSCORRUPTED;  	} @@ -828,8 +862,8 @@ xfs_alloc_cur_setup(  	 * attempt a small allocation.  	 */  	if (!acur->cnt) -		acur->cnt = xfs_allocbt_init_cursor(args->mp, args->tp, -					args->agbp, args->pag, XFS_BTNUM_CNT); +		acur->cnt = xfs_cntbt_init_cursor(args->mp, args->tp, +					args->agbp, args->pag);  	error = xfs_alloc_lookup_ge(acur->cnt, 0, args->maxlen, &i);  	if (error)  		return error; @@ -838,11 +872,11 @@ xfs_alloc_cur_setup(  	 * Allocate the bnobt left and right search cursors.  	 */  	if (!acur->bnolt) -		acur->bnolt = xfs_allocbt_init_cursor(args->mp, args->tp, -					args->agbp, args->pag, XFS_BTNUM_BNO); +		acur->bnolt = xfs_bnobt_init_cursor(args->mp, args->tp, +					args->agbp, args->pag);  	if (!acur->bnogt) -		acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp, -					args->agbp, args->pag, XFS_BTNUM_BNO); +		acur->bnogt = xfs_bnobt_init_cursor(args->mp, args->tp, +					args->agbp, args->pag);  	return i == 1 ? 0 : -ENOSPC;  } @@ -884,15 +918,17 @@ xfs_alloc_cur_check(  	bool			busy;  	unsigned		busy_gen = 0;  	bool			deactivate = false; -	bool			isbnobt = cur->bc_btnum == XFS_BTNUM_BNO; +	bool			isbnobt = xfs_btree_is_bno(cur->bc_ops);  	*new = 0;  	error = xfs_alloc_get_rec(cur, &bno, &len, &i);  	if (error)  		return error; -	if (XFS_IS_CORRUPT(args->mp, i != 1)) +	if (XFS_IS_CORRUPT(args->mp, i != 1)) { +		xfs_btree_mark_sick(cur);  		return -EFSCORRUPTED; +	}  	/*  	 * Check minlen and deactivate a cntbt cursor if out of acceptable size @@ -958,9 +994,8 @@ xfs_alloc_cur_check(  		deactivate = true;  out:  	if (deactivate) -		cur->bc_ag.abt.active = false; -	trace_xfs_alloc_cur_check(args->mp, cur->bc_btnum, bno, len, diff, -				  *new); +		cur->bc_flags &= ~XFS_BTREE_ALLOCBT_ACTIVE; +	trace_xfs_alloc_cur_check(cur, bno, len, diff, *new);  	return 0;  } @@ -1098,6 +1133,7 @@ xfs_alloc_ag_vextent_small(  		if (error)  			goto error;  		if (XFS_IS_CORRUPT(args->mp, i != 1)) { +			xfs_btree_mark_sick(ccur);  			error = -EFSCORRUPTED;  			goto error;  		} @@ -1132,6 +1168,7 @@ xfs_alloc_ag_vextent_small(  	*fbnop = args->agbno = fbno;  	*flenp = args->len = 1;  	if (XFS_IS_CORRUPT(args->mp, fbno >= be32_to_cpu(agf->agf_length))) { +		xfs_btree_mark_sick(ccur);  		error = -EFSCORRUPTED;  		goto error;  	} @@ -1197,8 +1234,8 @@ xfs_alloc_ag_vextent_exact(  	/*  	 * Allocate/initialize a cursor for the by-number freespace btree.  	 */ -	bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, -					  args->pag, XFS_BTNUM_BNO); +	bno_cur = xfs_bnobt_init_cursor(args->mp, args->tp, args->agbp, +					  args->pag);  	/*  	 * Lookup bno and minlen in the btree (minlen is irrelevant, really). @@ -1218,6 +1255,7 @@ xfs_alloc_ag_vextent_exact(  	if (error)  		goto error0;  	if (XFS_IS_CORRUPT(args->mp, i != 1)) { +		xfs_btree_mark_sick(bno_cur);  		error = -EFSCORRUPTED;  		goto error0;  	} @@ -1257,8 +1295,8 @@ xfs_alloc_ag_vextent_exact(  	 * We are allocating agbno for args->len  	 * Allocate/initialize a cursor for the by-size btree.  	 */ -	cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, -					args->pag, XFS_BTNUM_CNT); +	cnt_cur = xfs_cntbt_init_cursor(args->mp, args->tp, args->agbp, +					args->pag);  	ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length));  	error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno,  				      args->len, XFSA_FIXUP_BNO_OK); @@ -1330,7 +1368,7 @@ xfs_alloc_walk_iter(  		if (error)  			return error;  		if (i == 0) -			cur->bc_ag.abt.active = false; +			cur->bc_flags &= ~XFS_BTREE_ALLOCBT_ACTIVE;  		if (count > 0)  			count--; @@ -1444,7 +1482,7 @@ xfs_alloc_ag_vextent_locality(  		if (error)  			return error;  		if (i) { -			acur->cnt->bc_ag.abt.active = true; +			acur->cnt->bc_flags |= XFS_BTREE_ALLOCBT_ACTIVE;  			fbcur = acur->cnt;  			fbinc = false;  		} @@ -1497,8 +1535,10 @@ xfs_alloc_ag_vextent_lastblock(  			error = xfs_alloc_get_rec(acur->cnt, bno, len, &i);  			if (error)  				return error; -			if (XFS_IS_CORRUPT(args->mp, i != 1)) +			if (XFS_IS_CORRUPT(args->mp, i != 1)) { +				xfs_btree_mark_sick(acur->cnt);  				return -EFSCORRUPTED; +			}  			if (*len >= args->minlen)  				break;  			error = xfs_btree_increment(acur->cnt, 0, &i); @@ -1670,8 +1710,8 @@ restart:  	/*  	 * Allocate and initialize a cursor for the by-size btree.  	 */ -	cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, -					args->pag, XFS_BTNUM_CNT); +	cnt_cur = xfs_cntbt_init_cursor(args->mp, args->tp, args->agbp, +					args->pag);  	bno_cur = NULL;  	/* @@ -1710,6 +1750,7 @@ restart:  			if (error)  				goto error0;  			if (XFS_IS_CORRUPT(args->mp, i != 1)) { +				xfs_btree_mark_sick(cnt_cur);  				error = -EFSCORRUPTED;  				goto error0;  			} @@ -1756,6 +1797,7 @@ restart:  			   rlen != 0 &&  			   (rlen > flen ||  			    rbno + rlen > fbno + flen))) { +		xfs_btree_mark_sick(cnt_cur);  		error = -EFSCORRUPTED;  		goto error0;  	} @@ -1778,6 +1820,7 @@ restart:  					&i)))  				goto error0;  			if (XFS_IS_CORRUPT(args->mp, i != 1)) { +				xfs_btree_mark_sick(cnt_cur);  				error = -EFSCORRUPTED;  				goto error0;  			} @@ -1790,6 +1833,7 @@ restart:  					   rlen != 0 &&  					   (rlen > flen ||  					    rbno + rlen > fbno + flen))) { +				xfs_btree_mark_sick(cnt_cur);  				error = -EFSCORRUPTED;  				goto error0;  			} @@ -1806,6 +1850,7 @@ restart:  				&i)))  			goto error0;  		if (XFS_IS_CORRUPT(args->mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -1844,14 +1889,15 @@ restart:  	rlen = args->len;  	if (XFS_IS_CORRUPT(args->mp, rlen > flen)) { +		xfs_btree_mark_sick(cnt_cur);  		error = -EFSCORRUPTED;  		goto error0;  	}  	/*  	 * Allocate and initialize a cursor for the by-block tree.  	 */ -	bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, -					args->pag, XFS_BTNUM_BNO); +	bno_cur = xfs_bnobt_init_cursor(args->mp, args->tp, args->agbp, +					args->pag);  	if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,  			rbno, rlen, XFSA_FIXUP_CNT_OK)))  		goto error0; @@ -1863,6 +1909,7 @@ restart:  	if (XFS_IS_CORRUPT(args->mp,  			   args->agbno + args->len >  			   be32_to_cpu(agf->agf_length))) { +		xfs_ag_mark_sick(args->pag, XFS_SICK_AG_BNOBT);  		error = -EFSCORRUPTED;  		goto error0;  	} @@ -1924,7 +1971,7 @@ xfs_free_ag_extent(  	/*  	 * Allocate and initialize a cursor for the by-block btree.  	 */ -	bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_BNO); +	bno_cur = xfs_bnobt_init_cursor(mp, tp, agbp, pag);  	/*  	 * Look for a neighboring block on the left (lower block numbers)  	 * that is contiguous with this space. @@ -1938,6 +1985,7 @@ xfs_free_ag_extent(  		if ((error = xfs_alloc_get_rec(bno_cur, <bno, <len, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(bno_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -1953,6 +2001,7 @@ xfs_free_ag_extent(  			 * Very bad.  			 */  			if (XFS_IS_CORRUPT(mp, ltbno + ltlen > bno)) { +				xfs_btree_mark_sick(bno_cur);  				error = -EFSCORRUPTED;  				goto error0;  			} @@ -1971,6 +2020,7 @@ xfs_free_ag_extent(  		if ((error = xfs_alloc_get_rec(bno_cur, >bno, >len, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(bno_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -1986,6 +2036,7 @@ xfs_free_ag_extent(  			 * Very bad.  			 */  			if (XFS_IS_CORRUPT(mp, bno + len > gtbno)) { +				xfs_btree_mark_sick(bno_cur);  				error = -EFSCORRUPTED;  				goto error0;  			} @@ -1994,7 +2045,7 @@ xfs_free_ag_extent(  	/*  	 * Now allocate and initialize a cursor for the by-size tree.  	 */ -	cnt_cur = xfs_allocbt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_CNT); +	cnt_cur = xfs_cntbt_init_cursor(mp, tp, agbp, pag);  	/*  	 * Have both left and right contiguous neighbors.  	 * Merge all three into a single free block. @@ -2006,12 +2057,14 @@ xfs_free_ag_extent(  		if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			error = -EFSCORRUPTED;  			goto error0;  		}  		if ((error = xfs_btree_delete(cnt_cur, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -2021,12 +2074,14 @@ xfs_free_ag_extent(  		if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			error = -EFSCORRUPTED;  			goto error0;  		}  		if ((error = xfs_btree_delete(cnt_cur, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -2036,6 +2091,7 @@ xfs_free_ag_extent(  		if ((error = xfs_btree_delete(bno_cur, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(bno_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -2045,6 +2101,7 @@ xfs_free_ag_extent(  		if ((error = xfs_btree_decrement(bno_cur, 0, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(bno_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -2064,6 +2121,7 @@ xfs_free_ag_extent(  					   i != 1 ||  					   xxbno != ltbno ||  					   xxlen != ltlen)) { +				xfs_btree_mark_sick(bno_cur);  				error = -EFSCORRUPTED;  				goto error0;  			} @@ -2088,12 +2146,14 @@ xfs_free_ag_extent(  		if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			error = -EFSCORRUPTED;  			goto error0;  		}  		if ((error = xfs_btree_delete(cnt_cur, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -2104,6 +2164,7 @@ xfs_free_ag_extent(  		if ((error = xfs_btree_decrement(bno_cur, 0, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(bno_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -2123,12 +2184,14 @@ xfs_free_ag_extent(  		if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			error = -EFSCORRUPTED;  			goto error0;  		}  		if ((error = xfs_btree_delete(cnt_cur, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(cnt_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -2151,6 +2214,7 @@ xfs_free_ag_extent(  		if ((error = xfs_btree_insert(bno_cur, &i)))  			goto error0;  		if (XFS_IS_CORRUPT(mp, i != 1)) { +			xfs_btree_mark_sick(bno_cur);  			error = -EFSCORRUPTED;  			goto error0;  		} @@ -2163,12 +2227,14 @@ xfs_free_ag_extent(  	if ((error = xfs_alloc_lookup_eq(cnt_cur, nbno, nlen, &i)))  		goto error0;  	if (XFS_IS_CORRUPT(mp, i != 0)) { +		xfs_btree_mark_sick(cnt_cur);  		error = -EFSCORRUPTED;  		goto error0;  	}  	if ((error = xfs_btree_insert(cnt_cur, &i)))  		goto error0;  	if (XFS_IS_CORRUPT(mp, i != 1)) { +		xfs_btree_mark_sick(cnt_cur);  		error = -EFSCORRUPTED;  		goto error0;  	} @@ -2267,8 +2333,9 @@ xfs_alloc_min_freelist(  	struct xfs_perag	*pag)  {  	/* AG btrees have at least 1 level. */ -	static const uint8_t	fake_levels[XFS_BTNUM_AGF] = {1, 1, 1}; -	const uint8_t		*levels = pag ? pag->pagf_levels : fake_levels; +	const unsigned int	bno_level = pag ? pag->pagf_bno_level : 1; +	const unsigned int	cnt_level = pag ? pag->pagf_cnt_level : 1; +	const unsigned int	rmap_level = pag ? pag->pagf_rmap_level : 1;  	unsigned int		min_free;  	ASSERT(mp->m_alloc_maxlevels > 0); @@ -2295,16 +2362,12 @@ xfs_alloc_min_freelist(  	 */  	/* space needed by-bno freespace btree */ -	min_free = min_t(unsigned int, levels[XFS_BTNUM_BNOi] + 1, -				       mp->m_alloc_maxlevels) * 2 - 2; +	min_free = min(bno_level + 1, mp->m_alloc_maxlevels) * 2 - 2;  	/* space needed by-size freespace btree */ -	min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1, -				       mp->m_alloc_maxlevels) * 2 - 2; +	min_free += min(cnt_level + 1, mp->m_alloc_maxlevels) * 2 - 2;  	/* space needed reverse mapping used space btree */  	if (xfs_has_rmapbt(mp)) -		min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1, -						mp->m_rmap_maxlevels) * 2 - 2; - +		min_free += min(rmap_level + 1, mp->m_rmap_maxlevels) * 2 - 2;  	return min_free;  } @@ -2691,13 +2754,14 @@ xfs_exact_minlen_extent_available(  	xfs_extlen_t		flen;  	int			error = 0; -	cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, agbp, -					args->pag, XFS_BTNUM_CNT); +	cnt_cur = xfs_cntbt_init_cursor(args->mp, args->tp, agbp, +					args->pag);  	error = xfs_alloc_lookup_ge(cnt_cur, 0, args->minlen, stat);  	if (error)  		goto out;  	if (*stat == 0) { +		xfs_btree_mark_sick(cnt_cur);  		error = -EFSCORRUPTED;  		goto out;  	} @@ -2987,8 +3051,8 @@ xfs_alloc_log_agf(  		offsetof(xfs_agf_t, agf_versionnum),  		offsetof(xfs_agf_t, agf_seqno),  		offsetof(xfs_agf_t, agf_length), -		offsetof(xfs_agf_t, agf_roots[0]), -		offsetof(xfs_agf_t, agf_levels[0]), +		offsetof(xfs_agf_t, agf_bno_root),   /* also cnt/rmap root */ +		offsetof(xfs_agf_t, agf_bno_level),  /* also cnt/rmap levels */  		offsetof(xfs_agf_t, agf_flfirst),  		offsetof(xfs_agf_t, agf_fllast),  		offsetof(xfs_agf_t, agf_flcount), @@ -3167,12 +3231,10 @@ xfs_agf_verify(  	    be32_to_cpu(agf->agf_freeblks) > agf_length)  		return __this_address; -	if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) < 1 || -	    be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) < 1 || -	    be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > -						mp->m_alloc_maxlevels || -	    be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > -						mp->m_alloc_maxlevels) +	if (be32_to_cpu(agf->agf_bno_level) < 1 || +	    be32_to_cpu(agf->agf_cnt_level) < 1 || +	    be32_to_cpu(agf->agf_bno_level) > mp->m_alloc_maxlevels || +	    be32_to_cpu(agf->agf_cnt_level) > mp->m_alloc_maxlevels)  		return __this_address;  	if (xfs_has_lazysbcount(mp) && @@ -3183,9 +3245,8 @@ xfs_agf_verify(  		if (be32_to_cpu(agf->agf_rmap_blocks) > agf_length)  			return __this_address; -		if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) < 1 || -		    be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > -							mp->m_rmap_maxlevels) +		if (be32_to_cpu(agf->agf_rmap_level) < 1 || +		    be32_to_cpu(agf->agf_rmap_level) > mp->m_rmap_maxlevels)  			return __this_address;  	} @@ -3268,6 +3329,8 @@ xfs_read_agf(  	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,  			XFS_AG_DADDR(mp, pag->pag_agno, XFS_AGF_DADDR(mp)),  			XFS_FSS_TO_BB(mp, 1), flags, agfbpp, &xfs_agf_buf_ops); +	if (xfs_metadata_is_sick(error)) +		xfs_ag_mark_sick(pag, XFS_SICK_AG_AGF);  	if (error)  		return error; @@ -3309,12 +3372,9 @@ xfs_alloc_read_agf(  		pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);  		pag->pagf_flcount = be32_to_cpu(agf->agf_flcount);  		pag->pagf_longest = be32_to_cpu(agf->agf_longest); -		pag->pagf_levels[XFS_BTNUM_BNOi] = -			be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]); -		pag->pagf_levels[XFS_BTNUM_CNTi] = -			be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); -		pag->pagf_levels[XFS_BTNUM_RMAPi] = -			be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]); +		pag->pagf_bno_level = be32_to_cpu(agf->agf_bno_level); +		pag->pagf_cnt_level = be32_to_cpu(agf->agf_cnt_level); +		pag->pagf_rmap_level = be32_to_cpu(agf->agf_rmap_level);  		pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);  		if (xfs_agfl_needs_reset(pag->pag_mount, agf))  			set_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate); @@ -3343,10 +3403,8 @@ xfs_alloc_read_agf(  		ASSERT(pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks));  		ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount));  		ASSERT(pag->pagf_longest == be32_to_cpu(agf->agf_longest)); -		ASSERT(pag->pagf_levels[XFS_BTNUM_BNOi] == -		       be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi])); -		ASSERT(pag->pagf_levels[XFS_BTNUM_CNTi] == -		       be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi])); +		ASSERT(pag->pagf_bno_level == be32_to_cpu(agf->agf_bno_level)); +		ASSERT(pag->pagf_cnt_level == be32_to_cpu(agf->agf_cnt_level));  	}  #endif  	if (agfbpp) @@ -3895,17 +3953,23 @@ __xfs_free_extent(  		return -EIO;  	error = xfs_free_extent_fix_freelist(tp, pag, &agbp); -	if (error) +	if (error) { +		if (xfs_metadata_is_sick(error)) +			xfs_ag_mark_sick(pag, XFS_SICK_AG_BNOBT);  		return error; +	} +  	agf = agbp->b_addr;  	if (XFS_IS_CORRUPT(mp, agbno >= mp->m_sb.sb_agblocks)) { +		xfs_ag_mark_sick(pag, XFS_SICK_AG_BNOBT);  		error = -EFSCORRUPTED;  		goto err_release;  	}  	/* validate the extent size is legal now we have the agf locked */  	if (XFS_IS_CORRUPT(mp, agbno + len > be32_to_cpu(agf->agf_length))) { +		xfs_ag_mark_sick(pag, XFS_SICK_AG_BNOBT);  		error = -EFSCORRUPTED;  		goto err_release;  	} @@ -3962,7 +4026,7 @@ xfs_alloc_query_range(  	union xfs_btree_irec			high_brec = { .a = *high_rec };  	struct xfs_alloc_query_range_info	query = { .priv = priv, .fn = fn }; -	ASSERT(cur->bc_btnum == XFS_BTNUM_BNO); +	ASSERT(xfs_btree_is_bno(cur->bc_ops));  	return xfs_btree_query_range(cur, &low_brec, &high_brec,  			xfs_alloc_query_range_helper, &query);  } @@ -3976,7 +4040,7 @@ xfs_alloc_query_all(  {  	struct xfs_alloc_query_range_info	query; -	ASSERT(cur->bc_btnum == XFS_BTNUM_BNO); +	ASSERT(xfs_btree_is_bno(cur->bc_ops));  	query.priv = priv;  	query.fn = fn;  	return xfs_btree_query_all(cur, xfs_alloc_query_range_helper, &query);  | 
