From 17390c047f5470eec005c5461a7926d03d6bbbe7 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 7 Jul 2000 04:13:21 +0000 Subject: [PATCH] ChangeLog, Makefile.in, e2fsck.h, journal.c, unix.c: 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 | 18 ++++++++++++++ e2fsck/Makefile.in | 9 ++++--- e2fsck/e2fsck.h | 3 +++ e2fsck/journal.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ e2fsck/unix.c | 35 ++++++++++++++++++++++---- 5 files changed, 128 insertions(+), 9 deletions(-) create mode 100644 e2fsck/journal.c diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index abaa9bc..a3e2d70 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,21 @@ +2000-07-06 Theodore Ts'o + + * 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 * unix.c (e2fsck_update_progress): Only save and check the last diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in index a4e49e6..9cbb3a0 100644 --- a/e2fsck/Makefile.in +++ b/e2fsck/Makefile.in @@ -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 \ diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index b0ba043..6b69ed7 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -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 index 0000000..15b86cc --- /dev/null +++ b/e2fsck/journal.c @@ -0,0 +1,72 @@ +/* + * journal.c --- code for handling the "ext3" journal + */ + +#include + +#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; +} + diff --git a/e2fsck/unix.c b/e2fsck/unix.c index 1675817..9503471 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -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, -- 1.8.3.1