/*
 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <libxfs.h>
#include "avl.h"
#include "globals.h"
#include "agheader.h"
#include "incore.h"
#include "protos.h"
#include "err_protos.h"
#include "dinode.h"
#include "scan.h"
#include "versions.h"
#include "bmap.h"
#include "progress.h"

extern int verify_set_agheader(xfs_mount_t *mp, xfs_buf_t *sbuf, xfs_sb_t *sb,
		xfs_agf_t *agf, xfs_agi_t *agi, xfs_agnumber_t i);

static xfs_mount_t	*mp = NULL;

void
set_mp(xfs_mount_t *mpp)
{
	libxfs_bcache_purge();
	mp = mpp;
}

void
scan_sbtree(
	xfs_agblock_t	root,
	int		nlevels,
	xfs_agnumber_t	agno,
	int		suspect,
	void		(*func)(struct xfs_btree_block	*block,
				int			level,
				xfs_agblock_t		bno,
				xfs_agnumber_t		agno,
				int			suspect,
				int			isroot),
	int		isroot)
{
	xfs_buf_t	*bp;

	bp = libxfs_readbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, root),
			XFS_FSB_TO_BB(mp, 1), 0);
	if (!bp) {
		do_error(_("can't read btree block %d/%d\n"), agno, root);
		return;
	}
	(*func)(XFS_BUF_TO_BLOCK(bp), nlevels - 1, root, agno, suspect, isroot);
	libxfs_putbuf(bp);
}

/*
 * returns 1 on bad news (inode needs to be cleared), 0 on good
 */
int
scan_lbtree(
	xfs_dfsbno_t	root,
	int		nlevels,
	int		(*func)(struct xfs_btree_block	*block,
				int			level,
				int			type,
				int			whichfork,
				xfs_dfsbno_t		bno,
				xfs_ino_t		ino,
				xfs_drfsbno_t		*tot,
				__uint64_t		*nex,
				blkmap_t		**blkmapp,
				bmap_cursor_t		*bm_cursor,
				int			isroot,
				int			check_dups,
				int			*dirty),
	int		type,
	int		whichfork,
	xfs_ino_t	ino,
	xfs_drfsbno_t	*tot,
	__uint64_t	*nex,
	blkmap_t	**blkmapp,
	bmap_cursor_t	*bm_cursor,
	int		isroot,
	int		check_dups)
{
	xfs_buf_t	*bp;
	int		err;
	int		dirty = 0;

	bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, root),
		      XFS_FSB_TO_BB(mp, 1), 0);
	if (!bp)  {
		do_error(_("can't read btree block %d/%d\n"),
			XFS_FSB_TO_AGNO(mp, root),
			XFS_FSB_TO_AGBNO(mp, root));
		return(1);
	}
	err = (*func)(XFS_BUF_TO_BLOCK(bp), nlevels - 1,
			type, whichfork, root, ino, tot, nex, blkmapp,
			bm_cursor, isroot, check_dups, &dirty);

	ASSERT(dirty == 0 || (dirty && !no_modify));

	if (dirty && !no_modify)
		libxfs_writebuf(bp, 0);
	else
		libxfs_putbuf(bp);

	return(err);
}

