OSDN Git Service

Work around lame Ubuntu init scripts / installer bugs
authorTheodore Ts'o <tytso@mit.edu>
Sun, 23 Sep 2007 00:42:04 +0000 (20:42 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 23 Sep 2007 00:43:11 +0000 (20:43 -0400)
The Ubuntu init scripts don't properly set the system time correctly
from hardware clock if the hardware clock is configured to tick local
time instead of GMT time.

Work around this as best as we can by providing an option in
/etc/e2fsck.conf which can be set on Ubuntu systems:

[options]
buggy_init_scripts = 1

Addresses-Debian-Bug: #441093
Addresses-Ubuntu-Bug: #131201

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

index bb3f1d3..842965e 100755 (executable)
@@ -342,6 +342,12 @@ binary-arch: install install-udeb
 
        $(INSTALL) -d ${debdir}/uuid-dev/usr/share/doc/libuuid${UUID_SOVERSION}
 
+       if test -f /etc/lsb-release && \
+               grep -q DISTRIB_ID=Ubuntu /etc/lsb-release; then \
+       $(INSTALL) -p -m 0644 e2fsck/e2fsck.conf.ubuntu \
+               ${debdir}/e2fsprogs/etc/e2fsck.conf; \
+       fi
+
        dh_installinfo -pcomerr-dev ${stdbuilddir}/lib/et/com_err.info
        dh_installinfo -pe2fslibs-dev ${stdbuilddir}/doc/libext2fs.info
 
index 8c580d2..9d12171 100644 (file)
@@ -86,6 +86,20 @@ If this relation is set to a boolean value of true, then if the user
 interrupts e2fsck using ^C, and the filesystem is not explicitly flagged
 as containing errors, e2fsck will exit with an exit status of 0 instead
 of 32.  This setting defaults to false.
+.TP
+.I buggy_init_scripts
+Some buggy distributions (such as Ubuntu) have init scripts and/or
+installers which fail to correctly set the system clock before running
+e2fsck and/or formatting the filesystem initially.  Normally this
+happens because the hardware clock is ticking localtime, instead of the
+more proper and less error-prone UTC time.  So while the kernel is
+booting, the system time (which in Linux systems always ticks in UTC
+time) is set from the hardware clock, but since the hardware clock is
+ticking localtime, the system time is incorrect.  Unfortunately, some
+buggy distributions do not correct this before running e2fsck.  If this
+option is set to a boolean value of true, we attempt to work around this
+situation by allowing the superblock last write time, last mount time,
+and last check time to be in the future by up to 24 hours.
 .TP 
 .I defer_check_on_battery
 This boolean relation controls whether or not the interval between 
index 25a9773..57adb2a 100644 (file)
@@ -329,6 +329,7 @@ struct e2fsck_struct {
 
        /* misc fields */
        time_t now;
+       time_t time_fudge;      /* For working around buggy init scripts */
        int ext_attr_ver;
        profile_t       profile;
        int blocks_per_page;
index 00a131c..e90e961 100644 (file)
@@ -463,6 +463,7 @@ void check_super_block(e2fsck_t ctx)
        int     inodes_per_block;
        int     ipg_max;
        int     inode_size;
+       int     buggy_init_scripts;
        dgrp_t  i;
        blk_t   should_be;
        struct problem_context  pctx;
@@ -711,18 +712,39 @@ void check_super_block(e2fsck_t ctx)
                ext2fs_mark_super_dirty(fs);
        }
 
+       /*
+        * Some buggy distributions (such as Ubuntu) have init scripts
+        * and/or installers which fail to correctly set the system
+        * clock before running e2fsck and/or formatting the
+        * filesystem initially.  Normally this happens because the
+        * hardware clock is ticking localtime, instead of the more
+        * proper and less error-prone UTC time.  So while the kernel
+        * is booting, the system time (which in Linux systems always
+        * ticks in UTC time) is set from the hardware clock, but
+        * since the hardware clock is ticking localtime, the system
+        * time is incorrect.  Unfortunately, some buggy distributions
+        * do not correct this before running e2fsck.  If this option
+        * is set to a boolean value of true, we attempt to work
+        * around this situation by allowing the superblock last write
+        * time, last mount time, and last check time to be in the
+        * future by up to 24 hours.
+        */
+       profile_get_boolean(ctx->profile, "options", "buggy_init_scripts",
+                           0, 0, &buggy_init_scripts);
+       ctx->time_fudge = buggy_init_scripts ? 86400 : 0;
+
        /* 
         * 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 (fs->super->s_mtime > (__u32) ctx->now + ctx->time_fudge) {
                pctx.num = fs->super->s_mtime;
                if (fix_problem(ctx, PR_0_FUTURE_SB_LAST_MOUNT, &pctx)) {
                        fs->super->s_mtime = ctx->now;
                        ext2fs_mark_super_dirty(fs);
                }
        }
-       if (fs->super->s_wtime > (__u32) ctx->now) {
+       if (fs->super->s_wtime > (__u32) ctx->now + ctx->time_fudge) {
                pctx.num = fs->super->s_wtime;
                if (fix_problem(ctx, PR_0_FUTURE_SB_LAST_WRITE, &pctx)) {
                        fs->super->s_wtime = ctx->now;
index 950e2d4..72545da 100644 (file)
@@ -260,6 +260,7 @@ static void check_if_skip(e2fsck_t ctx)
        long next_check;
        int batt = is_on_batt();
        int defer_check_on_battery;
+       time_t lastcheck;
 
        profile_get_boolean(ctx->profile, "options",
                            "defer_check_on_battery", 0, 1, 
@@ -271,6 +272,9 @@ static void check_if_skip(e2fsck_t ctx)
            cflag || swapfs)
                return;
        
+       lastcheck = fs->super->s_lastcheck;
+       if (lastcheck > ctx->now)
+               lastcheck -= ctx->time_fudge;
        if ((fs->super->s_state & EXT2_ERROR_FS) ||
            !ext2fs_test_valid(fs))
                reason = _(" contains a file system with errors");
@@ -285,8 +289,7 @@ static void check_if_skip(e2fsck_t ctx)
                             (unsigned) fs->super->s_max_mnt_count*2))
                        reason = 0;
        } else if (fs->super->s_checkinterval &&
-                  ((ctx->now - fs->super->s_lastcheck) >= 
-                   fs->super->s_checkinterval)) {
+                  ((ctx->now - lastcheck) >= fs->super->s_checkinterval)) {
                reason = _(" has gone %u days without being checked");
                reason_arg = (ctx->now - fs->super->s_lastcheck)/(3600*24);
                if (batt && ((ctx->now - fs->super->s_lastcheck) <