Whamcloud - gitweb
e2fsck: Offer to clear the test_fs flag if ext4 is available
authorTheodore Ts'o <tytso@mit.edu>
Mon, 13 Oct 2008 03:09:26 +0000 (23:09 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 13 Oct 2008 03:12:23 +0000 (23:12 -0400)
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
e2fsck/e2fsck.conf.5.in
e2fsck/e2fsck.h
e2fsck/problem.c
e2fsck/problem.h
e2fsck/super.c
e2fsck/util.c

index 9d12171..c66a769 100644 (file)
@@ -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] 
index 9833248..e94b871 100644 (file)
@@ -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,
index 5a3ef79..19e8719 100644 (file)
@@ -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 */
index 24e7ed7..815b37c 100644 (file)
@@ -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
  */
index 1bacbc7..cd2b9f0 100644 (file)
@@ -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.
         */
index efaea4d..6fbe5fc 100644 (file)
  */
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <ctype.h>
+#ifdef __linux__
+#include <sys/utsname.h>
+#endif
 
 #ifdef HAVE_CONIO_H
 #undef HAVE_TERMIOS_H
@@ -22,7 +26,6 @@
 #ifdef HAVE_TERMIOS_H
 #include <termios.h>
 #endif
-#include <stdio.h>
 #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);
+}