]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: rebuild directory when non-root leafn blocks claim block 0
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 12 Dec 2018 17:42:40 +0000 (11:42 -0600)
committerEric Sandeen <sandeen@redhat.com>
Wed, 12 Dec 2018 17:42:40 +0000 (11:42 -0600)
As explained in

71a6af8 Revert "xfs_repair: treat zero da btree pointers as corruption"

a single root LEAFN block can exist in a directory until it grows
further.

This is why, normally, we skip directories with a root marked
XFS_DIR2_LEAFN_MAGIC, as detected by the left-most leaf block being
found at file block 0.

However, if we traversed any level of a btree to get here (as
indicated by da_cursor.active > 0), then a leaf block claiming block
0 indicates corruption, and we should handle it as such, and rebuild
the directory.

This was found by repair repeatedly rebuilding a directory containing a
single leafn block (xfs/495).

Fixes: 67a79e2cc932 ("xfs_repair: treat zero da btree pointers as corruption")
Reported-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
[sandeen: clarify commit log, refer to revert commit]
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
repair/dir2.c

index ba5763ed3d26878ee8a93eb69a60bdd7af163d68..e67ec590c0917698fcab4df412b52cba13a6505f 100644 (file)
@@ -1243,10 +1243,21 @@ process_node_dir2(
 
        /*
         * Skip directories with a root marked XFS_DIR2_LEAFN_MAGIC
+        *
+        * Be careful here: If any level of the da cursor was filled out then
+        * the directory has a da btree containing an invalid before pointer to
+        * dblock 0, and we should move on to rebuilding the directory.  If no
+        * levels in the da cursor got filled out, then we just have a single
+        * leafn block and we're done.
         */
        if (bno == 0) {
-               release_da_cursor(mp, &da_cursor, 0);
-               return 0;
+               if (da_cursor.active > 0) {
+                       err_release_da_cursor(mp, &da_cursor, 0);
+                       return 1;
+               } else {
+                       release_da_cursor(mp, &da_cursor, 0);
+                       return 0;
+               }
        } else {
                /*
                 * Now pass cursor and bno into leaf-block processing routine.