+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
#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 \
$(srcdir)/pass3.c \
$(srcdir)/pass4.c \
$(srcdir)/pass5.c \
+ $(srcdir)/journal.c \
$(srcdir)/badblocks.c \
$(srcdir)/util.c \
$(srcdir)/unix.c \
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);
--- /dev/null
+/*
+ * 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;
+}
+
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 +
struct percent_tbl e2fsck_tbl = {
5, { 0, 70, 90, 92, 95, 100 }
};
-static int dpywidth = 50;
static char bar[] =
"==============================================================="
"===============================================================";
float percent;
int tick;
struct timeval tv;
+ static int dpywidth = 0;
if (pass == 0)
return 0;
} 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
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);
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,