From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> In rmap_store_ag_btree_rec(), we try to reserve 16 blocks to handle adding all the AG btree rmaps to the rmap record. Unfortunately, at that point in phase5 we haven't yet reinitialied sb_fdblocks, so reserving blocks can fail if repair reconstructed the primary sb from a secondary sb. Even if the function succeeds, this still leads to incorrect fdblocks because phase 5 resets sb_fdblocks after running the rmap transactions. To avoid all this, move the rmap_store_ag_btree_rec call to after the sb has been reset. xfs/350 was helpful in finding cases where xfs_repair errored out while repairing the filesystem. Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --- repair/phase5.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/repair/phase5.c b/repair/phase5.c index 2e18cc69..7f7d3d18 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -2233,7 +2233,6 @@ phase5_func( #endif xfs_agblock_t num_extents; struct agi_stat agi_stat = {0,}; - int error; if (verbose) do_log(_(" - agno = %d\n"), agno); @@ -2426,14 +2425,6 @@ phase5_func( finish_cursor(&fino_btree_curs); finish_cursor(&bcnt_btree_curs); - /* - * Put the per-AG btree rmap data into the rmapbt - */ - error = rmap_store_ag_btree_rec(mp, agno); - if (error) - do_error( -_("unable to add AG %u reverse-mapping data to btree.\n"), agno); - /* * release the incore per-AG bno/bcnt trees so * the extent nodes can be recycled @@ -2561,6 +2552,21 @@ phase5(xfs_mount_t *mp) */ sync_sb(mp); + /* + * Put the per-AG btree rmap data into the rmapbt now that we've reset + * the superblock counters. + */ + for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { + error = rmap_store_ag_btree_rec(mp, agno); + if (error) + do_error( +_("unable to add AG %u reverse-mapping data to btree.\n"), agno); + } + + /* + * Put blocks that were unnecessarily reserved for btree + * reconstruction back into the filesystem free space data. + */ error = inject_lost_blocks(mp, lost_fsb); if (error) do_error(_("Unable to reinsert lost blocks into filesystem.\n"));