]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - repair/phase1.c
xfs: perags need atomic operational state
[thirdparty/xfsprogs-dev.git] / repair / phase1.c
index 1853d0f772d5db931157b255585e79726258dbc0..00b98584eed4291e7ab3eebcd786d4439cc0bc69 100644 (file)
@@ -1,42 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2000-2001 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-2001,2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
  */
 
-#include <libxfs.h>
+#include "libxfs.h"
 #include "globals.h"
 #include "agheader.h"
 #include "protos.h"
 #include "err_protos.h"
 
-void
+static void
 no_sb(void)
 {
        do_warn(_("Sorry, could not find valid secondary superblock\n"));
@@ -47,10 +21,10 @@ no_sb(void)
 char *
 alloc_ag_buf(int size)
 {
-       char    *bp;
+       char    *bp;
 
-        bp = (char *)memalign(MEM_ALIGN, size);
-        if (!bp)
+       bp = (char *)memalign(libxfs_device_alignment(), size);
+       if (!bp)
                do_error(_("could not allocate ag header buffer (%d bytes)\n"),
                        size);
        return(bp);
@@ -69,8 +43,6 @@ phase1(xfs_mount_t *mp)
        char                    *ag_bp;
        int                     rval;
 
-       io_init();
-
        do_log(_("Phase 1 - find and verify superblock...\n"));
 
        primary_sb_modified = 0;
@@ -79,7 +51,6 @@ phase1(xfs_mount_t *mp)
        need_rbmino = 0;
        need_rsumino = 0;
        lost_quotas = 0;
-       old_orphanage_ino = (xfs_ino_t) 0;
 
        /*
         * get AG 0 into ag header buf
@@ -87,13 +58,14 @@ phase1(xfs_mount_t *mp)
        ag_bp = alloc_ag_buf(MAX_SECTSIZE);
        sb = (xfs_sb_t *) ag_bp;
 
-       if (get_sb(sb, 0LL, MAX_SECTSIZE, 0) == XR_EOF)
+       rval = get_sb(sb, 0LL, MAX_SECTSIZE, 0);
+       if (rval == XR_EOF)
                do_error(_("error reading primary superblock\n"));
 
        /*
         * is this really an sb, verify internal consistency
         */
-       if ((rval = verify_sb(sb, 1)) != XR_OK)  {
+       if (rval != XR_OK)  {
                do_warn(_("bad primary superblock - %s !!!\n"),
                        err_string(rval));
                if (!find_secondary_sb(sb))
@@ -107,7 +79,60 @@ phase1(xfs_mount_t *mp)
                        no_sb();
                primary_sb_modified = 1;
        }
-       
+
+       /*
+        * Check bad_features2 and make sure features2 the same as
+        * bad_features (ORing the two together). Leave bad_features2
+        * set so older kernels can still use it and not mount unsupported
+        * filesystems when it reads bad_features2.
+        */
+       if (sb->sb_bad_features2 != 0 &&
+                       sb->sb_bad_features2 != sb->sb_features2) {
+               sb->sb_features2 |= sb->sb_bad_features2;
+               sb->sb_bad_features2 = sb->sb_features2;
+               primary_sb_modified = 1;
+               do_warn(_("superblock has a features2 mismatch, correcting\n"));
+       }
+
+       /*
+        * apply any version changes or conversions after the primary
+        * superblock has been verified or repaired
+        *
+        * Send output to stdout as do_log and everything else in repair
+        * is sent to stderr and there is no "quiet" option. xfs_admin
+        * will filter stderr but not stdout. This situation must be improved.
+        */
+       if (convert_lazy_count) {
+               if (lazy_count && !xfs_sb_version_haslazysbcount(sb)) {
+                       sb->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
+                       sb->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT;
+                       sb->sb_bad_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT;
+                       primary_sb_modified = 1;
+                       printf(_("Enabling lazy-counters\n"));
+               } else if (!lazy_count && xfs_sb_version_haslazysbcount(sb)) {
+                       if (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5) {
+                               printf(
+_("Cannot disable lazy-counters on V5 fs\n"));
+                               exit(1);
+                       }
+                       sb->sb_features2 &= ~XFS_SB_VERSION2_LAZYSBCOUNTBIT;
+                       sb->sb_bad_features2 &= ~XFS_SB_VERSION2_LAZYSBCOUNTBIT;
+                       printf(_("Disabling lazy-counters\n"));
+                       primary_sb_modified = 1;
+               } else {
+                       printf(_("Lazy-counters are already %s\n"),
+                               lazy_count ? _("enabled") : _("disabled"));
+                       exit(0); /* no conversion required, exit */
+               }
+       }
+
+       /* shared_vn should be zero */
+       if (sb->sb_shared_vn) {
+               do_warn(_("resetting shared_vn to zero\n"));
+               sb->sb_shared_vn = 0;
+               primary_sb_modified = 1;
+       }
+
        if (primary_sb_modified)  {
                if (!no_modify)  {
                        do_warn(_("writing modified primary superblock\n"));