Whamcloud - gitweb
tune2fs: confirm dangerous operations
authorDarrick J. Wong <darrick.wong@oracle.com>
Sat, 13 Feb 2016 22:38:11 +0000 (14:38 -0800)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 7 Mar 2016 01:08:53 +0000 (20:08 -0500)
Give admins a short amount of time to confirm that they want to
proceed with a dangerous operation.  Refuse to perform the op
unless the filesystem is freshly checked.

Cc: Andreas Dilger <adilger@dilger.ca>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
misc/tune2fs.c
tests/t_dangerous/expect [new file with mode: 0644]
tests/t_dangerous/name [new file with mode: 0644]
tests/t_dangerous/script [new file with mode: 0644]

index f1a0514..9e1e712 100644 (file)
@@ -406,14 +406,24 @@ static int update_mntopts(ext2_filsys fs, char *mntopts)
        return 0;
 }
 
-static int check_fsck_needed(ext2_filsys fs)
+static void check_fsck_needed(ext2_filsys fs, const char *prompt)
 {
-       if (fs->super->s_state & EXT2_VALID_FS)
-               return 0;
-       printf("\n%s\n", _(please_fsck));
-       if (mount_flags & EXT2_MF_READONLY)
-               printf("%s", _("(and reboot afterwards!)\n"));
-       return 1;
+       /* Refuse to modify anything but a freshly checked valid filesystem. */
+       if (!(fs->super->s_state & EXT2_VALID_FS) ||
+           (fs->super->s_state & EXT2_ERROR_FS) ||
+           (fs->super->s_lastcheck < fs->super->s_mtime)) {
+               printf("\n%s\n", _(please_fsck));
+               if (mount_flags & EXT2_MF_READONLY)
+                       printf("%s", _("(and reboot afterwards!)\n"));
+               exit(1);
+       }
+
+       /* Give the admin a few seconds to bail out of a dangerous op. */
+       if (!getenv("TUNE2FS_FORCE_PROMPT") && (!isatty(0) || !isatty(1)))
+               return;
+
+       puts(prompt);
+       proceed_question(5);
 }
 
 static void request_dir_fsck_afterwards(ext2_filsys fs)
@@ -1147,8 +1157,8 @@ mmp_error:
 
        if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
