]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - repair/dir2.c
xfs_repair: rebuild directory when non-root leafn blocks claim block 0
[thirdparty/xfsprogs-dev.git] / repair / dir2.c
index e162d2b8e3856fa273e0d148e3c21ea025c7c6c4..e67ec590c0917698fcab4df412b52cba13a6505f 100644 (file)
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include "libxfs.h"
@@ -495,8 +483,10 @@ _("corrected entry offsets in directory %" PRIu64 "\n"),
 
        /*
         * if parent entry is bogus, null it out.  we'll fix it later .
+        * If the validation fails for the root inode we fix it in
+        * the next else case.
         */
-       if (verify_inum(mp, *parent))  {
+       if (verify_inum(mp, *parent) && ino != mp->m_sb.sb_rootino)  {
 
                do_warn(
 _("bogus .. inode number (%" PRIu64 ") in directory inode %" PRIu64 ", "),
@@ -1252,11 +1242,22 @@ process_node_dir2(
                return 1;
 
        /*
-        * Directories with a root marked XFS_DIR2_LEAFN_MAGIC are corrupt
+        * 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) {
-               err_release_da_cursor(mp, &da_cursor, 0);
-               return 1;
+               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.