]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: don't dirty inodes unconditionally when testing unlinked state
authorDave Chinner <dchinner@redhat.com>
Tue, 30 Oct 2018 23:24:08 +0000 (18:24 -0500)
committerEric Sandeen <sandeen@redhat.com>
Tue, 30 Oct 2018 23:24:08 +0000 (18:24 -0500)
I noticed phase 4 writing back lots of inode buffers during recent
testing. The recent rework of clear_inode() in commit 0724d0f4cb53
("xfs_repair: clear_dinode should simply clear, not check contents")
accidentally caught a call to clear_inode_unlinked() as well,
resulting in all inodes being marked dirty whether then needed
updating or not.

Fix it by making clear_inode_unlinked unconditionally do the clear
(as was done for clear_inode), and move the test to the caller.
Add warnings as well so that this corruption is no longer silently
fixed.

Fixes: 0724d0f ("xfs_repair: clear_dinode should simply clear, ...")
Signed-off-by: Dave Chinner <dchinner@redhat.com>
[sandeen: rework so clear_inode_unlinked is unconditional]
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
repair/dinode.c

index 379f85cf1268e940e9fc00640a2354d80c10c90b..f466e7784206b7e19ea62b742cb169bfe0ec5fdb 100644 (file)
@@ -125,23 +125,16 @@ clear_dinode_core(struct xfs_mount *mp, xfs_dinode_t *dinoc, xfs_ino_t ino_num)
        return;
 }
 
-static int
+static void
 clear_dinode_unlinked(xfs_mount_t *mp, xfs_dinode_t *dino)
 {
 
-       if (be32_to_cpu(dino->di_next_unlinked) != NULLAGINO)  {
-               if (!no_modify)
-                       dino->di_next_unlinked = cpu_to_be32(NULLAGINO);
-               return(1);
-       }
-
-       return(0);
+       dino->di_next_unlinked = cpu_to_be32(NULLAGINO);
 }
 
 /*
  * this clears the unlinked list too so it should not be called
  * until after the agi unlinked lists are walked in phase 3.
- * returns > zero if the inode has been altered while being cleared
  */
 static void
 clear_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num)
@@ -2675,9 +2668,16 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
         * we're going to find.  check_dups is set to 1 only during
         * phase 4.  Ugly.
         */
-       if (check_dups && !no_modify) {
-               clear_dinode_unlinked(mp, dino);
-               *dirty += 1;
+       if (check_dups && be32_to_cpu(dino->di_next_unlinked) != NULLAGINO) {
+               if (no_modify) {
+                       do_warn(
+       _("Would clear next_unlinked in inode %" PRIu64 "\n"), lino);
+               } else  {
+                       clear_dinode_unlinked(mp, dino);
+                       do_warn(
+       _("Cleared next_unlinked in inode %" PRIu64 "\n"), lino);
+                       *dirty += 1;
+               }
        }
 
        /* set type and map type info */