]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - repair/phase2.c
libxfs: refactor manage_zones()
[thirdparty/xfsprogs-dev.git] / repair / phase2.c
index fdf85a9f9330a5ceb7d3021daae42967d6edb8ac..4bd6c631a0298684c71486364ade11b8960ffc3e 100644 (file)
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 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.
- * 
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- * 
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- * 
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- * 
- * http://www.sgi.com 
- * 
- * For further information regarding this notice, see: 
- * 
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
  */
 
-#include <libxlog.h>
+#include "libxfs.h"
+#include "libxlog.h"
 #include "avl.h"
 #include "globals.h"
 #include "agheader.h"
 #include "protos.h"
 #include "err_protos.h"
 #include "incore.h"
-
-void   set_mp(xfs_mount_t *mpp);
-void   scan_ag(xfs_agnumber_t agno);
+#include "progress.h"
+#include "scan.h"
 
 /* workaround craziness in the xlog routines */
-int xlog_recover_do_trans(xlog_t *log, xlog_recover_t *t, int p) { return 0; }
+int xlog_recover_do_trans(struct xlog *log, xlog_recover_t *t, int p)
+{
+       return 0;
+}
 
 static void
-zero_log(xfs_mount_t *mp)
+zero_log(
+       struct xfs_mount        *mp)
 {
-       int error;
-       xlog_t  log;
-       xfs_daddr_t head_blk, tail_blk;
-       dev_t logdev = (mp->m_sb.sb_logstart == 0) ? x.logdev : x.ddev;
-
-       memset(&log, 0, sizeof(log));
-       if (!x.logdev)
-               x.logdev = x.ddev;
+       int                     error;
+       xfs_daddr_t             head_blk;
+       xfs_daddr_t             tail_blk;
+       struct xlog             *log = mp->m_log;
+
+       memset(log, 0, sizeof(struct xlog));
        x.logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
        x.logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart);
+       x.lbsize = BBSIZE;
+       if (xfs_sb_version_hassector(&mp->m_sb))
+               x.lbsize <<= (mp->m_sb.sb_logsectlog - BBSHIFT);
+
+       log->l_dev = mp->m_logdev_targp;
+       log->l_logBBsize = x.logBBsize;
+       log->l_logBBstart = x.logBBstart;
+       log->l_sectBBsize  = BTOBB(x.lbsize);
+       log->l_mp = mp;
+       if (xfs_sb_version_hassector(&mp->m_sb)) {
+               log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
+               ASSERT(log->l_sectbb_log <= mp->m_sectbb_log);
+               /* for larger sector sizes, must have v2 or external log */
+               ASSERT(log->l_sectbb_log == 0 ||
+                       log->l_logBBstart == 0 ||
+                       xfs_sb_version_haslogv2(&mp->m_sb));
+               ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT);
+       }
+       log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1;
 