int
scanfunc_bmap(
	struct xfs_btree_block	*block,
	int			level,
	int			type,
	int			whichfork,
	xfs_dfsbno_t		bno,
	xfs_ino_t		ino,
	xfs_drfsbno_t		*tot,
	__uint64_t		*nex,
	blkmap_t		**blkmapp,
	bmap_cursor_t		*bm_cursor,
	int			isroot,
	int			check_dups,
	int			*dirty)
{
	int			i;
	int			err;
	xfs_bmbt_ptr_t		*pp;
	xfs_bmbt_key_t		*pkey;
	xfs_bmbt_rec_t		*rp;
	xfs_dfiloff_t		first_key;
	xfs_dfiloff_t		last_key;
	char			*forkname;
	int			numrecs;
	xfs_agnumber_t		agno;
	xfs_agblock_t		agbno;
	int			state;

	if (whichfork == XFS_DATA_FORK)
		forkname = _("data");
	else
		forkname = _("attr");

	/*
	 * unlike the ag freeblock btrees, if anything looks wrong
	 * in an inode bmap tree, just bail.  it's possible that
	 * we'll miss a case where the to-be-toasted inode and
	 * another inode are claiming the same block but that's
	 * highly unlikely.
	 */
	if (be32_to_cpu(block->bb_magic) != XFS_BMAP_MAGIC) {
		do_warn(_("bad magic # %#x in inode %llu (%s fork) bmbt "
			"block %llu\n"), be32_to_cpu(block->bb_magic),
			ino, forkname, bno);
		return(1);
	}
	if (be16_to_cpu(block->bb_level) != level) {
		do_warn(_("expected level %d got %d in inode %llu, (%s fork) "
			"bmbt block %llu\n"), level,
			be16_to_cpu(block->bb_level), ino, forkname, bno);
		return(1);
	}

	if (check_dups == 0)  {
		/*
		 * check sibling pointers. if bad we have a conflict
		 * between the sibling pointers and the child pointers
		 * in the parent block.  blow out the inode if that happens
		 */
		if (bm_cursor->level[level].fsbno != NULLDFSBNO)  {
			/*
			 * this is not the first block on this level
			 * so the cursor for this level has recorded the
			 * values for this's block left-sibling.
			 */
			if (bno != bm_cursor->level[level].right_fsbno)  {
				do_warn(
_("bad fwd (right) sibling pointer (saw %llu parent block says %llu)\n"
  "\tin inode %llu (%s fork) bmap btree block %llu\n"),
					bm_cursor->level[level].right_fsbno,
					bno, ino, forkname,
					bm_cursor->level[level].fsbno);
				return(1);
			}
			if (be64_to_cpu(block->bb_u.l.bb_leftsib) !=
					bm_cursor->level[level].fsbno)  {
				do_warn(
_("bad back (left) sibling pointer (saw %llu parent block says %llu)\n"
  "\tin inode %llu (%s fork) bmap btree block %llu\n"),
					be64_to_cpu(block->bb_u.l.bb_leftsib),
					bm_cursor->level[level].fsbno,
					ino, forkname, bno);
				return(1);
			}
		} else {
			/*
			 * This is the first or only block on this level.
			 * Check that the left sibling pointer is NULL
			 */
			if (be64_to_cpu(block->bb_u.l.bb_leftsib) != NULLDFSBNO) {
				do_warn(
_("bad back (left) sibling pointer (saw %llu should be NULL (0))\n"
  "\tin inode %llu (%s fork) bmap btree block %llu\n"),
					be64_to_cpu(block->bb_u.l.bb_leftsib),
					ino, forkname, bno);
				return(1);
			}
		}

		/*
		 * update cursor block pointers to reflect this block
		 */
		bm_cursor->level[level].fsbno = bno;
		bm_cursor->level[level].left_fsbno =
					be64_to_cpu(block->bb_u.l.bb_leftsib);
		bm_cursor->level[level].right_fsbno =
					be64_to_cpu(block->bb_u.l.bb_rightsib);

		agno = XFS_FSB_TO_AGNO(mp, bno);
		agbno = XFS_FSB_TO_AGBNO(mp, bno);

		pthread_mutex_lock(&ag_locks[agno]);
		state = get_bmap(agno, agbno);
		switch (state) {
		case XR_E_UNKNOWN:
		case XR_E_FREE1:
		case XR_E_FREE:
			set_bmap(agno, agbno, XR_E_INUSE);
			break;
		case XR_E_FS_MAP:
		case XR_E_INUSE:
			/*
			 * we'll try and continue searching here since
			 * the block looks like it's been claimed by file
			 * to store user data, a directory to store directory
			 * data, or the space allocation btrees but since
			 * we made it here, the block probably
			 * contains btree data.
			 */
			set_bmap(agno, agbno, XR_E_MULT);
			do_warn(
		_("inode 0x%llx bmap block 0x%llx claimed, state is %d\n"),
				ino, (__uint64_t) bno, state);
			break;
		case XR_E_MULT:
		case XR_E_INUSE_FS:
			set_bmap(agno, agbno, XR_E_MULT);
			do_warn(
		_("inode 0x%llx bmap block 0x%llx claimed, state is %d\n"),
				ino, (__uint64_t) bno, state);
			/*
			 * if we made it to here, this is probably a bmap block
			 * that is being used by *another* file as a bmap block
			 * so the block will be valid.  Both files should be
			 * trashed along with any other file that impinges on
			 * any blocks referenced by either file.  So we
			 * continue searching down this btree to mark all
			 * blocks duplicate
			 */
			break;
		case XR_E_BAD_STATE:
		default:
			do_warn(
		_("bad state %d, inode 0x%llx bmap block 0x%llx\n"),
				state, ino, (__uint64_t) bno);
			break;
		}
		pthread_mutex_unlock(&ag_locks[agno]);
	} else  {
		/*
		 * attribute fork for realtime files is in the regular
		 * filesystem
		 */
		if (type != XR_INO_RTDATA || whichfork != XFS_DATA_FORK)  {
			if (search_dup_extent(XFS_FSB_TO_AGNO(mp, bno),
					XFS_FSB_TO_AGBNO(mp, bno),
					XFS_FSB_TO_AGBNO(mp, bno) + 1))
				return(1);
		} else  {
			if (search_rt_dup_extent(mp, bno))
				return(1);
		}
	}
	(*tot)++;
	numrecs = be16_to_cpu(block->bb_numrecs);

	if (level == 0) {
		if (numrecs > mp->m_bmap_dmxr[0] || (isroot == 0 && numrecs <
							mp->m_bmap_dmnr[0])) {
				do_warn(
	_("inode 0x%llx bad # of bmap records (%u, min - %u, max - %u)\n"),
					ino, numrecs, mp->m_bmap_dmnr[0],
					mp->m_bmap_dmxr[0]);
			return(1);
		}
		rp = XFS_BMBT_REC_ADDR(mp, block, 1);
		*nex += numrecs;
		/*
		 * XXX - if we were going to fix up the btree record,
		 * we'd do it right here.  For now, if there's a problem,
		 * we'll bail out and presumably clear the inode.
		 */
		if (check_dups == 0)  {
			err = process_bmbt_reclist(mp, rp, numrecs,
					type, ino, tot, blkmapp,
					&first_key, &last_key,
					whichfork);
			if (err)
				return(1);
			/*
			 * check that key ordering is monotonically increasing.
			 * if the last_key value in the cursor is set to
			 * NULLDFILOFF, then we know this is the first block
			 * on the leaf level and we shouldn't check the
			 * last_key value.
			 */
			if (first_key <= bm_cursor->level[level].last_key &&
					bm_cursor->level[level].last_key !=
					NULLDFILOFF)  {
				do_warn(
_("out-of-order bmap key (file offset) in inode %llu, %s fork, fsbno %llu\n"),
					ino, forkname, bno);
				return(1);
			}
			/*
			 * update cursor keys to reflect this block.
			 * don't have to check if last_key is > first_key
			 * since that gets checked by process_bmbt_reclist.
			 */
			bm_cursor->level[level].first_key = first_key;
			bm_cursor->level[level].last_key = last_key;

			return(0);
		} else
			return(scan_bmbt_reclist(mp, rp, numrecs,
						type, ino, tot, whichfork));
	}
	if (numrecs > mp->m_bmap_dmxr[1] || (isroot == 0 && numrecs <
							mp->m_bmap_dmnr[1])) {
		do_warn(
	_("inode 0x%llx bad # of bmap records (%u, min - %u, max - %u)\n"),
			ino, numrecs, mp->m_bmap_dmnr[1], mp->m_bmap_dmxr[1]);
		return(1);
	}
	pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
	pkey = XFS_BMBT_KEY_ADDR(mp, block, 1);

	last_key = NULLDFILOFF;

	for (i = 0, err = 0; i < numrecs; i++)  {
		/*
		 * XXX - if we were going to fix up the interior btree nodes,
		 * we'd do it right here.  For now, if there's a problem,
		 * we'll bail out and presumably clear the inode.
		 */
		if (!verify_dfsbno(mp, be64_to_cpu(pp[i])))  {
			do_warn(_("bad bmap btree ptr 0x%llx in ino %llu\n"),
				be64_to_cpu(pp[i]), ino);
			return(1);
		}

		err = scan_lbtree(be64_to_cpu(pp[i]), level, scanfunc_bmap,
				type, whichfork, ino, tot, nex, blkmapp,
				bm_cursor, 0, check_dups);
		if (err)
			return(1);

		/*
		 * fix key (offset) mismatches between the first key
		 * in the child block (as recorded in the cursor) and the
		 * key in the interior node referencing the child block.
		 *
		 * fixes cases where entries have been shifted between
		 * child blocks but the parent hasn't been updated.  We
		 * don't have to worry about the key values in the cursor
		 * not being set since we only look at the key values of
		 * our child and those are guaranteed to be set by the
		 * call to scan_lbtree() above.
		 */
		if (check_dups == 0 && be64_to_cpu(pkey[i].br_startoff) !=
					bm_cursor->level[level-1].first_key)  {
			if (!no_modify)  {
				do_warn(
		_("correcting bt key (was %llu, now %llu) in inode %llu\n"
		  "\t\t%s fork, btree block %llu\n"),
					be64_to_cpu(pkey[i].br_startoff),
					bm_cursor->level[level-1].first_key,
					ino,
					forkname, bno);
				*dirty = 1;
				pkey[i].br_startoff = cpu_to_be64(
					bm_cursor->level[level-1].first_key);
			} else  {
				do_warn(
	_("bad btree key (is %llu, should be %llu) in inode %llu\n"
	  "\t\t%s fork, btree block %llu\n"),
					be64_to_cpu(pkey[i].br_startoff),
					bm_cursor->level[level-1].first_key,
					ino, forkname, bno);
			}
		}
	}

	/*
	 * If we're the last node at our level, check that the last child
	 * block's forward sibling pointer is NULL.
	 */
	if (check_dups == 0 &&
			bm_cursor->level[level].right_fsbno == NULLDFSBNO &&
			bm_cursor->level[level - 1].right_fsbno != NULLDFSBNO) {
		do_warn(
	_("bad fwd (right) sibling pointer (saw %llu should be NULLDFSBNO)\n"
	  "\tin inode %llu (%s fork) bmap btree block %llu\n"),
			bm_cursor->level[level - 1].right_fsbno,
			ino, forkname, bm_cursor->level[level - 1].fsbno);
		return(1);
	}

	/*
	 * update cursor keys to reflect this block
	 */
	if (check_dups == 0)  {
		bm_cursor->level[level].first_key =
				be64_to_cpu(pkey[0].br_startoff);
		bm_cursor->level[level].last_key =
				be64_to_cpu(pkey[numrecs - 1].br_startoff);
	}

	return(0);
}