-               if (check_fsck_needed(fs))
-                       exit(1);
+               check_fsck_needed(fs,
+                       _("Enabling checksums could take some time."));
                if (mount_flags & EXT2_MF_MOUNTED) {
                        fputs(_("Cannot enable metadata_csum on a mounted "
                                "filesystem!\n"), stderr);
@@ -1188,8 +1198,8 @@ mmp_error:
                        EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
                __u32   test_features[3];
 
-               if (check_fsck_needed(fs))
-                       exit(1);
+               check_fsck_needed(fs,
+                       _("Disabling checksums could take some time."));
                if (mount_flags & EXT2_MF_MOUNTED) {
                        fputs(_("Cannot disable metadata_csum on a mounted "
                                "filesystem!\n"), stderr);
@@ -2797,6 +2807,8 @@ retry_open:
                        rc = 1;
                        goto closefs;
                }
+               check_fsck_needed(fs,
+                       _("Resizing inodes could take some time."));
                /*
                 * If inode resize is requested use the
                 * Undo I/O manager
@@ -3012,8 +3024,10 @@ retry_open:
                                try_confirm_csum_seed_support();
                                exit(1);
                        }
-                       if (check_fsck_needed(fs))
-                               exit(1);
+                       if (!ext2fs_has_feature_csum_seed(fs->super))
+                               check_fsck_needed(fs,
+                                       _("Setting UUID on a checksummed "
+                                         "filesystem could take some time."));
 
                        /*
                         * Determine if the block group checksums are
diff --git a/tests/t_dangerous/expect b/tests/t_dangerous/expect
new file mode 100644 (file)
index 0000000..353bd57
--- /dev/null
@@ -0,0 +1,97 @@
+tune2fs dangerous prompts test
+Creating filesystem with 524288 1k blocks and 65536 inodes
+Superblock backups stored on blocks: 
+       8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
+
+Allocating group tables:      \b\b\b\b\bdone                            
+Writing inode tables:      \b\b\b\b\bdone                            
+Creating journal (16384 blocks): done
+Creating 445 huge file(s) with 1024 blocks each: done
+Writing superblocks and filesystem accounting information:      \b\b\b\b\bdone
+
+tune2fs -O metadata_csum test.img
+
+Please run e2fsck on the filesystem.
+
+Exit status is 1
+tune2fs -O metadata_csum test.img
+Exit status is 0
+Creating filesystem with 524288 1k blocks and 65536 inodes
+Superblock backups stored on blocks: 
+       8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
+
+Allocating group tables:      \b\b\b\b\bdone                            
+Writing inode tables:      \b\b\b\b\bdone                            
+Creating journal (16384 blocks): done
+Creating 445 huge file(s) with 1024 blocks each: done
+Writing superblocks and filesystem accounting information:      \b\b\b\b\bdone
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+Exit status is 0
+tune2fs -O metadata_csum test.img
+Enabling checksums could take some time.
+Proceed anyway (or wait 5 seconds) ? (y,n) 
+Exit status is 1
+tune2fs -I 512 test.img
+Resizing inodes could take some time.
+Proceed anyway (or wait 5 seconds) ? (y,n) 
+Exit status is 1
+tune2fs -U random test.img
+Setting UUID on a checksummed filesystem could take some time.
+Proceed anyway (or wait 5 seconds) ? (y,n) 
+Exit status is 1
+
+Change in FS metadata:
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+Exit status is 0
+tune2fs -O metadata_csum test.img
+Enabling checksums could take some time.
+Proceed anyway (or wait 5 seconds) ? (y,n) 
+Please run e2fsck -D on the filesystem.
+
+Exit status is 0
+test_filesys was not cleanly unmounted, check forced.
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 3A: Optimizing directories
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+
+
+tune2fs -I 512 test.img
+Resizing inodes could take some time.
+Proceed anyway (or wait 5 seconds) ? (y,n) Setting inode size 512
+Exit status is 0
+tune2fs -U f0f0f0f0-f0f0-f0f0-f0f0-f0f0f0f0f0f0 test.img
+Setting UUID on a checksummed filesystem could take some time.
+Proceed anyway (or wait 5 seconds) ? (y,n) Exit status is 0
+Backing up journal inode block information.
+
+
+Change in FS metadata:
+@@ -1,3 +1,3 @@
+-Filesystem UUID:          6fc3daa4-180d-4f2b-a6f2-f7a5efb79bcf
+-Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent 64bit sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
+-Inode size:             256
++Filesystem UUID:          f0f0f0f0-f0f0-f0f0-f0f0-f0f0f0f0f0f0
++Filesystem features:      has_journal ext_attr resize_inode dir_index filetype extent 64bit sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
++Inode size:             512
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+Exit status is 0
diff --git a/tests/t_dangerous/name b/tests/t_dangerous/name
new file mode 100644 (file)
index 0000000..c9a1030
--- /dev/null
@@ -0,0 +1 @@
+dangerous tune2fs operation prompts
diff --git a/tests/t_dangerous/script b/tests/t_dangerous/script
new file mode 100644 (file)
index 0000000..dc70ad2
--- /dev/null
@@ -0,0 +1,134 @@
+FSCK_OPT=-fn
+OUT=$test_name.log
+EXP=$test_dir/expect
+CONF=$TMPFILE.conf
+
+cat > $CONF << ENDL
+[fs_types]
+       ext4h = {
+               features = has_journal,extent,huge_file,^flex_bg,uninit_bg,dir_nlink,extra_isize,sparse_super,filetype,dir_index,ext_attr,resize_inode,64bit
+               blocksize = 1024
+               inode_size = 256
+               make_hugefiles = true
+               hugefiles_dir = /
+               hugefiles_slack = 32M
+               hugefiles_name = aaaaa
+               hugefiles_digits = 4
+               hugefiles_size = 1M
+               zero_hugefiles = false
+       }
+ENDL
+
+echo "tune2fs dangerous prompts test" > $OUT
+
+MKE2FS_CONFIG=$CONF $MKE2FS -F -T ext4h -U 6fc3daa4-180d-4f2b-a6f2-f7a5efb79bcf $TMPFILE 524288 >> $OUT 2>&1
+
+# trigger a filesystem check
+$DEBUGFS -w -R 'ssv mtime now' $TMPFILE > /dev/null 2>&1
+$DEBUGFS -w -R 'ssv lastcheck 20000' $TMPFILE > /dev/null 2>&1
+
+# add mcsum
+echo "tune2fs -O metadata_csum test.img" >> $OUT
+$TUNE2FS -O metadata_csum $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+# check fs
+$FSCK -f -y -N test_filesys $TMPFILE > /dev/null 2>&1
+
+# add mcsum
+echo "tune2fs -O metadata_csum test.img" >> $OUT
+$TUNE2FS -O metadata_csum $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+MKE2FS_CONFIG=$CONF $MKE2FS -F -T ext4h -U 6fc3daa4-180d-4f2b-a6f2-f7a5efb79bcf $TMPFILE 524288 >> $OUT 2>&1
+
+# dump and check
+$DUMPE2FS $TMPFILE 2> /dev/null | grep '^Group 0:' -B99 -A20 | sed -f $cmd_dir/filter.sed > $OUT.before
+$FSCK $FSCK_OPT -f -N test_filesys $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+# add mcsum
+echo "tune2fs -O metadata_csum test.img" >> $OUT
+echo 'n' | TUNE2FS_FORCE_PROMPT=1 $TUNE2FS -O metadata_csum $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+# change inode size
+echo "tune2fs -I 512 test.img" >> $OUT
+echo 'n' | TUNE2FS_FORCE_PROMPT=1 $TUNE2FS -I 512 $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+# change uuid
+echo "tune2fs -U random test.img" >> $OUT
+echo 'n' | TUNE2FS_FORCE_PROMPT=1 $TUNE2FS -U random $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+# check
+$FSCK -yD -N test_filesys $TMPFILE >> $OUT 2>&1
+
+# dump and check
+$DUMPE2FS $TMPFILE 2> /dev/null | grep '^Group 0:' -B99 -A20 | sed -f $cmd_dir/filter.sed > $OUT.after
+echo "Change in FS metadata:" >> $OUT
+diff -u $OUT.before $OUT.after | tail -n +3 >> $OUT
+$FSCK $FSCK_OPT -N test_filesys $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+$DUMPE2FS $TMPFILE 2> /dev/null | egrep '^(Filesystem features:|Filesystem UUID:|Inode size:)' > $OUT.before
+
+# add mcsum
+echo "tune2fs -O metadata_csum test.img" >> $OUT
+echo 'y' | TUNE2FS_FORCE_PROMPT=1 $TUNE2FS -O metadata_csum $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+$FSCK -yD -N test_filesys $TMPFILE >> $OUT 2>&1
+
+# change inode size
+echo "tune2fs -I 512 test.img" >> $OUT
+echo 'y' | TUNE2FS_FORCE_PROMPT=1 $TUNE2FS -I 512 $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+# change uuid
+echo "tune2fs -U f0f0f0f0-f0f0-f0f0-f0f0-f0f0f0f0f0f0 test.img" >> $OUT
+echo 'y' | TUNE2FS_FORCE_PROMPT=1 $TUNE2FS -U f0f0f0f0-f0f0-f0f0-f0f0-f0f0f0f0f0f0 $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+# check
+$FSCK -yD -N test_filesys $TMPFILE >> $OUT 2>&1
+
+# dump and check
+$DUMPE2FS $TMPFILE 2> /dev/null | egrep '^(Filesystem features:|Filesystem UUID:|Inode size:)' > $OUT.after
+echo "Change in FS metadata:" >> $OUT
+diff -u $OUT.before $OUT.after | tail -n +3 >> $OUT
+$FSCK $FSCK_OPT -N test_filesys $TMPFILE >> $OUT 2>&1
+status=$?
+echo Exit status is $status >> $OUT
+
+rm $TMPFILE $OUT.before $OUT.after $CONF
+
+#
+# Do the verification
+#
+
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" -e 's/test_filesys:.*//g' < $OUT > $OUT.new
+mv $OUT.new $OUT
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+       echo "$test_name: $test_description: ok"
+       touch $test_name.ok
+else
+       echo "$test_name: $test_description: failed"
+       diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+fi
+
+unset IMAGE FSCK_OPT OUT EXP CONF