From 80875db58a6db58e3e2f01caf1adabca068d3ffb Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 12 Oct 2008 23:09:26 -0400 Subject: [PATCH] e2fsck: Offer to clear the test_fs flag if ext4 is available Signed-off-by: "Theodore Ts'o" --- e2fsck/e2fsck.conf.5.in | 5 +++ e2fsck/e2fsck.h | 2 ++ e2fsck/problem.c | 4 +++ e2fsck/problem.h | 3 ++ e2fsck/super.c | 19 ++++++++++- e2fsck/util.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 117 insertions(+), 2 deletions(-) diff --git a/e2fsck/e2fsck.conf.5.in b/e2fsck/e2fsck.conf.5.in index 9d12171..c66a769 100644 --- a/e2fsck/e2fsck.conf.5.in +++ b/e2fsck/e2fsck.conf.5.in @@ -106,6 +106,11 @@ This boolean relation controls whether or not the interval between filesystem checks (either based on time or number of mounts) should be doubled if the system is running on battery. It defaults to true. +.TP +.I clear_test_fs_flag +This boolean relation controls whether or not e2fsck will offer to clear +the test_fs flag if the ext4 filesystem is available on the system. It +defaults to true. .SH THE [problems] STANZA Each tag in the .I [problems] diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 9833248..e94b871 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -481,6 +481,8 @@ extern void preenhalt(e2fsck_t ctx); extern char *string_copy(e2fsck_t ctx, const char *str, int len); extern errcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num, blk_t *ret_blk, int *ret_count); +extern int fs_proc_check(const char *fs_name); +extern int check_for_modules(const char *fs_name); #ifdef RESOURCE_TRACK extern void print_resource_track(const char *desc, struct resource_track *track, diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 5a3ef79..19e8719 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -381,6 +381,10 @@ static struct e2fsck_problem problem_table[] = { N_("Journal transaction %i was corrupt, replay was aborted.\n"), PROMPT_NONE, 0 }, + { PR_0_CLEAR_TESTFS_FLAG, + N_("The test_fs flag is set (and ext4 is available). "), + PROMPT_CLEAR, PR_PREEN_OK }, + /* Pass 1 errors */ /* Pass 1: Checking inodes, blocks, and sizes */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 24e7ed7..815b37c 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -214,6 +214,9 @@ struct problem_context { /* Journal transaction found corrupt */ #define PR_0_JNL_TXN_CORRUPT 0x00003A +/* The test_fs filesystem flag is set and ext4 is available */ +#define PR_0_CLEAR_TESTFS_FLAG 0x00003B + /* * Pass 1 errors */ diff --git a/e2fsck/super.c b/e2fsck/super.c index 1bacbc7..cd2b9f0 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -468,7 +468,7 @@ void check_super_block(e2fsck_t ctx) struct problem_context pctx; blk_t free_blocks = 0; ino_t free_inodes = 0; - int csum_flag; + int csum_flag, clear_test_fs_flag; inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super); ipg_max = inodes_per_block * (blocks_per_group - 4); @@ -732,6 +732,23 @@ void check_super_block(e2fsck_t ctx) #endif /* + * Check to see if we should disable the test_fs flag + */ + profile_get_boolean(ctx->profile, "options", + "clear_test_fs_flag", 0, 1, + &clear_test_fs_flag); + if (!(ctx->options & E2F_OPT_READONLY) && + clear_test_fs_flag && + (fs->super->s_flags & EXT2_FLAGS_TEST_FILESYS) && + (fs_proc_check("ext4") || check_for_modules("ext4"))) { + if (fix_problem(ctx, PR_0_CLEAR_TESTFS_FLAG, &pctx)) { + fs->super->s_flags &= ~EXT2_FLAGS_TEST_FILESYS; + ext2fs_mark_super_dirty(fs); + fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; + } + } + + /* * For the Hurd, check to see if the filetype option is set, * since it doesn't support it. */ diff --git a/e2fsck/util.c b/e2fsck/util.c index efaea4d..6fbe5fc 100644 --- a/e2fsck/util.c +++ b/e2fsck/util.c @@ -10,9 +10,13 @@ */ #include +#include #include #include #include +#ifdef __linux__ +#include +#endif #ifdef HAVE_CONIO_H #undef HAVE_TERMIOS_H @@ -22,7 +26,6 @@ #ifdef HAVE_TERMIOS_H #include #endif -#include #endif #ifdef HAVE_MALLOC_H @@ -594,3 +597,84 @@ errcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num, } return 0; } + +/* + * Check to see if a filesystem is in /proc/filesystems. + * Returns 1 if found, 0 if not + */ +int fs_proc_check(const char *fs_name) +{ + FILE *f; + char buf[80], *cp, *t; + + f = fopen("/proc/filesystems", "r"); + if (!f) + return (0); + while (!feof(f)) { + if (!fgets(buf, sizeof(buf), f)) + break; + cp = buf; + if (!isspace(*cp)) { + while (*cp && !isspace(*cp)) + cp++; + } + while (*cp && isspace(*cp)) + cp++; + if ((t = strchr(cp, '\n')) != NULL) + *t = 0; + if ((t = strchr(cp, '\t')) != NULL) + *t = 0; + if ((t = strchr(cp, ' ')) != NULL) + *t = 0; + if (!strcmp(fs_name, cp)) { + fclose(f); + return (1); + } + } + fclose(f); + return (0); +} + +/* + * Check to see if a filesystem is available as a module + * Returns 1 if found, 0 if not + */ +int check_for_modules(const char *fs_name) +{ +#ifdef __linux__ + struct utsname uts; + FILE *f; + char buf[1024], *cp, *t; + int i; + + if (uname(&uts)) + return (0); + snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release); + + f = fopen(buf, "r"); + if (!f) + return (0); + while (!feof(f)) { + if (!fgets(buf, sizeof(buf), f)) + break; + if ((cp = strchr(buf, ':')) != NULL) + *cp = 0; + else + continue; + if ((cp = strrchr(buf, '/')) != NULL) + cp++; + i = strlen(cp); + if (i > 3) { + t = cp + i - 3; + if (!strcmp(t, ".ko")) + *t = 0; + } + if (!strcmp(cp, fs_name)) { + fclose(f); + return (1); + } + } + fclose(f); +#endif /* __linux__ */ + return (0); +} -- 1.8.3.1