]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: clear the needsrepair flag
authorDarrick J. Wong <djwong@kernel.org>
Wed, 24 Feb 2021 00:09:28 +0000 (19:09 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Wed, 24 Feb 2021 00:09:28 +0000 (19:09 -0500)
Clear the needsrepair flag, since it's used to prevent mounting of an
inconsistent filesystem.  We only do this if we make it to the end of
repair with a non-zero error code, and all the rebuilt indices and
corrected metadata are persisted correctly.

Note that we cannot combine clearing needsrepair with clearing the quota
checked flags because we need to clear the quota flags even if
reformatting the log fails, whereas we can't clear needsrepair if the
log reformat fails.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
include/xfs_mount.h
libxfs/init.c
repair/agheader.c
repair/xfs_repair.c

index 36594643862045cd97cf7d09662dd20737afbca2..75230ca56ab420ca6df17fc2f21f3dc2474bb828 100644 (file)
@@ -181,6 +181,7 @@ xfs_perag_resv(
 
 extern xfs_mount_t     *libxfs_mount (xfs_mount_t *, xfs_sb_t *,
                                dev_t, dev_t, dev_t, int);
+int libxfs_flush_mount(struct xfs_mount *mp);
 int            libxfs_umount(struct xfs_mount *mp);
 extern void    libxfs_rtmount_destroy (xfs_mount_t *);
 
index 9fe13b8d9d55018c2271889b1ddb5be3e9738801..8a8ce3c4b7fd38b582dece040ed62a7c4239d9ad 100644 (file)
@@ -870,7 +870,7 @@ _("%s: Flushing the %s failed, err=%d!\n"),
  * Flush all dirty buffers to stable storage and report on writes that didn't
  * make it to stable storage.
  */
-static int
+int
 libxfs_flush_mount(
        struct xfs_mount        *mp)
 {
@@ -878,13 +878,13 @@ libxfs_flush_mount(
        int                     err2;
 
        /*
-        * Purge the buffer cache to write all dirty buffers to disk and free
-        * all incore buffers.  Buffers that fail write verification will cause
-        * the CORRUPT_WRITE flag to be set in the buftarg.  Buffers that
-        * cannot be written will cause the LOST_WRITE flag to be set in the
-        * buftarg.
+        * Flush the buffer cache to write all dirty buffers to disk.  Buffers
+        * that fail write verification will cause the CORRUPT_WRITE flag to be
+        * set in the buftarg.  Buffers that cannot be written will cause the
+        * LOST_WRITE flag to be set in the buftarg.  Once that's done,
+        * instruct the disks to persist their write caches.
         */
-       libxfs_bcache_purge();
+       libxfs_bcache_flush();
 
        /* Flush all kernel and disk write caches, and report failures. */
        if (mp->m_ddev_targp) {
@@ -923,6 +923,12 @@ libxfs_umount(
 
        libxfs_rtmount_destroy(mp);
 
+       /*
+        * Purge the buffer cache to write all dirty buffers to disk and free
+        * all incore buffers, then pick up the outcome when we tell the disks
+        * to persist their write caches.
+        */
+       libxfs_bcache_purge();
        error = libxfs_flush_mount(mp);
 
        for (agno = 0; agno < mp->m_maxagi; agno++) {
index 8bb99489f8e74ca737c55f8b4a530a10142a42be..2af2410630a66d5daf8d4feae1409919c3850775 100644 (file)
@@ -452,6 +452,27 @@ secondary_sb_whack(
                        rval |= XR_AG_SB_SEC;
        }
 
+       if (xfs_sb_version_needsrepair(sb)) {
+               if (i == 0) {
+                       if (!no_modify)
+                               do_warn(
+       _("clearing needsrepair flag and regenerating metadata\n"));
+                       else
+                               do_warn(
+       _("would clear needsrepair flag and regenerate metadata\n"));
+               } else {
+                       /*
+                        * Quietly clear needsrepair on the secondary supers as
+                        * part of ensuring them.  If needsrepair is set on the
+                        * primary, it will be cleared at the end of repair
+                        * once we've flushed all other dirty blocks to disk.
+                        */
+                       sb->sb_features_incompat &=
+                                       ~XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+                       rval |= XR_AG_SB_SEC;
+               }
+       }
+
        return(rval);
 }
 
index 403524580bb13745f4092dde6a0251d47d0dd197..e2e99b2166f44f6bc57a60f844b3a55b3cb1cd77 100644 (file)
@@ -712,6 +712,45 @@ check_fs_vs_host_sectsize(
        }
 }
 
+/* Clear needsrepair after a successful repair run. */
+void
+clear_needsrepair(
+       struct xfs_mount        *mp)
+{
+       struct xfs_buf          *bp;
+       int                     error;
+
+       /*
+        * If we're going to clear NEEDSREPAIR, we need to make absolutely sure
+        * that everything is ok with the ondisk filesystem.  Make sure any
+        * dirty buffers are sent to disk and that the disks have persisted
+        * writes to stable storage.  If that fails, leave NEEDSREPAIR in
+        * place.
+        */
+       error = -libxfs_flush_mount(mp);
+       if (error) {
+               do_warn(
+       _("Cannot clear needsrepair due to flush failure, err=%d.\n"),
+                       error);
+               return;
+       }
+
+       /* Clear needsrepair from the superblock. */
+       bp = libxfs_getsb(mp);
+       if (!bp || bp->b_error) {
+               do_warn(
+       _("Cannot clear needsrepair from primary super, err=%d.\n"),
+                       bp ? bp->b_error : ENOMEM);
+       } else {
+               mp->m_sb.sb_features_incompat &=
+                               ~XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
+               libxfs_sb_to_disk(bp->b_addr, &mp->m_sb);
+               libxfs_buf_mark_dirty(bp);
+       }
+       if (bp)
+               libxfs_buf_relse(bp);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -1128,6 +1167,9 @@ _("Note - stripe unit (%d) and width (%d) were copied from a backup superblock.\
        libxfs_bcache_flush();
        format_log_max_lsn(mp);
 
+       if (xfs_sb_version_needsrepair(&mp->m_sb))
+               clear_needsrepair(mp);
+
        /* Report failure if anything failed to get written to our fs. */
        error = -libxfs_umount(mp);
        if (error)