Ejemplo n.º 1
0
void
phase3(xfs_mount_t *mp)
{
	int 			i, j;

	do_log(_("Phase 3 - for each AG...\n"));
	if (!no_modify)
		do_log(_("        - scan and clear agi unlinked lists...\n"));
	else
		do_log(_("        - scan (but don't clear) agi unlinked lists...\n"));

	set_progress_msg(PROG_FMT_AGI_UNLINKED, (__uint64_t) glob_agcount);

	/* first clear the agi unlinked AGI list */
	if (!no_modify) {
		for (i = 0; i < mp->m_sb.sb_agcount; i++)
			process_agi_unlinked(mp, i);
	}

	/* now look at possibly bogus inodes */
	for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
		check_uncertain_aginodes(mp, i);
		PROG_RPT_INC(prog_rpt_done[i], 1);
	}
	print_final_rpt();

	/* ok, now that the tree's ok, let's take a good look */

	do_log(_(
	    "        - process known inodes and perform inode discovery...\n"));

	set_progress_msg(PROG_FMT_PROCESS_INO, (__uint64_t) mp->m_sb.sb_icount);

	process_ags(mp);

	print_final_rpt();

	/*
	 * process newly discovered inode chunks
	 */
	do_log(_("        - process newly discovered inodes...\n"));
	set_progress_msg(PROG_FMT_NEW_INODES, (__uint64_t) glob_agcount);
	do  {
		/*
		 * have to loop until no ag has any uncertain
		 * inodes
		 */
		j = 0;
		for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
			j += process_uncertain_aginodes(mp, i);
#ifdef XR_INODE_TRACE
			fprintf(stderr,
				"\t\t phase 3 - process_uncertain_inodes returns %d\n", j);
#endif
			PROG_RPT_INC(prog_rpt_done[i], 1);
		}
	} while (j != 0);
	print_final_rpt();
}
Ejemplo n.º 2
0
static void
do_uncertain_aginodes(
	work_queue_t	*wq,
	xfs_agnumber_t	agno,
	void		*arg)
{
	int		*count = arg;

	*count = process_uncertain_aginodes(wq->mp, agno);

#ifdef XR_INODE_TRACE
	fprintf(stderr,
		"\t\t phase 3 - ag %d process_uncertain_inodes returns %d\n",
		*count, j);
#endif

	PROG_RPT_INC(prog_rpt_done[agno], 1);
}
Ejemplo n.º 3
0
void
phase3(
	struct xfs_mount *mp,
	int		scan_threads)
{
	int			i, j;
	int			*counts;
	work_queue_t		wq;

	do_log(_("Phase 3 - for each AG...\n"));
	if (!no_modify)
		do_log(_("        - scan and clear agi unlinked lists...\n"));
	else
		do_log(_("        - scan (but don't clear) agi unlinked lists...\n"));

	set_progress_msg(PROG_FMT_AGI_UNLINKED, (__uint64_t) glob_agcount);

	/* first clear the agi unlinked AGI list */
	if (!no_modify) {
		for (i = 0; i < mp->m_sb.sb_agcount; i++)
			process_agi_unlinked(mp, i);
	}

	/* now look at possibly bogus inodes */
	for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
		check_uncertain_aginodes(mp, i);
		PROG_RPT_INC(prog_rpt_done[i], 1);
	}
	print_final_rpt();

	/* ok, now that the tree's ok, let's take a good look */

	do_log(_(
	    "        - process known inodes and perform inode discovery...\n"));

	set_progress_msg(PROG_FMT_PROCESS_INO, (__uint64_t) mp->m_sb.sb_icount);

	process_ags(mp);

	print_final_rpt();

	/*
	 * process newly discovered inode chunks
	 */
	do_log(_("        - process newly discovered inodes...\n"));
	set_progress_msg(PROG_FMT_NEW_INODES, (__uint64_t) glob_agcount);

	counts = calloc(sizeof(*counts), mp->m_sb.sb_agcount);
	if (!counts) {
		do_abort(_("no memory for uncertain inode counts\n"));
		return;
	}

	do  {
		/*
		 * have to loop until no ag has any uncertain
		 * inodes
		 */
		j = 0;
		memset(counts, 0, mp->m_sb.sb_agcount * sizeof(*counts));

		create_work_queue(&wq, mp, scan_threads);

		for (i = 0; i < mp->m_sb.sb_agcount; i++)
			queue_work(&wq, do_uncertain_aginodes, i, &counts[i]);

		destroy_work_queue(&wq);

		/* tally up the counts */
		for (i = 0; i < mp->m_sb.sb_agcount; i++)
			j += counts[i];

	} while (j != 0);

	free(counts);

	print_final_rpt();
}
Ejemplo n.º 4
0
static void
phase5_func(
	xfs_mount_t	*mp,
	xfs_agnumber_t	agno)
{
	__uint64_t	num_inos;
	__uint64_t	num_free_inos;
	__uint64_t	finobt_num_inos;
	__uint64_t	finobt_num_free_inos;
	bt_status_t	bno_btree_curs;
	bt_status_t	bcnt_btree_curs;
	bt_status_t	ino_btree_curs;
	bt_status_t	fino_btree_curs;
	int		extra_blocks = 0;
	uint		num_freeblocks;
	xfs_extlen_t	freeblks1;
#ifdef DEBUG
	xfs_extlen_t	freeblks2;
#endif
	xfs_agblock_t	num_extents;
	__uint32_t	magic;
	struct agi_stat	agi_stat = {0,};

	if (verbose)
		do_log(_("        - agno = %d\n"), agno);

	{
		/*
		 * build up incore bno and bcnt extent btrees
		 */
		num_extents = mk_incore_fstree(mp, agno);

#ifdef XR_BLD_FREE_TRACE
		fprintf(stderr, "# of bno extents is %d\n",
				count_bno_extents(agno));
#endif

		if (num_extents == 0)  {
			/*
			 * XXX - what we probably should do here is pick an
			 * inode for a regular file in the allocation group
			 * that has space allocated and shoot it by traversing
			 * the bmap list and putting all its extents on the
			 * incore freespace trees, clearing the inode,
			 * and clearing the in-use bit in the incore inode
			 * tree.  Then try mk_incore_fstree() again.
			 */
			do_error(_("unable to rebuild AG %u.  "
				  "Not enough free space in on-disk AG.\n"),
				agno);
		}

		/*
		 * ok, now set up the btree cursors for the
		 * on-disk btrees (includs pre-allocating all
		 * required blocks for the trees themselves)
		 */
		init_ino_cursor(mp, agno, &ino_btree_curs, &num_inos,
				&num_free_inos, 0);

		if (xfs_sb_version_hasfinobt(&mp->m_sb))
			init_ino_cursor(mp, agno, &fino_btree_curs,
					&finobt_num_inos, &finobt_num_free_inos,
					1);

		sb_icount_ag[agno] += num_inos;
		sb_ifree_ag[agno] += num_free_inos;

		num_extents = count_bno_extents_blocks(agno, &num_freeblocks);
		/*
		 * lose two blocks per AG -- the space tree roots
		 * are counted as allocated since the space trees
		 * always have roots
		 */
		sb_fdblocks_ag[agno] += num_freeblocks - 2;

		if (num_extents == 0)  {
			/*
			 * XXX - what we probably should do here is pick an
			 * inode for a regular file in the allocation group
			 * that has space allocated and shoot it by traversing
			 * the bmap list and putting all its extents on the
			 * incore freespace trees, clearing the inode,
			 * and clearing the in-use bit in the incore inode
			 * tree.  Then try mk_incore_fstree() again.
			 */
			do_error(
			_("unable to rebuild AG %u.  No free space.\n"), agno);
		}

#ifdef XR_BLD_FREE_TRACE
		fprintf(stderr, "# of bno extents is %d\n", num_extents);
#endif

		/*
		 * track blocks that we might really lose
		 */
		extra_blocks = calculate_freespace_cursor(mp, agno,
					&num_extents, &bno_btree_curs);

		/*
		 * freespace btrees live in the "free space" but
		 * the filesystem treats AGFL blocks as allocated
		 * since they aren't described by the freespace trees
		 */

		/*
		 * see if we can fit all the extra blocks into the AGFL
		 */
		extra_blocks = (extra_blocks - XFS_AGFL_SIZE(mp) > 0)
				? extra_blocks - XFS_AGFL_SIZE(mp)
				: 0;

		if (extra_blocks > 0)  {
			do_warn(_("lost %d blocks in agno %d, sorry.\n"),
				extra_blocks, agno);
			sb_fdblocks_ag[agno] -= extra_blocks;
		}

		bcnt_btree_curs = bno_btree_curs;

		setup_cursor(mp, agno, &bno_btree_curs);
		setup_cursor(mp, agno, &bcnt_btree_curs);

#ifdef XR_BLD_FREE_TRACE
		fprintf(stderr, "# of bno extents is %d\n",
				count_bno_extents(agno));
		fprintf(stderr, "# of bcnt extents is %d\n",
				count_bcnt_extents(agno));
#endif

		/*
		 * now rebuild the freespace trees
		 */
		freeblks1 = build_freespace_tree(mp, agno,
					&bno_btree_curs, XFS_ABTB_MAGIC);
#ifdef XR_BLD_FREE_TRACE
		fprintf(stderr, "# of free blocks == %d\n", freeblks1);
#endif
		write_cursor(&bno_btree_curs);

#ifdef DEBUG
		freeblks2 = build_freespace_tree(mp, agno,
					&bcnt_btree_curs, XFS_ABTC_MAGIC);
#else
		(void) build_freespace_tree(mp, agno,
					&bcnt_btree_curs, XFS_ABTC_MAGIC);
#endif
		write_cursor(&bcnt_btree_curs);

		ASSERT(freeblks1 == freeblks2);

		/*
		 * set up agf and agfl
		 */
		build_agf_agfl(mp, agno, &bno_btree_curs,
				&bcnt_btree_curs, freeblks1, extra_blocks);
		/*
		 * build inode allocation tree.
		 */
		magic = xfs_sb_version_hascrc(&mp->m_sb) ?
				XFS_IBT_CRC_MAGIC : XFS_IBT_MAGIC;
		build_ino_tree(mp, agno, &ino_btree_curs, magic, &agi_stat, 0);
		write_cursor(&ino_btree_curs);

		/*
		 * build free inode tree
		 */
		if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
			magic = xfs_sb_version_hascrc(&mp->m_sb) ?
					XFS_FIBT_CRC_MAGIC : XFS_FIBT_MAGIC;
			build_ino_tree(mp, agno, &fino_btree_curs, magic,
					NULL, 1);
			write_cursor(&fino_btree_curs);
		}

		/* build the agi */
		build_agi(mp, agno, &ino_btree_curs, &fino_btree_curs,
			  &agi_stat);

		/*
		 * tear down cursors
		 */
		finish_cursor(&bno_btree_curs);
		finish_cursor(&ino_btree_curs);
		if (xfs_sb_version_hasfinobt(&mp->m_sb))
			finish_cursor(&fino_btree_curs);
		finish_cursor(&bcnt_btree_curs);
		/*
		 * release the incore per-AG bno/bcnt trees so
		 * the extent nodes can be recycled
		 */
		release_agbno_extent_tree(agno);
		release_agbcnt_extent_tree(agno);
	}
	PROG_RPT_INC(prog_rpt_done[agno], 1);
}