void
scanfunc_allocbt(
	struct xfs_btree_block	*block,
	int			level,
	xfs_agblock_t		bno,
	xfs_agnumber_t		agno,
	int			suspect,
	int			isroot,
	__uint32_t		magic)
{
	const char 		*name;
	int			i;
	xfs_alloc_ptr_t		*pp;
	xfs_alloc_rec_t		*rp;
	int			hdr_errors = 0;
	int			numrecs;
	int			state;

	name = (magic == XFS_ABTB_MAGIC) ? "bno" : "cnt";

	if (be32_to_cpu(block->bb_magic) != magic) {
		do_warn(_("bad magic # %#x in bt%s block %d/%d\n"),
			be32_to_cpu(block->bb_magic), name, agno, bno);
		hdr_errors++;
		if (suspect)
			return;
	}
	if (be16_to_cpu(block->bb_level) != level) {
		do_warn(_("expected level %d got %d in bt%s block %d/%d\n"),
			level, be16_to_cpu(block->bb_level), name, agno, bno);
		hdr_errors++;
		if (suspect)
			return;
	}

	/*
	 * check for btree blocks multiply claimed
	 */
	state = get_bmap(agno, bno);
	switch (state != XR_E_UNKNOWN)  {
		set_bmap(agno, bno, XR_E_MULT);
		do_warn(
_("%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
				name, state, agno, bno, suspect);
		return;
	}
	set_bmap(agno, bno, XR_E_FS_MAP);

	numrecs = be16_to_cpu(block->bb_numrecs);

	if (level == 0) {

		if (numrecs > mp->m_alloc_mxr[0])  {
			numrecs = mp->m_alloc_mxr[0];
			hdr_errors++;
		}
		if (isroot == 0 && numrecs < mp->m_alloc_mnr[0])  {
			numrecs = mp->m_alloc_mnr[0];
			hdr_errors++;
		}

		if (hdr_errors)
			suspect++;

		rp = XFS_ALLOC_REC_ADDR(mp, block, 1);
		for (i = 0; i < numrecs; i++) {
			xfs_agblock_t		b, end;
			xfs_extlen_t		len, blen;

			b = be32_to_cpu(rp[i].ar_startblock);
			len = be32_to_cpu(rp[i].ar_blockcount);
			end = b + len;

			if (b == 0 || !verify_agbno(mp, agno, b))
				continue;
			if (len == 0 || len > MAXEXTLEN)
				continue;
			if (!verify_agbno(mp, agno, end - 1))
				continue;

			for ( ; b < end; b += blen)  {
				state = get_bmap_ext(agno, b, end, &blen);
				switch (state) {
				case XR_E_UNKNOWN:
					set_bmap(agno, b, XR_E_FREE1);
					break;
				case XR_E_FREE1:
					/*
					 * no warning messages -- we'll catch
					 * FREE1 blocks later
					 */
					if (magic != XFS_ABTB_MAGIC) {
						set_bmap_ext(agno, b, blen,
							     XR_E_FREE);
						break;
					}
				default:
					do_warn(
	_("block (%d,%d-%d) multiply claimed by %s space tree, state - %d\n"),
						agno, b, b + blen - 1,
						name, state);
					break;
				}
			}
		}
		return;
	}

	/*
	 * interior record
	 */
	pp = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]);

	if (numrecs > mp->m_alloc_mxr[1])  {
		numrecs = mp->m_alloc_mxr[1];
		hdr_errors++;
	}
	if (isroot == 0 && numrecs < mp->m_alloc_mnr[1])  {
		numrecs = mp->m_alloc_mnr[1];
		hdr_errors++;
	}

	/*
	 * don't pass bogus tree flag down further if this block
	 * looked ok.  bail out if two levels in a row look bad.
	 */

	if (suspect && !hdr_errors)
		suspect = 0;

	if (hdr_errors)  {
		if (suspect)
			return;
		else suspect++;
	}

	for (i = 0; i < numrecs; i++)  {
		xfs_agblock_t		bno = be32_to_cpu(pp[i]);

		/*
		 * XXX - put sibling detection right here.
		 * we know our sibling chain is good.  So as we go,
		 * we check the entry before and after each entry.
		 * If either of the entries references a different block,
		 * check the sibling pointer.  If there's a sibling
		 * pointer mismatch, try and extract as much data
		 * as possible.
		 */
		if (bno != 0 && verify_agbno(mp, agno, bno)) {
			scan_sbtree(bno, level, agno, suspect,
				    (magic == XFS_ABTB_MAGIC) ?
				     scanfunc_bno : scanfunc_cnt, 0);
		}
	}
}

