]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
e2fsck: Skip time-based checks if the time looks insane or broken_system_clock
authorTheodore Ts'o <tytso@mit.edu>
Thu, 13 May 2010 21:36:36 +0000 (17:36 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 13 May 2010 21:36:36 +0000 (17:36 -0400)
There are broken embedded devices that have system clocks that always
reset to January 1, 1970 whenever they boot (even if no power is
lost).  There are also systems that have super cheap clock crystals
that can be very inaccurate.  So if the option broken_system_clock is
given, disable all time based checks.  E2fsck will also try to detect
incorrect system clock times, and automatically mark the system clock
as insane.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
e2fsck/e2fsck.c
e2fsck/e2fsck.conf.5.in
e2fsck/e2fsck.h
e2fsck/problem.c
e2fsck/super.c
e2fsck/unix.c

index 26f7b5e5831ce043ce7cf974a6005f3cb153fe5e..f1da97a33d39c9c1b31f7e2e6108fd2f03d272d5 100644 (file)
@@ -37,8 +37,11 @@ errcode_t e2fsck_allocate_context(e2fsck_t *ret)
        time_env = getenv("E2FSCK_TIME");
        if (time_env)
                context->now = strtoul(time_env, NULL, 0);
-       else
+       else {
                context->now = time(0);
+               if (context->now < 1262322000) /* January 1 2010 */
+                       context->flags |= E2F_FLAG_TIME_INSANE;
+       }
 
        *ret = context;
        return 0;
@@ -52,7 +55,7 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
 {
        int     i;
 
-       ctx->flags = 0;
+       ctx->flags &= E2F_RESET_FLAGS;
        ctx->lost_and_found = 0;
        ctx->bad_lost_and_found = 0;
        if (ctx->inode_used_map) {
index 64aafd702368fdbcc2f6367741e6f36808b05989..7cb0633f8b1a1b8d3138d2831fd5ac74a178e650 100644 (file)
@@ -118,9 +118,10 @@ For example, the UUID library depends on time not going backwards in
 order for it to be able to make its guarantees about issuing universally
 unique ID's.  Systems with broken system clocks, are well, broken.
 However, broken system clocks, particularly in embedded systems, do
-exist.  If true, e2fsck will not abort a preen check if it detects a
-last mounted or last write time in the superblock in the future.  This
-setting defaults to false.
+exist.  E2fsck will attempt to use hueristics to determine if the time
+can no tbe trusted; and to skip time-based checks if this is true.  If
+this boolean is set to true, then e2fsck will always assume that the
+system clock can not be trusted.
 .TP
 .I clear_test_fs_flag
 This boolean relation controls whether or not 
index e763b89a49fbaf8f235f512854372321faadbaff..79266581a8caa7bc25b3b7f16c07ca1f6bed1718 100644 (file)
@@ -176,6 +176,9 @@ struct resource_track {
 #define E2F_FLAG_RESIZE_INODE  0x0400 /* Request to recreate resize inode */
 #define E2F_FLAG_GOT_DEVSIZE   0x0800 /* Device size has been fetched */
 #define E2F_FLAG_EXITING       0x1000 /* E2fsck exiting due to errors */
+#define E2F_FLAG_TIME_INSANE   0x2000 /* Time is insane */
+
+#define E2F_RESET_FLAGS (E2F_FLAG_TIME_INSANE)
 
 /*
  * Defines for indicating the e2fsck pass number
index 5825f5bcfd0480ffc7f99fa338090e7665c0834c..8032fdae228e9d46969d0412009ae36c83ca4384 100644 (file)
@@ -1746,7 +1746,7 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
        struct e2fsck_problem *ptr;
        struct latch_descr *ldesc = 0;
        const char *message;
-       int             def_yn, answer, ans, broken_system_clock;
+       int             def_yn, answer, ans;
        int             print_answer = 0;
        int             suppress = 0;
 
@@ -1758,15 +1758,6 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
        if (!(ptr->flags & PR_CONFIG)) {
                char    key[9], *new_desc;
 
-               if ((code == PR_0_FUTURE_SB_LAST_MOUNT) ||
-                   (code == PR_0_FUTURE_SB_LAST_WRITE)) {
-                       profile_get_boolean(ctx->profile, "options",
-                                           "broken_system_clock", 0, 0,
-                                           &broken_system_clock);
-                       if (broken_system_clock)
-                               ptr->flags |= PR_PREEN_OK;
-               }
-
                sprintf(key, "0x%06x", code);
 
                profile_get_string(ctx->profile, "problems", key,
index 951f6dbbba13406dba9bea0ab17dcf4909b2447b..accc2f11d447593de8ea856f0fe112ff8538489c 100644 (file)
@@ -464,6 +464,7 @@ void check_super_block(e2fsck_t ctx)
        int     ipg_max;
        int     inode_size;
        int     accept_time_fudge;
+       int     broken_system_clock;
        dgrp_t  i;
        blk_t   should_be;
        struct problem_context  pctx;
@@ -821,11 +822,16 @@ void check_super_block(e2fsck_t ctx)
                            0, accept_time_fudge, &accept_time_fudge);
        ctx->time_fudge = accept_time_fudge ? 86400 : 0;
 
+       profile_get_boolean(ctx->profile, "options", "broken_system_clock",
+                           0, 0, &broken_system_clock);
+
        /*
         * Check to see if the superblock last mount time or last
         * write time is in the future.
         */
-       if (fs->super->s_mtime > (__u32) ctx->now) {
+       if (!broken_system_clock &&
+           !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
+           fs->super->s_mtime > (__u32) ctx->now) {
                pctx.num = fs->super->s_mtime;
                problem = PR_0_FUTURE_SB_LAST_MOUNT;
                if (fs->super->s_mtime <= (__u32) ctx->now + ctx->time_fudge)
@@ -835,7 +841,9 @@ void check_super_block(e2fsck_t ctx)
                        ext2fs_mark_super_dirty(fs);
                }
        }
-       if (fs->super->s_wtime > (__u32) ctx->now) {
+       if (!broken_system_clock &&
+           !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
+           fs->super->s_wtime > (__u32) ctx->now) {
                pctx.num = fs->super->s_wtime;
                problem = PR_0_FUTURE_SB_LAST_WRITE;
                if (fs->super->s_wtime <= (__u32) ctx->now + ctx->time_fudge)
index fd62ce5dd91d464eeb1745cc141c9ef5f4220212..383c651f8d6bbc352203da8278100bd6d1a8333c 100644 (file)
@@ -291,8 +291,13 @@ static void check_if_skip(e2fsck_t ctx)
        long next_check;
        int batt = is_on_batt();
        int defer_check_on_battery;
+       int broken_system_clock;
        time_t lastcheck;
 
+       profile_get_boolean(ctx->profile, "options", "broken_system_clock",
+                           0, 0, &broken_system_clock);
+       if (ctx->flags & E2F_FLAG_TIME_INSANE)
+               broken_system_clock = 1;
        profile_get_boolean(ctx->profile, "options",
                            "defer_check_on_battery", 0, 1,
                            &defer_check_on_battery);
@@ -320,11 +325,12 @@ static void check_if_skip(e2fsck_t ctx)
                if (batt && (fs->super->s_mnt_count <
                             (unsigned) fs->super->s_max_mnt_count*2))
                        reason = 0;
-       } else if (fs->super->s_checkinterval && (ctx->now < lastcheck)) {
+       } else if (!broken_system_clock && fs->super->s_checkinterval &&
+                  (ctx->now < lastcheck)) {
                reason = _(" has filesystem last checked time in the future");
                if (batt)
                        reason = 0;
-       } else if (fs->super->s_checkinterval &&
+       } else if (!broken_system_clock && fs->super->s_checkinterval &&
                   ((ctx->now - lastcheck) >=
                    ((time_t) fs->super->s_checkinterval))) {
                reason = _(" has gone %u days without being checked");
@@ -350,7 +356,7 @@ static void check_if_skip(e2fsck_t ctx)
                if (next_check <= 0)
                        next_check = 1;
        }
-       if (fs->super->s_checkinterval &&
+       if (!broken_system_clock && fs->super->s_checkinterval &&
            ((ctx->now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
                next_check = 1;
        if (next_check <= 5) {
@@ -1433,7 +1439,8 @@ no_journal:
                        } else
                                sb->s_state &= ~EXT2_VALID_FS;
                        sb->s_mnt_count = 0;
-                       sb->s_lastcheck = ctx->now;
+                       if (!(ctx->flags & E2F_FLAG_TIME_INSANE))
+                               sb->s_lastcheck = ctx->now;
                        ext2fs_mark_super_dirty(fs);
                }
        }