-       log.l_dev = logdev;
-       log.l_logsize = BBTOB(x.logBBsize);
-       log.l_logBBsize = x.logBBsize;
-       log.l_logBBstart = x.logBBstart;
-       log.l_mp = mp;
-
-       if ((error = xlog_find_tail(&log, &head_blk, &tail_blk, 0))) {
-               do_warn("zero_log: cannot find log head/tail "
-                       "(xlog_find_tail=%d), zeroing it anyway\n",
+       /*
+        * Find the log head and tail and alert the user to the situation if the
+        * log appears corrupted or contains data. In either case, we do not
+        * proceed past this point unless the user explicitly requests to zap
+        * the log.
+        */
+       error = xlog_find_tail(log, &head_blk, &tail_blk);
+       if (error) {
+               do_warn(
+               _("zero_log: cannot find log head/tail (xlog_find_tail=%d)\n"),
                        error);
+               if (!no_modify && !zap_log) {
+                       do_warn(_(
+"ERROR: The log head and/or tail cannot be discovered. Attempt to mount the\n"
+"filesystem to replay the log or use the -L option to destroy the log and\n"
+"attempt a repair.\n"));
+                       exit(2);
+               }
        } else {
                if (verbose) {
-                       do_warn("zero_log: head block %lld tail block %lld\n",
+                       do_log(
+       _("zero_log: head block %" PRId64 " tail block %" PRId64 "\n"),
                                head_blk, tail_blk);
                }
                if (head_blk != tail_blk) {
-                       if (zap_log) {
-                               do_warn(
+                       if (!no_modify && zap_log) {
+                               do_warn(_(
+"ALERT: The filesystem has valuable metadata changes in a log which is being\n"
+"destroyed because the -L option was used.\n"));
+                       } else if (no_modify) {
+                               do_warn(_(
 "ALERT: The filesystem has valuable metadata changes in a log which is being\n"
-"destroyed because the -L option was used.\n");
+"ignored because the -n option was used.  Expect spurious inconsistencies\n"
+"which may be resolved by first mounting the filesystem to replay the log.\n"));
                        } else {
-                               do_warn(
+                               do_warn(_(
 "ERROR: The filesystem has valuable metadata changes in a log which needs to\n"
 "be replayed.  Mount the filesystem to replay the log, and unmount it before\n"
 "re-running xfs_repair.  If you are unable to mount the filesystem, then use\n"
 "the -L option to destroy the log and attempt a repair.\n"
 "Note that destroying the log may cause corruption -- please attempt a mount\n"
-"of the filesystem before doing this.\n");
+"of the filesystem before doing this.\n"));
                                exit(2);
                        }
                }
        }
 
-       libxfs_log_clear(logdev, 
-               XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
-               (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
-               &mp->m_sb.sb_uuid,
-               XFS_SB_VERSION_HASLOGV2(&mp->m_sb) ? 2 : 1,
-               mp->m_sb.sb_logsunit, XLOG_FMT);
+       /*
+        * Only clear the log when explicitly requested. Doing so is unnecessary
+        * unless something is wrong. Further, this resets the current LSN of
+        * the filesystem and creates more work for repair of v5 superblock
+        * filesystems.
+        */
+       if (!no_modify && zap_log) {
+               libxfs_log_clear(log->l_dev, NULL,
+                       XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
+                       (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
+                       &mp->m_sb.sb_uuid,
+                       xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1,
+                       mp->m_sb.sb_logsunit, XLOG_FMT, XLOG_INIT_CYCLE, true);
+
+               /* update the log data structure with new state */
+               error = xlog_find_tail(log, &head_blk, &tail_blk);
+               if (error || head_blk != tail_blk)
+                       do_error(_("failed to clear log"));
+       }
+
+       /*
+        * Finally, seed the max LSN from the current state of the log if this
+        * is a v5 filesystem.
+        */
+       if (xfs_sb_version_hascrc(&mp->m_sb))
+               libxfs_max_lsn = log->l_last_sync_lsn;
 }
 
 /*
@@ -109,10 +138,10 @@ zero_log(xfs_mount_t *mp)
  */
 
 void
-phase2(xfs_mount_t *mp)
+phase2(
+       struct xfs_mount        *mp,
+       int                     scan_threads)
 {
-       xfs_agnumber_t          i;
-       xfs_agblock_t           b;
        int                     j;
        ino_tree_node_t         *ino_rec;
 
@@ -121,53 +150,40 @@ phase2(xfs_mount_t *mp)
 
        /* Check whether this fs has internal or external log */
        if (mp->m_sb.sb_logstart == 0) {
-               if (!x.logname) {
-                       fprintf (stderr,
-                               "This filesystem has an external log.  "
-                               "Specify log device with the -l option.\n");
-                       exit (1);
-               }
-               
-               fprintf (stderr, "Phase 2 - using external log on %s\n", 
-                        x.logname);
+               if (!x.logname)
+                       do_error(_("This filesystem has an external log.  "
+                                  "Specify log device with the -l option.\n"));
+
+               do_log(_("Phase 2 - using external log on %s\n"), x.logname);
        } else
-               fprintf (stderr, "Phase 2 - using internal log\n");
+               do_log(_("Phase 2 - using internal log\n"));
 
        /* Zero log if applicable */
-       if (!no_modify)  {
-               do_log("        - zero log...\n");
-               zero_log(mp);
-       }
+       do_log(_("        - zero log...\n"));
+       zero_log(mp);
 
-       do_log("        - scan filesystem freespace and inode maps...\n");
-
-       /*
-        * account for space used by ag headers and log if internal
-        */
-       set_bmap_log(mp);
-       set_bmap_fs(mp);
+       do_log(_("        - scan filesystem freespace and inode maps...\n"));
 
        bad_ino_btree = 0;
 
-       for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
-               scan_ag(i);
-#ifdef XR_INODE_TRACE
-               print_inode_list(i);
-#endif
-       }
+       set_progress_msg(PROG_FMT_SCAN_AG, (uint64_t) glob_agcount);
+
+       scan_ags(mp, scan_threads);
+
+       print_final_rpt();
 
        /*
         * make sure we know about the root inode chunk
         */
-       if ((ino_rec = find_inode_rec(0, mp->m_sb.sb_rootino)) == NULL)  {
+       if ((ino_rec = find_inode_rec(mp, 0, mp->m_sb.sb_rootino)) == NULL)  {
                ASSERT(mp->m_sb.sb_rbmino == mp->m_sb.sb_rootino + 1 &&
                        mp->m_sb.sb_rsumino == mp->m_sb.sb_rootino + 2);
-               do_warn("root inode chunk not found\n");
+               do_warn(_("root inode chunk not found\n"));
 
                /*
                 * mark the first 3 used, the rest are free
                 */
-               ino_rec = set_inode_used_alloc(0,
+               ino_rec = set_inode_used_alloc(mp, 0,
                                (xfs_agino_t) mp->m_sb.sb_rootino);
                set_inode_used(ino_rec, 1);
                set_inode_used(ino_rec, 2);
@@ -178,42 +194,39 @@ phase2(xfs_mount_t *mp)
                /*
                 * also mark blocks
                 */
-               for (b = 0; b < mp->m_ialloc_blks; b++)  {
-                       set_agbno_state(mp, 0,
-                               b + XFS_INO_TO_AGBNO(mp, mp->m_sb.sb_rootino),
-                               XR_E_INO);
-               }
+               set_bmap_ext(0, XFS_INO_TO_AGBNO(mp, mp->m_sb.sb_rootino),
+                            mp->m_ialloc_blks, XR_E_INO);
        } else  {
-               do_log("        - found root inode chunk\n");
+               do_log(_("        - found root inode chunk\n"));
 
                /*
                 * blocks are marked, just make sure they're in use
                 */
                if (is_inode_free(ino_rec, 0))  {
-                       do_warn("root inode marked free, ");
+                       do_warn(_("root inode marked free, "));
                        set_inode_used(ino_rec, 0);
                        if (!no_modify)
-                               do_warn("correcting\n");
+                               do_warn(_("correcting\n"));
                        else
-                               do_warn("would correct\n");
+                               do_warn(_("would correct\n"));
                }
 
                if (is_inode_free(ino_rec, 1))  {
-                       do_warn("realtime bitmap inode marked free, ");
+                       do_warn(_("realtime bitmap inode marked free, "));
                        set_inode_used(ino_rec, 1);
                        if (!no_modify)
-                               do_warn("correcting\n");
+                               do_warn(_("correcting\n"));
                        else
-                               do_warn("would correct\n");
+                               do_warn(_("would correct\n"));
                }
 
                if (is_inode_free(ino_rec, 2))  {
-                       do_warn("realtime summary inode marked free, ");
+                       do_warn(_("realtime summary inode marked free, "));
                        set_inode_used(ino_rec, 2);
                        if (!no_modify)
-                               do_warn("correcting\n");
+                               do_warn(_("correcting\n"));
                        else
-                               do_warn("would correct\n");
+                               do_warn(_("would correct\n"));
                }
        }
 }