]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_repair: check plausibility of root dir pointer before trashing it
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 27 Feb 2020 20:05:47 +0000 (15:05 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Thu, 27 Feb 2020 20:05:47 +0000 (15:05 -0500)
If sb_rootino doesn't point to where we think mkfs should have allocated
the root directory, check to see if the alleged root directory actually
looks like a root directory.  If so, we'll let it live because someone
could have changed sunit since formatting time, and that changes the
root directory inode estimate.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
repair/xfs_repair.c

index 111306fe0e5dd9fdd75d1b7d6b87f05f407aa637..b34d41d48ad764e7f7a91dca989b0c38d2d8c380 100644 (file)
@@ -426,6 +426,37 @@ _("would reset superblock %s inode pointer to %"PRIu64"\n"),
        *ino = expected_ino;
 }
 
+/* Does the root directory inode look like a plausible root directory? */
+static bool
+has_plausible_rootdir(
+       struct xfs_mount        *mp)
+{
+       struct xfs_inode        *ip;
+       xfs_ino_t               ino;
+       int                     error;
+       bool                    ret = false;
+
+       error = -libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &ip,
+                       &xfs_default_ifork_ops);
+       if (error)
+               goto out;
+       if (!S_ISDIR(VFS_I(ip)->i_mode))
+               goto out_rele;
+
+       error = -libxfs_dir_lookup(NULL, ip, &xfs_name_dotdot, &ino, NULL);
+       if (error)
+               goto out_rele;
+
+       /* The root directory '..' entry points to the directory. */
+       if (ino == mp->m_sb.sb_rootino)
+               ret = true;
+
+out_rele:
+       libxfs_irele(ip);
+out:
+       return ret;
+}
+
 /*
  * Make sure that the first 3 inodes in the filesystem are the root directory,
  * the realtime bitmap, and the realtime summary, in that order.
@@ -438,6 +469,20 @@ calc_mkfs(
 
        rootino = libxfs_ialloc_calc_rootino(mp, mp->m_sb.sb_unit);
 
+       /*
+        * If the root inode isn't where we think it is, check its plausibility
+        * as a root directory.  It's possible that somebody changed sunit
+        * since the filesystem was created, which can change the value of the
+        * above computation.  Don't blow up the root directory if this is the
+        * case.
+        */
+       if (mp->m_sb.sb_rootino != rootino && has_plausible_rootdir(mp)) {
+               do_warn(
+_("sb root inode value %" PRIu64 " valid but in unaligned location (expected %"PRIu64") possibly due to sunit change\n"),
+                       mp->m_sb.sb_rootino, rootino);
+               rootino = mp->m_sb.sb_rootino;
+       }
+
        validate_sb_ino(&mp->m_sb.sb_rootino, rootino,
                        _("root"));
        validate_sb_ino(&mp->m_sb.sb_rbmino, rootino + 1,