void
scanfunc_bno(
	struct xfs_btree_block	*block,
	int			level,
	xfs_agblock_t		bno,
	xfs_agnumber_t		agno,
	int			suspect,
	int			isroot)
{
	return scanfunc_allocbt(block, level, bno, agno,
				suspect, isroot, XFS_ABTB_MAGIC);
}

void
scanfunc_cnt(
	struct xfs_btree_block	*block,
	int			level,
	xfs_agblock_t		bno,
	xfs_agnumber_t		agno,
	int			suspect,
	int			isroot
	)
{
	return scanfunc_allocbt(block, level, bno, agno,
				suspect, isroot, XFS_ABTC_MAGIC);
}

static int
scan_single_ino_chunk(
	xfs_agnumber_t		agno,
	xfs_inobt_rec_t		*rp,
	int			suspect)
{
	xfs_ino_t		lino;
	xfs_agino_t		ino;
	xfs_agblock_t		agbno;
	int			j;
	int			nfree;
	int			off;
	int			state;
	ino_tree_node_t		*ino_rec, *first_rec, *last_rec;

	ino = be32_to_cpu(rp->ir_startino);
	off = XFS_AGINO_TO_OFFSET(mp, ino);
	agbno = XFS_AGINO_TO_AGBNO(mp, ino);
	lino = XFS_AGINO_TO_INO(mp, agno, ino);

	/*
	 * on multi-block block chunks, all chunks start
	 * at the beginning of the block.  with multi-chunk
	 * blocks, all chunks must start on 64-inode boundaries
	 * since each block can hold N complete chunks. if
	 * fs has aligned inodes, all chunks must start
	 * at a fs_ino_alignment*N'th agbno.  skip recs
	 * with badly aligned starting inodes.
	 */
	if (ino == 0 ||
	    (inodes_per_block <= XFS_INODES_PER_CHUNK && off !=  0) ||
	    (inodes_per_block > XFS_INODES_PER_CHUNK &&
	     off % XFS_INODES_PER_CHUNK != 0) ||
	    (fs_aligned_inodes && agbno % fs_ino_alignment != 0))  {
		do_warn(
	_("badly aligned inode rec (starting inode = %llu)\n"),
			lino);
		suspect++;
	}

	/*
	 * verify numeric validity of inode chunk first
	 * before inserting into a tree.  don't have to
	 * worry about the overflow case because the
	 * starting ino number of a chunk can only get
	 * within 255 inodes of max (NULLAGINO).  if it
	 * gets closer, the agino number will be illegal
	 * as the agbno will be too large.
	 */
	if (verify_aginum(mp, agno, ino))  {
		do_warn(
_("bad starting inode # (%llu (0x%x 0x%x)) in ino rec, skipping rec\n"),
			lino, agno, ino);
		return ++suspect;
	}

	if (verify_aginum(mp, agno,
			ino + XFS_INODES_PER_CHUNK - 1))  {
		do_warn(
_("bad ending inode # (%llu (0x%x 0x%x)) in ino rec, skipping rec\n"),
			lino + XFS_INODES_PER_CHUNK - 1,
			agno, ino + XFS_INODES_PER_CHUNK - 1);
		return ++suspect;
	}

	/*
	 * set state of each block containing inodes
	 */
	if (off == 0 && !suspect)  {
		for (j = 0;
		     j < XFS_INODES_PER_CHUNK;
		     j += mp->m_sb.sb_inopblock)  {
			agbno = XFS_AGINO_TO_AGBNO(mp, ino + j);

			state = get_bmap(agno, agbno);
			if (state == XR_E_UNKNOWN)  {
				set_bmap(agno, agbno, XR_E_INO);
			} else if (state == XR_E_INUSE_FS && agno == 0 &&
				   ino + j >= first_prealloc_ino &&
				   ino + j < last_prealloc_ino)  {
				set_bmap(agno, agbno, XR_E_INO);
			} else  {
				do_warn(
_("inode chunk claims used block, inobt block - agno %d, bno %d, inopb %d\n"),
					agno, agbno,
				mp->m_sb.sb_inopblock);
				/*
				 * XXX - maybe should mark
				 * block a duplicate
				 */
				return ++suspect;
			}
		}
	}

	/*
	 * ensure only one avl entry per chunk
	 */
	find_inode_rec_range(agno, ino, ino + XFS_INODES_PER_CHUNK,
			     &first_rec, &last_rec);
	if (first_rec != NULL)  {
		/*
		 * this chunk overlaps with one (or more)
		 * already in the tree
		 */
		do_warn(
_("inode rec for ino %llu (%d/%d) overlaps existing rec (start %d/%d)\n"),
			lino, agno, ino, agno, first_rec->ino_startnum);
		suspect++;

		/*
		 * if the 2 chunks start at the same place,
		 * then we don't have to put this one
		 * in the uncertain list.  go to the next one.
		 */
		if (first_rec->ino_startnum == ino)
			return suspect;
	}

	nfree = 0;

	/*
	 * now mark all the inodes as existing and free or used.
	 * if the tree is suspect, put them into the uncertain
	 * inode tree.
	 */
	if (!suspect)  {
		if (XFS_INOBT_IS_FREE_DISK(rp, 0)) {
			nfree++;
			ino_rec = set_inode_free_alloc(agno, ino);
		} else  {
			ino_rec = set_inode_used_alloc(agno, ino);
		}
		for (j = 1; j < XFS_INODES_PER_CHUNK; j++) {
			if (XFS_INOBT_IS_FREE_DISK(rp, j)) {
				nfree++;
				set_inode_free(ino_rec, j);
			} else  {
				set_inode_used(ino_rec, j);
			}
		}
	} else  {
		for (j = 0; j < XFS_INODES_PER_CHUNK; j++) {
			if (XFS_INOBT_IS_FREE_DISK(rp, j)) {
				nfree++;
				add_aginode_uncertain(agno, ino + j, 1);
			} else  {
				add_aginode_uncertain(agno, ino + j, 0);
			}
		}
	}

	if (nfree != be32_to_cpu(rp->ir_freecount)) {
		do_warn(_("ir_freecount/free mismatch, inode "
			"chunk %d/%d, freecount %d nfree %d\n"),
			agno, ino, be32_to_cpu(rp->ir_freecount), nfree);
	}

	return suspect;
}


