]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: allow filesystems with a single allocation group
authorChristoph Hellwig <hch@lst.de>
Sun, 18 Jan 2009 21:13:43 +0000 (22:13 +0100)
committerChristoph Hellwig <hch@brick.lst.de>
Sun, 18 Jan 2009 21:13:43 +0000 (22:13 +0100)
Currently xfs_repair bails out on a filesystem with just a single AG.
But that's a perfectly valid configureation, so we should allow it.

Because we could cause harm only allow it when using the force_geometry
suboption.  But we nice enough to tell the user about it when he needs it.

Also make sure to take the internal log into account when guestimating the
first inode cluster offset.

I'll also cook up a testcase for repair on single AG filesystems.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reported-By: Arkadiusz Miskiewicz <arekm@maven.pl>
Reviewed-by: Eric Sandeen <sandeen@sandeen.net>
man/man8/xfs_repair.8
repair/sb.c
repair/xfs_repair.c

index eb40ed28038d9a41efc02073b3771abf2cd436c1..57c97da032dccc05d1bdc122f101d46a0df0f7a2 100644 (file)
@@ -146,6 +146,15 @@ RAM size.
 This creates additional processing threads to parallel process
 AGs that span multiple concat units. This can significantly
 reduce repair times on concat based filesystems.
+.TP
+.BI force_geometry
+Check the filesystem even if geometry information could not be validated.
+Geometry information can not be validated if only a single allocation
+group and exist and thus we do not have a backup superblock available, or
+if there are two allocation groups and the two superblocks do not
+agree on the filesystem geometry.  Only use this option if you validated
+the geometry yourself and know what you are doing.  If In doubt run
+in no modify mode first.
 .RE
 .TP
 .B \-t " interval"
index c963f3aad77f6ff1c37368e0ce0ad55faaa049de..ba58f2eebb48021755d459a496eda545c57ec411 100644 (file)
@@ -760,27 +760,37 @@ verify_set_primary_sb(xfs_sb_t            *rsb,
        switch (num_sbs)  {
        case 2:
                /*
-                * all them have to be right.  if not, report geometry
-                * and get out unless force option is in effect (-F)
+                * If we only have two allocation groups, and the superblock
+                * in the second allocation group differs from the primary
+                * superblock we can't verify the geometry information.
+                * Warn the user about this situation and get out unless
+                * explicitly overridden.
                 */
                if (current->refs != 2)  {
                        if (!force_geo)  {
                                do_warn(
-       _("Only two AGs detected and they do not match - cannot proceed.\n"));
+       _("Only two AGs detected and they do not match - "
+         "cannot validate filesystem geometry.\n"
+         "Use the -o force_geometry option to proceed.\n"));
                                exit(1);
                        }
                }
-               break;
+               goto out_free_list;
        case 1:
                /*
-                * just report the geometry info and get out.
-                * refuse to run further unless the force (-F)
-                * option is in effect.
+                * If we only have a single allocation group there is no
+                * secondary superblock that we can use to verify the geometry
+                * information.  Warn the user about this situation and get
+                * out unless explicitly overridden.
                 */
                if (!force_geo)  {
-                       do_warn(_("Only one AG detected - cannot proceed.\n"));
+                       do_warn(
+       _("Only one AG detected - "
+         "cannot validate filesystem geometry.\n"
+         "Use the -o force_geometry option to proceed.\n"));
                        exit(1);
                }
+               goto out_free_list;
        default:
                /*
                 * at least half of the probed superblocks have
@@ -820,6 +830,7 @@ verify_set_primary_sb(xfs_sb_t              *rsb,
                sb_width = sb->sb_width;
        }
 
+out_free_list:
        free_geo(list);
 out:
        free(sb);
index d51c9b19d6cba44ef1cd558870d52b86e5e143f6..e9e596511fddfed0a9aba726abd4655c357adcbc 100644 (file)
@@ -62,6 +62,8 @@ char *o_opts[] = {
        "bhash",
 #define        AG_STRIDE       4
        "ag_stride",
+#define FORCE_GEO      5
+       "force_geometry",
        NULL
 };
 
@@ -258,6 +260,13 @@ process_args(int argc, char **argv)
                                case AG_STRIDE:
                                        ag_stride = (int)strtol(val, NULL, 0);
                                        break;
+                               case FORCE_GEO:
+                                       if (val)
+                                               noval('o', o_opts, FORCE_GEO);
+                                       if (force_geo)
+                                               respec('o', o_opts, FORCE_GEO);
+                                       force_geo = 1;
+                                       break;
                                default:
                                        unknown('o', val);
                                        break;
@@ -408,6 +417,19 @@ calc_mkfs(xfs_mount_t *mp)
        inobt_root = bnobt_root + 2;
        fino_bno = inobt_root + XFS_MIN_FREELIST_RAW(1, 1, mp) + 1;
 
+       /*
+        * If we only have a single allocation group the log is also allocated
+        * in the first allocation group and we need to add the number of
+        * blocks used by the log to the above calculation.
+        * All this of course doesn't apply if we have an external log.
+        */
+       if (mp->m_sb.sb_agcount == 1 && mp->m_sb.sb_logstart) {
+               /*
+                * XXX(hch): verify that sb_logstart makes sense?
+                */
+                fino_bno += mp->m_sb.sb_logblocks;
+       }
+
        /*
         * ditto the location of the first inode chunks in the fs ('/')
         */