brintos

brintos / linux-shallow public Read only

0
0
Text · 24.2 KiB · c8d2196 Raw
885 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2018-2023 Oracle.  All Rights Reserved.4 * Author: Darrick J. Wong <djwong@kernel.org>5 */6#include "xfs.h"7#include "xfs_fs.h"8#include "xfs_shared.h"9#include "xfs_format.h"10#include "xfs_trans_resv.h"11#include "xfs_mount.h"12#include "xfs_defer.h"13#include "xfs_btree.h"14#include "xfs_btree_staging.h"15#include "xfs_bit.h"16#include "xfs_log_format.h"17#include "xfs_trans.h"18#include "xfs_sb.h"19#include "xfs_inode.h"20#include "xfs_alloc.h"21#include "xfs_ialloc.h"22#include "xfs_ialloc_btree.h"23#include "xfs_icache.h"24#include "xfs_rmap.h"25#include "xfs_rmap_btree.h"26#include "xfs_log.h"27#include "xfs_trans_priv.h"28#include "xfs_error.h"29#include "xfs_health.h"30#include "xfs_ag.h"31#include "scrub/xfs_scrub.h"32#include "scrub/scrub.h"33#include "scrub/common.h"34#include "scrub/btree.h"35#include "scrub/trace.h"36#include "scrub/repair.h"37#include "scrub/bitmap.h"38#include "scrub/agb_bitmap.h"39#include "scrub/xfile.h"40#include "scrub/xfarray.h"41#include "scrub/newbt.h"42#include "scrub/reap.h"43 44/*45 * Inode Btree Repair46 * ==================47 *48 * A quick refresher of inode btrees on a v5 filesystem:49 *50 * - Inode records are read into memory in units of 'inode clusters'.  However51 *   many inodes fit in a cluster buffer is the smallest number of inodes that52 *   can be allocated or freed.  Clusters are never smaller than one fs block53 *   though they can span multiple blocks.  The size (in fs blocks) is54 *   computed with xfs_icluster_size_fsb().  The fs block alignment of a55 *   cluster is computed with xfs_ialloc_cluster_alignment().56 *57 * - Each inode btree record can describe a single 'inode chunk'.  The chunk58 *   size is defined to be 64 inodes.  If sparse inodes are enabled, every59 *   inobt record must be aligned to the chunk size; if not, every record must60 *   be aligned to the start of a cluster.  It is possible to construct an XFS61 *   geometry where one inobt record maps to multiple inode clusters; it is62 *   also possible to construct a geometry where multiple inobt records map to63 *   different parts of one inode cluster.64 *65 * - If sparse inodes are not enabled, the smallest unit of allocation for66 *   inode records is enough to contain one inode chunk's worth of inodes.67 *68 * - If sparse inodes are enabled, the holemask field will be active.  Each69 *   bit of the holemask represents 4 potential inodes; if set, the70 *   corresponding space does *not* contain inodes and must be left alone.71 *   Clusters cannot be smaller than 4 inodes.  The smallest unit of allocation72 *   of inode records is one inode cluster.73 *74 * So what's the rebuild algorithm?75 *76 * Iterate the reverse mapping records looking for OWN_INODES and OWN_INOBT77 * records.  The OWN_INOBT records are the old inode btree blocks and will be78 * cleared out after we've rebuilt the tree.  Each possible inode cluster79 * within an OWN_INODES record will be read in; for each possible inobt record80 * associated with that cluster, compute the freemask calculated from the81 * i_mode data in the inode chunk.  For sparse inodes the holemask will be82 * calculated by creating the properly aligned inobt record and punching out83 * any chunk that's missing.  Inode allocations and frees grab the AGI first,84 * so repair protects itself from concurrent access by locking the AGI.85 *86 * Once we've reconstructed all the inode records, we can create new inode87 * btree roots and reload the btrees.  We rebuild both inode trees at the same88 * time because they have the same rmap owner and it would be more complex to89 * figure out if the other tree isn't in need of a rebuild and which OWN_INOBT90 * blocks it owns.  We have all the data we need to build both, so dump91 * everything and start over.92 *93 * We use the prefix 'xrep_ibt' because we rebuild both inode btrees at once.94 */95 96struct xrep_ibt {97	/* Record under construction. */98	struct xfs_inobt_rec_incore	rie;99 100	/* new inobt information */101	struct xrep_newbt	new_inobt;102 103	/* new finobt information */104	struct xrep_newbt	new_finobt;105 106	/* Old inode btree blocks we found in the rmap. */107	struct xagb_bitmap	old_iallocbt_blocks;108 109	/* Reconstructed inode records. */110	struct xfarray		*inode_records;111 112	struct xfs_scrub	*sc;113 114	/* Number of inodes assigned disk space. */115	unsigned int		icount;116 117	/* Number of inodes in use. */118	unsigned int		iused;119 120	/* Number of finobt records needed. */121	unsigned int		finobt_recs;122 123	/* get_records()'s position in the inode record array. */124	xfarray_idx_t		array_cur;125};126 127/*128 * Is this inode in use?  If the inode is in memory we can tell from i_mode,129 * otherwise we have to check di_mode in the on-disk buffer.  We only care130 * that the high (i.e. non-permission) bits of _mode are zero.  This should be131 * safe because repair keeps all AG headers locked until the end, and process132 * trying to perform an inode allocation/free must lock the AGI.133 *134 * @cluster_ag_base is the inode offset of the cluster within the AG.135 * @cluster_bp is the cluster buffer.136 * @cluster_index is the inode offset within the inode cluster.137 */138STATIC int139xrep_ibt_check_ifree(140	struct xrep_ibt		*ri,141	xfs_agino_t		cluster_ag_base,142	struct xfs_buf		*cluster_bp,143	unsigned int		cluster_index,144	bool			*inuse)145{146	struct xfs_scrub	*sc = ri->sc;147	struct xfs_mount	*mp = sc->mp;148	struct xfs_dinode	*dip;149	xfs_ino_t		fsino;150	xfs_agino_t		agino;151	xfs_agnumber_t		agno = ri->sc->sa.pag->pag_agno;152	unsigned int		cluster_buf_base;153	unsigned int		offset;154	int			error;155 156	agino = cluster_ag_base + cluster_index;157	fsino = XFS_AGINO_TO_INO(mp, agno, agino);158 159	/* Inode uncached or half assembled, read disk buffer */160	cluster_buf_base = XFS_INO_TO_OFFSET(mp, cluster_ag_base);161	offset = (cluster_buf_base + cluster_index) * mp->m_sb.sb_inodesize;162	if (offset >= BBTOB(cluster_bp->b_length))163		return -EFSCORRUPTED;164	dip = xfs_buf_offset(cluster_bp, offset);165	if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)166		return -EFSCORRUPTED;167 168	if (dip->di_version >= 3 && be64_to_cpu(dip->di_ino) != fsino)169		return -EFSCORRUPTED;170 171	/* Will the in-core inode tell us if it's in use? */172	error = xchk_inode_is_allocated(sc, agino, inuse);173	if (!error)174		return 0;175 176	*inuse = dip->di_mode != 0;177	return 0;178}179 180/* Stash the accumulated inobt record for rebuilding. */181STATIC int182xrep_ibt_stash(183	struct xrep_ibt		*ri)184{185	int			error = 0;186 187	if (xchk_should_terminate(ri->sc, &error))188		return error;189 190	ri->rie.ir_freecount = xfs_inobt_rec_freecount(&ri->rie);191	if (xfs_inobt_check_irec(ri->sc->sa.pag, &ri->rie) != NULL)192		return -EFSCORRUPTED;193 194	if (ri->rie.ir_freecount > 0)195		ri->finobt_recs++;196 197	trace_xrep_ibt_found(ri->sc->mp, ri->sc->sa.pag->pag_agno, &ri->rie);198 199	error = xfarray_append(ri->inode_records, &ri->rie);200	if (error)201		return error;202 203	ri->rie.ir_startino = NULLAGINO;204	return 0;205}206 207/*208 * Given an extent of inodes and an inode cluster buffer, calculate the209 * location of the corresponding inobt record (creating it if necessary),210 * then update the parts of the holemask and freemask of that record that211 * correspond to the inode extent we were given.212 *213 * @cluster_ir_startino is the AG inode number of an inobt record that we're214 * proposing to create for this inode cluster.  If sparse inodes are enabled,215 * we must round down to a chunk boundary to find the actual sparse record.216 * @cluster_bp is the buffer of the inode cluster.217 * @nr_inodes is the number of inodes to check from the cluster.218 */219STATIC int220xrep_ibt_cluster_record(221	struct xrep_ibt		*ri,222	xfs_agino_t		cluster_ir_startino,223	struct xfs_buf		*cluster_bp,224	unsigned int		nr_inodes)225{226	struct xfs_scrub	*sc = ri->sc;227	struct xfs_mount	*mp = sc->mp;228	xfs_agino_t		ir_startino;229	unsigned int		cluster_base;230	unsigned int		cluster_index;231	int			error = 0;232 233	ir_startino = cluster_ir_startino;234	if (xfs_has_sparseinodes(mp))235		ir_startino = rounddown(ir_startino, XFS_INODES_PER_CHUNK);236	cluster_base = cluster_ir_startino - ir_startino;237 238	/*239	 * If the accumulated inobt record doesn't map this cluster, add it to240	 * the list and reset it.241	 */242	if (ri->rie.ir_startino != NULLAGINO &&243	    ri->rie.ir_startino + XFS_INODES_PER_CHUNK <= ir_startino) {244		error = xrep_ibt_stash(ri);245		if (error)246			return error;247	}248 249	if (ri->rie.ir_startino == NULLAGINO) {250		ri->rie.ir_startino = ir_startino;251		ri->rie.ir_free = XFS_INOBT_ALL_FREE;252		ri->rie.ir_holemask = 0xFFFF;253		ri->rie.ir_count = 0;254	}255 256	/* Record the whole cluster. */257	ri->icount += nr_inodes;258	ri->rie.ir_count += nr_inodes;259	ri->rie.ir_holemask &= ~xfs_inobt_maskn(260				cluster_base / XFS_INODES_PER_HOLEMASK_BIT,261				nr_inodes / XFS_INODES_PER_HOLEMASK_BIT);262 263	/* Which inodes within this cluster are free? */264	for (cluster_index = 0; cluster_index < nr_inodes; cluster_index++) {265		bool		inuse = false;266 267		error = xrep_ibt_check_ifree(ri, cluster_ir_startino,268				cluster_bp, cluster_index, &inuse);269		if (error)270			return error;271		if (!inuse)272			continue;273		ri->iused++;274		ri->rie.ir_free &= ~XFS_INOBT_MASK(cluster_base +275						   cluster_index);276	}277	return 0;278}279 280/*281 * For each inode cluster covering the physical extent recorded by the rmapbt,282 * we must calculate the properly aligned startino of that cluster, then283 * iterate each cluster to fill in used and filled masks appropriately.  We284 * then use the (startino, used, filled) information to construct the285 * appropriate inode records.286 */287STATIC int288xrep_ibt_process_cluster(289	struct xrep_ibt		*ri,290	xfs_agblock_t		cluster_bno)291{292	struct xfs_imap		imap;293	struct xfs_buf		*cluster_bp;294	struct xfs_scrub	*sc = ri->sc;295	struct xfs_mount	*mp = sc->mp;296	struct xfs_ino_geometry	*igeo = M_IGEO(mp);297	xfs_agino_t		cluster_ag_base;298	xfs_agino_t		irec_index;299	unsigned int		nr_inodes;300	int			error;301 302	nr_inodes = min_t(unsigned int, igeo->inodes_per_cluster,303			XFS_INODES_PER_CHUNK);304 305	/*306	 * Grab the inode cluster buffer.  This is safe to do with a broken307	 * inobt because imap_to_bp directly maps the buffer without touching308	 * either inode btree.309	 */310	imap.im_blkno = XFS_AGB_TO_DADDR(mp, sc->sa.pag->pag_agno, cluster_bno);311	imap.im_len = XFS_FSB_TO_BB(mp, igeo->blocks_per_cluster);312	imap.im_boffset = 0;313	error = xfs_imap_to_bp(mp, sc->tp, &imap, &cluster_bp);314	if (error)315		return error;316 317	/*318	 * Record the contents of each possible inobt record mapping this319	 * cluster.320	 */321	cluster_ag_base = XFS_AGB_TO_AGINO(mp, cluster_bno);322	for (irec_index = 0;323	     irec_index < igeo->inodes_per_cluster;324	     irec_index += XFS_INODES_PER_CHUNK) {325		error = xrep_ibt_cluster_record(ri,326				cluster_ag_base + irec_index, cluster_bp,327				nr_inodes);328		if (error)329			break;330 331	}332 333	xfs_trans_brelse(sc->tp, cluster_bp);334	return error;335}336 337/* Check for any obvious conflicts in the inode chunk extent. */338STATIC int339xrep_ibt_check_inode_ext(340	struct xfs_scrub	*sc,341	xfs_agblock_t		agbno,342	xfs_extlen_t		len)343{344	struct xfs_mount	*mp = sc->mp;345	struct xfs_ino_geometry	*igeo = M_IGEO(mp);346	xfs_agino_t		agino;347	enum xbtree_recpacking	outcome;348	int			error;349 350	/* Inode records must be within the AG. */351	if (!xfs_verify_agbext(sc->sa.pag, agbno, len))352		return -EFSCORRUPTED;353 354	/* The entire record must align to the inode cluster size. */355	if (!IS_ALIGNED(agbno, igeo->blocks_per_cluster) ||356	    !IS_ALIGNED(agbno + len, igeo->blocks_per_cluster))357		return -EFSCORRUPTED;358 359	/*360	 * The entire record must also adhere to the inode cluster alignment361	 * size if sparse inodes are not enabled.362	 */363	if (!xfs_has_sparseinodes(mp) &&364	    (!IS_ALIGNED(agbno, igeo->cluster_align) ||365	     !IS_ALIGNED(agbno + len, igeo->cluster_align)))366		return -EFSCORRUPTED;367 368	/*369	 * On a sparse inode fs, this cluster could be part of a sparse chunk.370	 * Sparse clusters must be aligned to sparse chunk alignment.371	 */372	if (xfs_has_sparseinodes(mp) && mp->m_sb.sb_spino_align &&373	    (!IS_ALIGNED(agbno, mp->m_sb.sb_spino_align) ||374	     !IS_ALIGNED(agbno + len, mp->m_sb.sb_spino_align)))375		return -EFSCORRUPTED;376 377	/* Make sure the entire range of blocks are valid AG inodes. */378	agino = XFS_AGB_TO_AGINO(mp, agbno);379	if (!xfs_verify_agino(sc->sa.pag, agino))380		return -EFSCORRUPTED;381 382	agino = XFS_AGB_TO_AGINO(mp, agbno + len) - 1;383	if (!xfs_verify_agino(sc->sa.pag, agino))384		return -EFSCORRUPTED;385 386	/* Make sure this isn't free space. */387	error = xfs_alloc_has_records(sc->sa.bno_cur, agbno, len, &outcome);388	if (error)389		return error;390	if (outcome != XBTREE_RECPACKING_EMPTY)391		return -EFSCORRUPTED;392 393	return 0;394}395 396/* Found a fragment of the old inode btrees; dispose of them later. */397STATIC int398xrep_ibt_record_old_btree_blocks(399	struct xrep_ibt			*ri,400	const struct xfs_rmap_irec	*rec)401{402	if (!xfs_verify_agbext(ri->sc->sa.pag, rec->rm_startblock,403				rec->rm_blockcount))404		return -EFSCORRUPTED;405 406	return xagb_bitmap_set(&ri->old_iallocbt_blocks, rec->rm_startblock,407			rec->rm_blockcount);408}409 410/* Record extents that belong to inode cluster blocks. */411STATIC int412xrep_ibt_record_inode_blocks(413	struct xrep_ibt			*ri,414	const struct xfs_rmap_irec	*rec)415{416	struct xfs_mount		*mp = ri->sc->mp;417	struct xfs_ino_geometry		*igeo = M_IGEO(mp);418	xfs_agblock_t			cluster_base;419	int				error;420 421	error = xrep_ibt_check_inode_ext(ri->sc, rec->rm_startblock,422			rec->rm_blockcount);423	if (error)424		return error;425 426	trace_xrep_ibt_walk_rmap(mp, ri->sc->sa.pag->pag_agno,427			rec->rm_startblock, rec->rm_blockcount, rec->rm_owner,428			rec->rm_offset, rec->rm_flags);429 430	/*431	 * Record the free/hole masks for each inode cluster that could be432	 * mapped by this rmap record.433	 */434	for (cluster_base = 0;435	     cluster_base < rec->rm_blockcount;436	     cluster_base += igeo->blocks_per_cluster) {437		error = xrep_ibt_process_cluster(ri,438				rec->rm_startblock + cluster_base);439		if (error)440			return error;441	}442 443	return 0;444}445 446STATIC int447xrep_ibt_walk_rmap(448	struct xfs_btree_cur		*cur,449	const struct xfs_rmap_irec	*rec,450	void				*priv)451{452	struct xrep_ibt			*ri = priv;453	int				error = 0;454 455	if (xchk_should_terminate(ri->sc, &error))456		return error;457 458	switch (rec->rm_owner) {459	case XFS_RMAP_OWN_INOBT:460		return xrep_ibt_record_old_btree_blocks(ri, rec);461	case XFS_RMAP_OWN_INODES:462		return xrep_ibt_record_inode_blocks(ri, rec);463	}464	return 0;465}466 467/*468 * Iterate all reverse mappings to find the inodes (OWN_INODES) and the inode469 * btrees (OWN_INOBT).  Figure out if we have enough free space to reconstruct470 * the inode btrees.  The caller must clean up the lists if anything goes471 * wrong.472 */473STATIC int474xrep_ibt_find_inodes(475	struct xrep_ibt		*ri)476{477	struct xfs_scrub	*sc = ri->sc;478	int			error;479 480	ri->rie.ir_startino = NULLAGINO;481 482	/* Collect all reverse mappings for inode blocks. */483	xrep_ag_btcur_init(sc, &sc->sa);484	error = xfs_rmap_query_all(sc->sa.rmap_cur, xrep_ibt_walk_rmap, ri);485	xchk_ag_btcur_free(&sc->sa);486	if (error)487		return error;488 489	/* If we have a record ready to go, add it to the array. */490	if (ri->rie.ir_startino != NULLAGINO)491		return xrep_ibt_stash(ri);492 493	return 0;494}495 496/* Update the AGI counters. */497STATIC int498xrep_ibt_reset_counters(499	struct xrep_ibt		*ri)500{501	struct xfs_scrub	*sc = ri->sc;502	struct xfs_agi		*agi = sc->sa.agi_bp->b_addr;503	unsigned int		freecount = ri->icount - ri->iused;504 505	/* Trigger inode count recalculation */506	xfs_force_summary_recalc(sc->mp);507 508	/*509	 * The AGI header contains extra information related to the inode510	 * btrees, so we must update those fields here.511	 */512	agi->agi_count = cpu_to_be32(ri->icount);513	agi->agi_freecount = cpu_to_be32(freecount);514	xfs_ialloc_log_agi(sc->tp, sc->sa.agi_bp,515			   XFS_AGI_COUNT | XFS_AGI_FREECOUNT);516 517	/* Reinitialize with the values we just logged. */518	return xrep_reinit_pagi(sc);519}520 521/* Retrieve finobt data for bulk load. */522STATIC int523xrep_fibt_get_records(524	struct xfs_btree_cur		*cur,525	unsigned int			idx,526	struct xfs_btree_block		*block,527	unsigned int			nr_wanted,528	void				*priv)529{530	struct xfs_inobt_rec_incore	*irec = &cur->bc_rec.i;531	struct xrep_ibt			*ri = priv;532	union xfs_btree_rec		*block_rec;533	unsigned int			loaded;534	int				error;535 536	for (loaded = 0; loaded < nr_wanted; loaded++, idx++) {537		do {538			error = xfarray_load(ri->inode_records,539					ri->array_cur++, irec);540		} while (error == 0 && xfs_inobt_rec_freecount(irec) == 0);541		if (error)542			return error;543 544		block_rec = xfs_btree_rec_addr(cur, idx, block);545		cur->bc_ops->init_rec_from_cur(cur, block_rec);546	}547 548	return loaded;549}550 551/* Retrieve inobt data for bulk load. */552STATIC int553xrep_ibt_get_records(554	struct xfs_btree_cur		*cur,555	unsigned int			idx,556	struct xfs_btree_block		*block,557	unsigned int			nr_wanted,558	void				*priv)559{560	struct xfs_inobt_rec_incore	*irec = &cur->bc_rec.i;561	struct xrep_ibt			*ri = priv;562	union xfs_btree_rec		*block_rec;563	unsigned int			loaded;564	int				error;565 566	for (loaded = 0; loaded < nr_wanted; loaded++, idx++) {567		error = xfarray_load(ri->inode_records, ri->array_cur++, irec);568		if (error)569			return error;570 571		block_rec = xfs_btree_rec_addr(cur, idx, block);572		cur->bc_ops->init_rec_from_cur(cur, block_rec);573	}574 575	return loaded;576}577 578/* Feed one of the new inobt blocks to the bulk loader. */579STATIC int580xrep_ibt_claim_block(581	struct xfs_btree_cur	*cur,582	union xfs_btree_ptr	*ptr,583	void			*priv)584{585	struct xrep_ibt		*ri = priv;586 587	return xrep_newbt_claim_block(cur, &ri->new_inobt, ptr);588}589 590/* Feed one of the new finobt blocks to the bulk loader. */591STATIC int592xrep_fibt_claim_block(593	struct xfs_btree_cur	*cur,594	union xfs_btree_ptr	*ptr,595	void			*priv)596{597	struct xrep_ibt		*ri = priv;598 599	return xrep_newbt_claim_block(cur, &ri->new_finobt, ptr);600}601 602/* Make sure the records do not overlap in inumber address space. */603STATIC int604xrep_ibt_check_overlap(605	struct xrep_ibt			*ri)606{607	struct xfs_inobt_rec_incore	irec;608	xfarray_idx_t			cur;609	xfs_agino_t			next_agino = 0;610	int				error = 0;611 612	foreach_xfarray_idx(ri->inode_records, cur) {613		if (xchk_should_terminate(ri->sc, &error))614			return error;615 616		error = xfarray_load(ri->inode_records, cur, &irec);617		if (error)618			return error;619 620		if (irec.ir_startino < next_agino)621			return -EFSCORRUPTED;622 623		next_agino = irec.ir_startino + XFS_INODES_PER_CHUNK;624	}625 626	return error;627}628 629/* Build new inode btrees and dispose of the old one. */630STATIC int631xrep_ibt_build_new_trees(632	struct xrep_ibt		*ri)633{634	struct xfs_scrub	*sc = ri->sc;635	struct xfs_btree_cur	*ino_cur;636	struct xfs_btree_cur	*fino_cur = NULL;637	xfs_fsblock_t		fsbno;638	bool			need_finobt;639	int			error;640 641	need_finobt = xfs_has_finobt(sc->mp);642 643	/*644	 * Create new btrees for staging all the inobt records we collected645	 * earlier.  The records were collected in order of increasing agino,646	 * so we do not have to sort them.  Ensure there are no overlapping647	 * records.648	 */649	error = xrep_ibt_check_overlap(ri);650	if (error)651		return error;652 653	/*654	 * The new inode btrees will not be rooted in the AGI until we've655	 * successfully rebuilt the tree.656	 *657	 * Start by setting up the inobt staging cursor.658	 */659	fsbno = XFS_AGB_TO_FSB(sc->mp, sc->sa.pag->pag_agno,660			XFS_IBT_BLOCK(sc->mp));661	xrep_newbt_init_ag(&ri->new_inobt, sc, &XFS_RMAP_OINFO_INOBT, fsbno,662			XFS_AG_RESV_NONE);663	ri->new_inobt.bload.claim_block = xrep_ibt_claim_block;664	ri->new_inobt.bload.get_records = xrep_ibt_get_records;665 666	ino_cur = xfs_inobt_init_cursor(sc->sa.pag, NULL, NULL);667	xfs_btree_stage_afakeroot(ino_cur, &ri->new_inobt.afake);668	error = xfs_btree_bload_compute_geometry(ino_cur, &ri->new_inobt.bload,669			xfarray_length(ri->inode_records));670	if (error)671		goto err_inocur;672 673	/* Set up finobt staging cursor. */674	if (need_finobt) {675		enum xfs_ag_resv_type	resv = XFS_AG_RESV_METADATA;676 677		if (sc->mp->m_finobt_nores)678			resv = XFS_AG_RESV_NONE;679 680		fsbno = XFS_AGB_TO_FSB(sc->mp, sc->sa.pag->pag_agno,681				XFS_FIBT_BLOCK(sc->mp));682		xrep_newbt_init_ag(&ri->new_finobt, sc, &XFS_RMAP_OINFO_INOBT,683				fsbno, resv);684		ri->new_finobt.bload.claim_block = xrep_fibt_claim_block;685		ri->new_finobt.bload.get_records = xrep_fibt_get_records;686 687		fino_cur = xfs_finobt_init_cursor(sc->sa.pag, NULL, NULL);688		xfs_btree_stage_afakeroot(fino_cur, &ri->new_finobt.afake);689		error = xfs_btree_bload_compute_geometry(fino_cur,690				&ri->new_finobt.bload, ri->finobt_recs);691		if (error)692			goto err_finocur;693	}694 695	/* Last chance to abort before we start committing fixes. */696	if (xchk_should_terminate(sc, &error))697		goto err_finocur;698 699	/* Reserve all the space we need to build the new btrees. */700	error = xrep_newbt_alloc_blocks(&ri->new_inobt,701			ri->new_inobt.bload.nr_blocks);702	if (error)703		goto err_finocur;704 705	if (need_finobt) {706		error = xrep_newbt_alloc_blocks(&ri->new_finobt,707				ri->new_finobt.bload.nr_blocks);708		if (error)709			goto err_finocur;710	}711 712	/* Add all inobt records. */713	ri->array_cur = XFARRAY_CURSOR_INIT;714	error = xfs_btree_bload(ino_cur, &ri->new_inobt.bload, ri);715	if (error)716		goto err_finocur;717 718	/* Add all finobt records. */719	if (need_finobt) {720		ri->array_cur = XFARRAY_CURSOR_INIT;721		error = xfs_btree_bload(fino_cur, &ri->new_finobt.bload, ri);722		if (error)723			goto err_finocur;724	}725 726	/*727	 * Install the new btrees in the AG header.  After this point the old728	 * btrees are no longer accessible and the new trees are live.729	 */730	xfs_inobt_commit_staged_btree(ino_cur, sc->tp, sc->sa.agi_bp);731	xfs_btree_del_cursor(ino_cur, 0);732 733	if (fino_cur) {734		xfs_inobt_commit_staged_btree(fino_cur, sc->tp, sc->sa.agi_bp);735		xfs_btree_del_cursor(fino_cur, 0);736	}737 738	/* Reset the AGI counters now that we've changed the inode roots. */739	error = xrep_ibt_reset_counters(ri);740	if (error)741		goto err_finobt;742 743	/* Free unused blocks and bitmap. */744	if (need_finobt) {745		error = xrep_newbt_commit(&ri->new_finobt);746		if (error)747			goto err_inobt;748	}749	error = xrep_newbt_commit(&ri->new_inobt);750	if (error)751		return error;752 753	return xrep_roll_ag_trans(sc);754 755err_finocur:756	if (need_finobt)757		xfs_btree_del_cursor(fino_cur, error);758err_inocur:759	xfs_btree_del_cursor(ino_cur, error);760err_finobt:761	if (need_finobt)762		xrep_newbt_cancel(&ri->new_finobt);763err_inobt:764	xrep_newbt_cancel(&ri->new_inobt);765	return error;766}767 768/*769 * Now that we've logged the roots of the new btrees, invalidate all of the770 * old blocks and free them.771 */772STATIC int773xrep_ibt_remove_old_trees(774	struct xrep_ibt		*ri)775{776	struct xfs_scrub	*sc = ri->sc;777	int			error;778 779	/*780	 * Free the old inode btree blocks if they're not in use.  It's ok to781	 * reap with XFS_AG_RESV_NONE even if the finobt had a per-AG782	 * reservation because we reset the reservation before releasing the783	 * AGI and AGF header buffer locks.784	 */785	error = xrep_reap_agblocks(sc, &ri->old_iallocbt_blocks,786			&XFS_RMAP_OINFO_INOBT, XFS_AG_RESV_NONE);787	if (error)788		return error;789 790	/*791	 * If the finobt is enabled and has a per-AG reservation, make sure we792	 * reinitialize the per-AG reservations.793	 */794	if (xfs_has_finobt(sc->mp) && !sc->mp->m_finobt_nores)795		sc->flags |= XREP_RESET_PERAG_RESV;796 797	return 0;798}799 800/* Repair both inode btrees. */801int802xrep_iallocbt(803	struct xfs_scrub	*sc)804{805	struct xrep_ibt		*ri;806	struct xfs_mount	*mp = sc->mp;807	char			*descr;808	xfs_agino_t		first_agino, last_agino;809	int			error = 0;810 811	/* We require the rmapbt to rebuild anything. */812	if (!xfs_has_rmapbt(mp))813		return -EOPNOTSUPP;814 815	ri = kzalloc(sizeof(struct xrep_ibt), XCHK_GFP_FLAGS);816	if (!ri)817		return -ENOMEM;818	ri->sc = sc;819 820	/* We rebuild both inode btrees. */821	sc->sick_mask = XFS_SICK_AG_INOBT | XFS_SICK_AG_FINOBT;822 823	/* Set up enough storage to handle an AG with nothing but inodes. */824	xfs_agino_range(mp, sc->sa.pag->pag_agno, &first_agino, &last_agino);825	last_agino /= XFS_INODES_PER_CHUNK;826	descr = xchk_xfile_ag_descr(sc, "inode index records");827	error = xfarray_create(descr, last_agino,828			sizeof(struct xfs_inobt_rec_incore),829			&ri->inode_records);830	kfree(descr);831	if (error)832		goto out_ri;833 834	/* Collect the inode data and find the old btree blocks. */835	xagb_bitmap_init(&ri->old_iallocbt_blocks);836	error = xrep_ibt_find_inodes(ri);837	if (error)838		goto out_bitmap;839 840	/* Rebuild the inode indexes. */841	error = xrep_ibt_build_new_trees(ri);842	if (error)843		goto out_bitmap;844 845	/* Kill the old tree. */846	error = xrep_ibt_remove_old_trees(ri);847	if (error)848		goto out_bitmap;849 850out_bitmap:851	xagb_bitmap_destroy(&ri->old_iallocbt_blocks);852	xfarray_destroy(ri->inode_records);853out_ri:854	kfree(ri);855	return error;856}857 858/* Make sure both btrees are ok after we've rebuilt them. */859int860xrep_revalidate_iallocbt(861	struct xfs_scrub	*sc)862{863	__u32			old_type = sc->sm->sm_type;864	int			error;865 866	/*867	 * We must update sm_type temporarily so that the tree-to-tree cross868	 * reference checks will work in the correct direction, and also so869	 * that tracing will report correctly if there are more errors.870	 */871	sc->sm->sm_type = XFS_SCRUB_TYPE_INOBT;872	error = xchk_iallocbt(sc);873	if (error)874		goto out;875 876	if (xfs_has_finobt(sc->mp)) {877		sc->sm->sm_type = XFS_SCRUB_TYPE_FINOBT;878		error = xchk_iallocbt(sc);879	}880 881out:882	sc->sm->sm_type = old_type;883	return error;884}885