]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
tune2fs: forbid changing uuid on an uninit_bg filesystem
authorDarrick J. Wong <darrick.wong@oracle.com>
Sun, 15 Dec 2013 01:51:04 +0000 (20:51 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 15 Dec 2013 01:51:04 +0000 (20:51 -0500)
The old uninit_bg checksums depend on the UUID, so prohibit changes to
the UUID if a checksumming filesystem is mounted, because this
introduces a nasty race where the kernel and tune2fs are both trying
to rewrite group descriptors at the same time, with different ideas
about what the UUID is.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
misc/tune2fs.c

index 822df74a1ac83de69af5d92b19e9aed56a5d0756..a8dc11124017514d8884ea5e44b4afc02b4656e2 100644 (file)
@@ -358,6 +358,16 @@ static int update_mntopts(ext2_filsys fs, char *mntopts)
        return 0;
 }
 
+static int check_fsck_needed(ext2_filsys fs)
+{
+       if (fs->super->s_state & EXT2_VALID_FS)
+               return 0;
+       printf("\n%s\n", _(please_fsck));
+       if (mount_flags & EXT2_MF_READONLY)
+               printf(_("(and reboot afterwards!)\n"));
+       return 1;
+}
+
 static void request_fsck_afterwards(ext2_filsys fs)
 {
        static int requested = 0;
@@ -2146,6 +2156,19 @@ retry_open:
 
                if (sb->s_feature_ro_compat &
                    EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+                       /*
+                        * Changing the UUID requires rewriting all metadata,
+                        * which can race with a mounted fs.  Don't allow that.
+                        */
+                       if (mount_flags & EXT2_MF_MOUNTED) {
+                               fputs(_("The UUID may only be "
+                                       "changed when the filesystem is "
+                                       "unmounted.\n"), stderr);
+                               exit(1);
+                       }
+                       if (check_fsck_needed(fs))
+                               exit(1);
+
                        /*
                         * Determine if the block group checksums are
                         * correct so we know whether or not to set