Work around lame Ubuntu init scripts / installer bugs

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>
bitmap-optimize
Theodore Ts'o 2007-09-22 20:42:04 -04:00
parent ed773a2638
commit 60702c267d
5 changed files with 50 additions and 4 deletions

6
debian/rules vendored
View File

@ -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

View 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

View 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;

View 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;

View 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) <