All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] xfs_repair: fix process_leaf_node_dir2() for fragmented multiblock dirs
@ 2012-05-02 19:40 Eric Sandeen
  0 siblings, 0 replies; only message in thread
From: Eric Sandeen @ 2012-05-02 19:40 UTC (permalink / raw)
  To: xfs-oss

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@redhat.com>
---

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@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2012-05-02 19:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-02 19:40 [PATCH] xfs_repair: fix process_leaf_node_dir2() for fragmented multiblock dirs Eric Sandeen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.