/*
 * this one walks the inode btrees sucking the info there into
 * the incore avl tree.  We try and rescue corrupted btree records
 * to minimize our chances of losing inodes.  Inode info from potentially
 * corrupt sources could be bogus so rather than put the info straight
 * into the tree, instead we put it on a list and try and verify the
 * info in the next phase by examining what's on disk.  At that point,
 * we'll be able to figure out what's what and stick the corrected info
 * into the tree.  We do bail out at some point and give up on a subtree
 * so as to avoid walking randomly all over the ag.
 *
 * Note that it's also ok if the free/inuse info wrong, we can correct
 * that when we examine the on-disk inode.  The important thing is to
 * get the start and alignment of the inode chunks right.  Those chunks
 * that we aren't sure about go into the uncertain list.
 */
void
scanfunc_ino(
	struct xfs_btree_block	*block,
	int			level,
	xfs_agblock_t		bno,
	xfs_agnumber_t		agno,
	int			suspect,
	int			isroot
	)
{
	int			i;
	int			numrecs;
	int			state;
	xfs_inobt_ptr_t		*pp;
	xfs_inobt_rec_t		*rp;
	int			hdr_errors;

	hdr_errors = 0;

	if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC) {
		do_warn(_("bad magic # %#x in inobt block %d/%d\n"),
			be32_to_cpu(block->bb_magic), agno, bno);
		hdr_errors++;
		bad_ino_btree = 1;
		if (suspect)
			return;
	}
	if (be16_to_cpu(block->bb_level) != level) {
		do_warn(_("expected level %d got %d in inobt block %d/%d\n"),
			level, be16_to_cpu(block->bb_level), agno, bno);
		hdr_errors++;
		bad_ino_btree = 1;
		if (suspect)
			return;
	}

	/*
	 * check for btree blocks multiply claimed, any unknown/free state
	 * is ok in the bitmap block.
	 */
	state = get_bmap(agno, bno);
	switch (state)  {
	case XR_E_UNKNOWN:
	case XR_E_FREE1:
	case XR_E_FREE:
		set_bmap(agno, bno, XR_E_FS_MAP);
		break;
	default:
		set_bmap(agno, bno, XR_E_MULT);
		do_warn(
_("inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
			state, agno, bno, suspect);
	}

	numrecs = be16_to_cpu(block->bb_numrecs);

	/*
	 * leaf record in btree
	 */
	if (level == 0) {
		/* check for trashed btree block */

		if (numrecs > mp->m_inobt_mxr[0])  {
			numrecs = mp->m_inobt_mxr[0];
			hdr_errors++;
		}
		if (isroot == 0 && numrecs < mp->m_inobt_mnr[0])  {
			numrecs = mp->m_inobt_mnr[0];
			hdr_errors++;
		}

		if (hdr_errors)  {
			bad_ino_btree = 1;
			do_warn(_("dubious inode btree block header %d/%d\n"),
				agno, bno);
			suspect++;
		}

		rp = XFS_INOBT_REC_ADDR(mp, block, 1);

		/*
		 * step through the records, each record points to
		 * a chunk of inodes.  The start of inode chunks should
		 * be block-aligned.  Each inode btree rec should point
		 * to the start of a block of inodes or the start of a group
		 * of INODES_PER_CHUNK (64) inodes.  off is the offset into
		 * the block.  skip processing of bogus records.
		 */
		for (i = 0; i < numrecs; i++)
			suspect = scan_single_ino_chunk(agno, &rp[i], suspect);

		if (suspect)
			bad_ino_btree = 1;

		return;
	}

	/*
	 * interior record, continue on
	 */
	if (numrecs > mp->m_inobt_mxr[1])  {
		numrecs = mp->m_inobt_mxr[1];
		hdr_errors++;
	}
	if (isroot == 0 && numrecs < mp->m_inobt_mnr[1])  {
		numrecs = mp->m_inobt_mnr[1];
		hdr_errors++;
	}

	pp = XFS_INOBT_PTR_ADDR(mp, block, 1, mp->m_inobt_mxr[1]);

	/*
	 * don't pass bogus tree flag down further if this block
	 * looked ok.  bail out if two levels in a row look bad.
	 */

	if (suspect && !hdr_errors)
		suspect = 0;

	if (hdr_errors)  {
		bad_ino_btree = 1;
		if (suspect)
			return;
		else suspect++;
	}

	for (i = 0; i < numrecs; i++)  {
		if (be32_to_cpu(pp[i]) != 0 && verify_agbno(mp, agno,
							be32_to_cpu(pp[i])))
			scan_sbtree(be32_to_cpu(pp[i]), level, agno,
					suspect, scanfunc_ino, 0);
	}
}

void
scan_freelist(
	xfs_agf_t	*agf)
{
	xfs_agfl_t	*agfl;
	xfs_buf_t	*agflbuf;
	xfs_agnumber_t	agno;
	xfs_agblock_t	bno;
	int		count;
	int		i;

	agno = be32_to_cpu(agf->agf_seqno);

	if (XFS_SB_BLOCK(mp) != XFS_AGFL_BLOCK(mp) &&
	    XFS_AGF_BLOCK(mp) != XFS_AGFL_BLOCK(mp) &&
	    XFS_AGI_BLOCK(mp) != XFS_AGFL_BLOCK(mp))
		set_bmap(agno, XFS_AGFL_BLOCK(mp), XR_E_FS_MAP);

	if (be32_to_cpu(agf->agf_flcount) == 0)
		return;

	agflbuf = libxfs_readbuf(mp->m_dev,
				 XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
				 XFS_FSS_TO_BB(mp, 1), 0);
	if (!agflbuf)  {
		do_abort(_("can't read agfl block for ag %d\n"), agno);
		return;
	}
	agfl = XFS_BUF_TO_AGFL(agflbuf);
	i = be32_to_cpu(agf->agf_flfirst);
	count = 0;
	for (;;) {
		bno = be32_to_cpu(agfl->agfl_bno[i]);
		if (verify_agbno(mp, agno, bno))
			set_bmap(agno, bno, XR_E_FREE);
		else
			do_warn(_("bad agbno %u in agfl, agno %d\n"),
				bno, agno);
		count++;
		if (i == be32_to_cpu(agf->agf_fllast))
			break;
		if (++i == XFS_AGFL_SIZE(mp))
			i = 0;
	}
	if (count != be32_to_cpu(agf->agf_flcount)) {
		do_warn(_("freeblk count %d != flcount %d in ag %d\n"), count,
			be32_to_cpu(agf->agf_flcount), agno);
	}
	libxfs_putbuf(agflbuf);
}

