Consider a filesystem with 4k fs blocks and 16k dir blocks, with extremely fragmented freespace so that a 2 block (32k) directory ends up with these extents, covering 2 multiblock dir blocks: index: phys len ----------------- 0 10 1 1 12 1 2 14 1 3 16 1 ----------------- 4 18 1 5 20 1 6 22 1 7 24 1 The loop in process_leaf_node_dir2() would obtain the first 4 just fine: ----------------- 0 10 1 1 12 1 2 14 1 3 16 1 ----------------- But then although it advanced ndbno (next block nr) by an amount relative to mp->m_dirfsbs, it left "t" (the starting extent number for the search) untouched. blkmap_next_off() is really designed to be iterated block by block, as far as I can tell, and if you pass in a block nr which is at an offset beyond that when extent "t" covers, it will simply return you the first logical block in extent "t". So, we advanced the requested block nr by 4, but left t untouched at 1, and at the top of the loop next time, we get this for the next 16k "dir block:" 1 12 1 2 14 1 3 16 1 ----------------- 4 18 1 This isn't properly aligned with the dir block; the magic for the next dir block is in phys block 18, not 12, so repair thinks things are corrupted and it gets worse from there. To fix this, just call blkmap_next_off() a few more times in a loop until we reach the last fs block in our dir block. Then the outer loop will find the next block after THAT, and process the next multiblock dir block properly. Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx> --- diff --git a/repair/dir2.c b/repair/dir2.c index f9562d7..7a614a8 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -2003,7 +2003,11 @@ process_leaf_node_dir2( ndbno = NULLDFILOFF; while ((dbno = blkmap_next_off(blkmap, ndbno, &t)) < mp->m_dirleafblk) { nex = blkmap_getn(blkmap, dbno, mp->m_dirblkfsbs, &bmp, &lbmp); - ndbno = dbno + mp->m_dirblkfsbs - 1; + /* Advance through map to last fs block in this dir block */ + ndbno = dbno; + while (ndbno < dbno + mp->m_dirblkfsbs - 1) { + ndbno = blkmap_next_off(blkmap, ndbno, &t); + } if (nex == 0) { do_warn( _("block %" PRIu64 " for directory inode %" PRIu64 " is missing\n"), _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs