]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
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 9d12171610c94dd1bbedaea021c2a42775f0df62..c66a7698afc694411646b810399a4a9cb02a2a45 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 9833248f2dec2b2ad30af2bcef9a80bd6ecf4016..e94b8716f9102b399c72cdf765f77e1a14cd9ecd 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 5a3ef79af637f41c45769a26df33a6ddfb5e1fcb..19e87193fc2b96065829e9fa42b1b2485cf9b343 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 24e7ed708548ad9cbc69ae7ac7b047fd0a08209b..815b37c4ac211aea58b1878fbddfb00660dd06d1 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 1bacbc74a5ab78e45192f63561667d91145381b9..cd2b9f0f5b451c27eb28bb23e689f72acafb314c 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);
@@ -731,6 +731,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 efaea4dc9e10e418dc71832dbd470c3ae81dee36..6fbe5fc8445b75d9dc0a961e80b018675fce4427 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);
+}