Whamcloud - gitweb
ChangeLog, Makefile.in, e2fsck.h, journal.c, unix.c:
authorTheodore Ts'o <tytso@mit.edu>
Fri, 7 Jul 2000 04:13:21 +0000 (04:13 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 7 Jul 2000 04:13:21 +0000 (04:13 +0000)
  unix.c (check_if_skip): Modify algorithm for checking s_max_mnt_count
   to match with the kernel.  (If s_max_mnt_count is negative, ignore the
   mnt_count check.)
  unix.c (e2fsck_update_progress): Adjust the width of the progress bar
   dynamically, based on the filesystem name that we need to display.
  unix.c (main): If the ext3 needs_recovery flag is set, call
   e2fsck_run_ext3_journal() and then restart the e2fsck run.
  journal.c (e2fsck_run_ext3_journal): New file which contains logic to
   recover the ext3 journal.  This version relies on the kernel being
   able to mount the filesystem in order to run the journal.

e2fsck/ChangeLog
e2fsck/Makefile.in
e2fsck/e2fsck.h
e2fsck/journal.c [new file with mode: 0644]
e2fsck/unix.c

index abaa9bc..a3e2d70 100644 (file)
@@ -1,3 +1,21 @@
+2000-07-06  Theodore Ts'o  <tytso@valinux.com>
+
+       * unix.c (check_if_skip): Modify algorithm for checking
+               s_max_mnt_count to match with the kernel.  (If
+               s_max_mnt_count is negative, ignore the mnt_count check.)
+
+       * unix.c (e2fsck_update_progress): Adjust the width of the
+               progress bar dynamically, based on the filesystem name
+               that we need to display.
+
+       * unix.c (main): If the ext3 needs_recovery flag is set, call
+               e2fsck_run_ext3_journal() and then restart the e2fsck run.
+
+       * journal.c (e2fsck_run_ext3_journal): New file which contains
+               logic to recover the ext3 journal.  This version relies on
+               the kernel being able to mount the filesystem in order to
+               run the journal.
+
 2000-07-05  Theodore Ts'o  <tytso@valinux.com>
 
        * unix.c (e2fsck_update_progress): Only save and check the last
index a4e49e6..9cbb3a0 100644 (file)
@@ -55,15 +55,15 @@ PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) \
 #MCHECK= -DMCHECK
 
 OBJS= unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o pass3.o pass4.o \
-       pass5.o swapfs.o badblocks.o util.o dirinfo.o ehandler.o \
+       pass5.o journal.o swapfs.o badblocks.o util.o dirinfo.o ehandler.o \
        problem.o message.o $(MTRACE_OBJ)
 
 PROFILED_OBJS= profiled/unix.o profiled/e2fsck.o profiled/super.o \
        profiled/pass1.o profiled/pass1b.o \
        profiled/pass2.o profiled/pass3.o profiled/pass4.o profiled/pass5.o \
-       profiled/badblocks.o profiled/util.o profiled/dirinfo.o \
-       profiled/ehandler.o profiled/message.o profiled/problem.o \
-       profiled/swapfs.o
+       profiled/journal.o profiled/badblocks.o profiled/util.o \
+       profiled/dirinfo.o profiled/ehandler.o profiled/message.o \
+       profiled/problem.o profiled/swapfs.o
 
 SRCS= $(srcdir)/e2fsck.c \
        $(srcdir)/super.c \
@@ -73,6 +73,7 @@ SRCS= $(srcdir)/e2fsck.c \
        $(srcdir)/pass3.c \
        $(srcdir)/pass4.c \
        $(srcdir)/pass5.c \
+       $(srcdir)/journal.c \
        $(srcdir)/badblocks.c \
        $(srcdir)/util.c \
        $(srcdir)/unix.c \
index b0ba043..6b69ed7 100644 (file)
@@ -282,6 +282,9 @@ extern struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control);
 extern const char *ehandler_operation(const char *op);
 extern void ehandler_init(io_channel channel);
 