void
scan_ag(
	xfs_agnumber_t	agno)
{
	xfs_agf_t	*agf;
	xfs_buf_t	*agfbuf;
	int		agf_dirty;
	xfs_agi_t	*agi;
	xfs_buf_t	*agibuf;
	int		agi_dirty;
	xfs_sb_t	*sb;
	xfs_buf_t	*sbbuf;
	int		sb_dirty;
	int		status;

	agi_dirty = agf_dirty = sb_dirty = 0;

	sbbuf = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_SB_DADDR),
				XFS_FSS_TO_BB(mp, 1), 0);
	if (!sbbuf)  {
		do_error(_("can't get root superblock for ag %d\n"), agno);
		return;
	}

	sb = (xfs_sb_t *)calloc(BBSIZE, 1);
	if (!sb) {
		do_error(_("can't allocate memory for superblock\n"));
		libxfs_putbuf(sbbuf);
		return;
	}
	libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbbuf));

	agfbuf = libxfs_readbuf(mp->m_dev,
			XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
			XFS_FSS_TO_BB(mp, 1), 0);
	if (!agfbuf)  {
		do_error(_("can't read agf block for ag %d\n"), agno);
		libxfs_putbuf(sbbuf);
		free(sb);
		return;
	}
	agf = XFS_BUF_TO_AGF(agfbuf);

	agibuf = libxfs_readbuf(mp->m_dev,
			XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
			XFS_FSS_TO_BB(mp, 1), 0);
	if (!agibuf)  {
		do_error(_("can't read agi block for ag %d\n"), agno);
		libxfs_putbuf(agfbuf);
		libxfs_putbuf(sbbuf);
		free(sb);
		return;
	}
	agi = XFS_BUF_TO_AGI(agibuf);

	/* fix up bad ag headers */

	status = verify_set_agheader(mp, sbbuf, sb, agf, agi, agno);

	if (status & XR_AG_SB_SEC)  {
		if (!no_modify)
			sb_dirty = 1;
		/*
		 * clear bad sector bit because we don't want
		 * to skip further processing.  we just want to
		 * ensure that we write out the modified sb buffer.
		 */
		status &= ~XR_AG_SB_SEC;
	}
	if (status & XR_AG_SB)  {
		if (!no_modify) {
			do_warn(_("reset bad sb for ag %d\n"), agno);
			sb_dirty = 1;
		} else {
			do_warn(_("would reset bad sb for ag %d\n"), agno);
		}
	}
	if (status & XR_AG_AGF)  {
		if (!no_modify) {
			do_warn(_("reset bad agf for ag %d\n"), agno);
			agf_dirty = 1;
		} else {
			do_warn(_("would reset bad agf for ag %d\n"), agno);
		}
	}
	if (status & XR_AG_AGI)  {
		if (!no_modify) {
			do_warn(_("reset bad agi for ag %d\n"), agno);
			agi_dirty = 1;
		} else {
			do_warn(_("would reset bad agi for ag %d\n"), agno);
		}
	}

	if (status && no_modify)  {
		libxfs_putbuf(agibuf);
		libxfs_putbuf(agfbuf);
		libxfs_putbuf(sbbuf);
		free(sb);

		do_warn(_("bad uncorrected agheader %d, skipping ag...\n"),
			agno);

		return;
	}

	scan_freelist(agf);

	if (be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]) != 0 && verify_agbno(mp,
			agno, be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO])))
		scan_sbtree(be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]),
				be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]),
				agno, 0, scanfunc_bno, 1);
	else
		do_warn(_("bad agbno %u for btbno root, agno %d\n"),
			be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]),
			agno);

	if (be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]) != 0 && verify_agbno(mp,
			agno, be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT])))
		scan_sbtree(be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]),
				be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]),
				agno, 0, scanfunc_cnt, 1);
	else
		do_warn(_("bad agbno %u for btbcnt root, agno %d\n"),
			be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]),
			agno);

	if (be32_to_cpu(agi->agi_root) != 0 && verify_agbno(mp, agno,
						be32_to_cpu(agi->agi_root)))
		scan_sbtree(be32_to_cpu(agi->agi_root),
			be32_to_cpu(agi->agi_level), agno, 0, scanfunc_ino, 1);
	else
		do_warn(_("bad agbno %u for inobt root, agno %d\n"),
			be32_to_cpu(agi->agi_root), agno);

	ASSERT(agi_dirty == 0 || (agi_dirty && !no_modify));

	if (agi_dirty && !no_modify)
		libxfs_writebuf(agibuf, 0);
	else
		libxfs_putbuf(agibuf);

	ASSERT(agf_dirty == 0 || (agf_dirty && !no_modify));

	if (agf_dirty && !no_modify)
		libxfs_writebuf(agfbuf, 0);
	else
		libxfs_putbuf(agfbuf);

	ASSERT(sb_dirty == 0 || (sb_dirty && !no_modify));

	if (sb_dirty && !no_modify) {
		if (agno == 0)
			memcpy(&mp->m_sb, sb, sizeof(xfs_sb_t));
		libxfs_sb_to_disk(XFS_BUF_TO_SBP(sbbuf), sb, XFS_SB_ALL_BITS);
		libxfs_writebuf(sbbuf, 0);
	} else
		libxfs_putbuf(sbbuf);
	free(sb);
	PROG_RPT_INC(prog_rpt_done[agno], 1);
}
