]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
resize2fs: optionally create undo file
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 5 May 2015 14:40:53 +0000 (10:40 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 5 May 2015 14:41:05 +0000 (10:41 -0400)
Provide the user with an option to create an undo file so that they
can roll back a failed resize operation.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
resize/main.c
resize/resize2fs.8.in

index c25de61947f324c7e694d6844706b9b11c891bbd..a61943e49137f1c4bfe1b007ef3218616efd4996 100644 (file)
@@ -29,6 +29,7 @@ extern int optind;
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <libgen.h>
 
 #include "e2p/e2p.h"
 
 
 #include "e2p/e2p.h"
 
@@ -42,7 +43,8 @@ static char *device_name, *io_options;
 static void usage (char *prog)
 {
        fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
 static void usage (char *prog)
 {
        fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
-                          "[-p] device [-b|-s|new_size]\n\n"), prog);
+                          "[-p] device [-b|-s|new_size] [-z undo_file]\n\n"),
+                prog);
 
        exit (1);
 }
 
        exit (1);
 }
@@ -162,6 +164,82 @@ static void bigalloc_check(ext2_filsys fs, int force)
        }
 }
 
        }
 }
 
+static int resize2fs_setup_tdb(const char *device_name, char *undo_file,
+                              io_manager *io_ptr)
+{
+       errcode_t retval = ENOMEM;
+       char *tdb_dir = NULL, *tdb_file = NULL;
+       char *dev_name, *tmp_name;
+       int free_tdb_dir = 0;
+
+       /* (re)open a specific undo file */
+       if (undo_file && undo_file[0] != 0) {
+               set_undo_io_backing_manager(*io_ptr);
+               *io_ptr = undo_io_manager;
+               retval = set_undo_io_backup_file(undo_file);
+               if (retval)
+                       goto err;
+               printf(_("Overwriting existing filesystem; this can be undone "
+                        "using the command:\n"
+                        "    e2undo %s %s\n\n"),
+                       undo_file, device_name);
+               return 0;
+       }
+
+       /*
+        * Configuration via a conf file would be
+        * nice
+        */
+       tdb_dir = getenv("E2FSPROGS_UNDO_DIR");
+
+       if (tdb_dir == NULL || !strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) ||
+           access(tdb_dir, W_OK)) {
+               if (free_tdb_dir)
+                       free(tdb_dir);
+               return 0;
+       }
+
+       tmp_name = strdup(device_name);
+       if (!tmp_name)
+               goto errout;
+       dev_name = basename(tmp_name);
+       tdb_file = malloc(strlen(tdb_dir) + 8 + strlen(dev_name) + 7 + 1);
+       if (!tdb_file) {
+               free(tmp_name);
+               goto errout;
+       }
+       sprintf(tdb_file, "%s/resize2fs-%s.e2undo", tdb_dir, dev_name);
+       free(tmp_name);
+
+       if ((unlink(tdb_file) < 0) && (errno != ENOENT)) {
+               retval = errno;
+               goto errout;
+       }
+
+       set_undo_io_backing_manager(*io_ptr);
+       *io_ptr = undo_io_manager;
+       retval = set_undo_io_backup_file(tdb_file);
+       if (retval)
+               goto errout;
+       printf(_("Overwriting existing filesystem; this can be undone "
+                "using the command:\n"
+                "    e2undo %s %s\n\n"), tdb_file, device_name);
+
+       if (free_tdb_dir)
+               free(tdb_dir);
+       free(tdb_file);
+       return 0;
+
+errout:
+       if (free_tdb_dir)
+               free(tdb_dir);
+       free(tdb_file);
+err:
+       com_err(program_name, retval, "%s",
+               _("while trying to setup undo file\n"));
+       return retval;
+}
+
 int main (int argc, char ** argv)
 {
        errcode_t       retval;
 int main (int argc, char ** argv)
 {
        errcode_t       retval;
@@ -186,7 +264,7 @@ int main (int argc, char ** argv)
        unsigned int    blocksize;
        long            sysval;
        int             len, mount_flags;
        unsigned int    blocksize;
        long            sysval;
        int             len, mount_flags;
-       char            *mtpt;
+       char            *mtpt, *undo_file = NULL;
 
 #ifdef ENABLE_NLS
        setlocale(LC_MESSAGES, "");
 
 #ifdef ENABLE_NLS
        setlocale(LC_MESSAGES, "");
@@ -203,7 +281,7 @@ int main (int argc, char ** argv)
        if (argc && *argv)
                program_name = *argv;
 
        if (argc && *argv)
                program_name = *argv;
 
-       while ((c = getopt(argc, argv, "d:fFhMPpS:bs")) != EOF) {
+       while ((c = getopt(argc, argv, "d:fFhMPpS:bsz:")) != EOF) {
                switch (c) {
                case 'h':
                        usage(program_name);
                switch (c) {
                case 'h':
                        usage(program_name);
@@ -235,6 +313,9 @@ int main (int argc, char ** argv)
                case 's':
                        flags |= RESIZE_DISABLE_64BIT;
                        break;
                case 's':
                        flags |= RESIZE_DISABLE_64BIT;
                        break;
+               case 'z':
+                       undo_file = optarg;
+                       break;
                default:
                        usage(program_name);
                }
                default:
                        usage(program_name);
                }
@@ -318,7 +399,11 @@ int main (int argc, char ** argv)
                io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE;
 
        io_flags |= EXT2_FLAG_64BITS;
                io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE;
 
        io_flags |= EXT2_FLAG_64BITS;
-
+       if (undo_file) {
+               retval = resize2fs_setup_tdb(device_name, undo_file, &io_ptr);
+               if (retval)
+                       exit(1);
+       }
        retval = ext2fs_open2(device_name, io_options, io_flags,
                              0, 0, io_ptr, &fs);
        if (retval) {
        retval = ext2fs_open2(device_name, io_options, io_flags,
                              0, 0, io_ptr, &fs);
        if (retval) {
index 0129bfcafa3b44f612860ec9e91555e92a8cdd71..d2738e9cdf42ab2714d90ef29e44f312ff4f3a61 100644 (file)
@@ -18,6 +18,10 @@ resize2fs \- ext2/ext3/ext4 file system resizer
 .B \-S
 .I RAID-stride
 ]
 .B \-S
 .I RAID-stride
 ]
+[
+.B \-z
+.I undo_file
+]
 .I device
 [
 .I size
 .I device
 [
 .I size
@@ -149,6 +153,16 @@ The
 program will heuristically determine the RAID stride that was specified
 when the filesystem was created.  This option allows the user to
 explicitly specify a RAID stride setting to be used by resize2fs instead.
 program will heuristically determine the RAID stride that was specified
 when the filesystem was created.  This option allows the user to
 explicitly specify a RAID stride setting to be used by resize2fs instead.
+.TP
+.BI \-z " undo_file"
+Before overwriting a file system block, write the old contents of the block to
+an undo file.  This undo file can be used with e2undo(8) to restore the old
+contents of the file system should something go wrong.  If the empty string is
+passed as the undo_file argument, the undo file will be written to a file named
+resize2fs-\fIdevice\fR.e2undo in the directory specified via the
+\fIE2FSPROGS_UNDO_DIR\fR environment variable.
+
+WARNING: The undo file cannot be used to recover from a power or system crash.
 .SH KNOWN BUGS
 The minimum size of the filesystem as estimated by resize2fs may be
 incorrect, especially for filesystems with 1k and 2k blocksizes.
 .SH KNOWN BUGS
 The minimum size of the filesystem as estimated by resize2fs may be
 incorrect, especially for filesystems with 1k and 2k blocksizes.