+/* journal.c */
+extern int e2fsck_run_ext3_journal(const char *device);
+
 /* pass1.c */
 extern void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
 extern int e2fsck_pass1_check_device_inode(struct ext2_inode *inode);
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
new file mode 100644 (file)
index 0000000..15b86cc
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * journal.c --- code for handling the "ext3" journal
+ */
+
+#include <errno.h>
+
+#include "e2fsck.h"
+
+/*
+ * This is a list of directories to try.  The first element may get
+ * replaced by a mktemp'ed generated temp directory if possible.
+ */
+static char *dirlist[] = { "/mnt", "/tmp", "/root", "/boot", 0 };
+
+/*
+ * This function attempts to mount and unmount an ext3 filesystem,
+ * which is a cheap way to force the kernel to run the journal and
+ * handle the recovery for us.
+ */
+int e2fsck_run_ext3_journal(const char *device)
+{
+       int     ret = 0;
+       char    **cpp, *dir;
+       char    template[] = "/tmp/ext3.XXXXXX";
+       char    *tmpdir;
+
+       /*
+        * First try to make a temporary directory.  This may fail if
+        * the root partition is still mounted read-only.
+        */
+       tmpdir = mktemp(template);
+       if (tmpdir) {
+               ret = mkdir(template, 0700);
+               if (ret)
+                       tmpdir = 0;
+       }
+       if (tmpdir) {
+               ret = mount(device, tmpdir, "ext3", 0xC0ED, NULL);
+               if (ret) {
+                       ret = errno;
+                       rmdir(tmpdir);
+                       return (ret);
+               }
+       } else {
+               /*
+                * OK, creating a temporary directory didn't work.
+                * Let's try a list of possible temporary mountpoints.
+                */
+               for (cpp = dirlist; dir = *cpp; cpp++) {
+                       ret = mount(device, dir, "ext3", 0xC0ED, NULL);
+                       if (ret == 0)
+                               break;
+               }
+               if (!dir)
+                       return errno;
+       }
+
+       /*
+        * Now that it mounted cleanly, the filesystem will have been
+        * recovered, so we can now unmount it.
+        */
+       ret = umount(device);
+       if (ret)
+               return errno;
+       /*
+        * Remove the temporary directory, if it was created.
+        */
+       if (tmpdir)
+               rmdir(tmpdir);
+       return 0;
+}
+
index 1675817..9503471 100644 (file)
@@ -260,8 +260,9 @@ static void check_if_skip(e2fsck_t ctx)
                reason = _("contains a file system with errors");
        else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
                reason = _("was not cleanly unmounted");
-       else if (fs->super->s_mnt_count >=
-                (unsigned) fs->super->s_max_mnt_count)
+       else if ((fs->super->s_max_mnt_count >= 0) &&
+                (fs->super->s_mnt_count >=
+                 (unsigned) fs->super->s_max_mnt_count))
                reason = _("has reached maximal mount count");
        else if (fs->super->s_checkinterval &&
                 time(0) >= (fs->super->s_lastcheck +
@@ -290,7 +291,6 @@ struct percent_tbl {
 struct percent_tbl e2fsck_tbl = {
        5, { 0, 70, 90, 92,  95, 100 }
 };
-static int dpywidth = 50;
 static char bar[] =
        "==============================================================="
        "===============================================================";
@@ -330,6 +330,7 @@ static int e2fsck_update_progress(e2fsck_t ctx, int pass,
        float percent;
        int     tick;
        struct timeval  tv;
+       static int dpywidth = 0;
 
        if (pass == 0)
                return 0;
@@ -340,6 +341,10 @@ static int e2fsck_update_progress(e2fsck_t ctx, int pass,
        } else {
                if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
                        return 0;
+               if (dpywidth == 0) {
+                       dpywidth = 66 - strlen(ctx->device_name);
+                       dpywidth = 8 * (dpywidth / 8);
+               }
                /*
                 * Calculate the new progress position.  If the
                 * percentage hasn't changed, then we skip out right
@@ -701,7 +706,10 @@ restart:
        io_ptr = test_io_manager;
        test_io_backing_manager = unix_io_manager;
 #endif
-       flags = (ctx->options & E2F_OPT_READONLY) ? 0 : EXT2_FLAG_RW;
+       flags = 0;
+       if ((ctx->options & E2F_OPT_READONLY) == 0)
+               flags |= EXT2_FLAG_RW;
+
        if (ctx->superblock && blocksize) {
                retval = ext2fs_open(ctx->filesystem_name, flags,
                                     ctx->superblock, blocksize, io_ptr, &fs);
@@ -769,11 +777,28 @@ restart:
                fatal_error(ctx, _("Get a newer version of e2fsck!"));
        }
 #endif
+       s = (struct ext2fs_sb *) fs->super;
+       /*
+        * Check to see if we need to do ext3-style recovery.  If so,
+        * do it, and then restart the fsck.
+        */
+       if (s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
+               printf("%s: reading journal for ext3 filesystem...\n",
+                      ctx->filesystem_name);
+               ext2fs_close(fs);
+               retval = e2fsck_run_ext3_journal(ctx->filesystem_name);
+               if (retval) {
+                       com_err(ctx->program_name, retval,
+                               ": couldn't load ext3 journal for %s",
+                               ctx->filesystem_name);
+                       exit(FSCK_ERROR);
+               }
+               goto restart;
+       }
        /*
         * Check for compatibility with the feature sets.  We need to
         * be more stringent than ext2fs_open().
         */
-       s = (struct ext2fs_sb *) fs->super;
        if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
            (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
                com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,