Merge branch 'maint'

This commit is contained in:
Theodore Ts'o 2007-10-06 12:41:26 -04:00
commit 2628a1d3e1
22 changed files with 180 additions and 19 deletions

6
debian/rules vendored
View File

@ -340,6 +340,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

@ -331,6 +331,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;
@ -455,6 +456,7 @@ void e2fsck_rehash_directories(e2fsck_t ctx);
/* super.c */
void check_super_block(e2fsck_t ctx);
int check_backup_super_block(e2fsck_t ctx);
/* util.c */
extern void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,

View File

@ -454,6 +454,7 @@ static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
sb->s_journal_inum = 0;
ctx->flags |= E2F_FLAG_JOURNAL_INODE;
ctx->fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
e2fsck_clear_recover(ctx, 1);
return 0;
}
@ -753,6 +754,7 @@ no_has_journal:
e2fsck_clear_recover(ctx, force_fsck);
} else if (!(ctx->options & E2F_OPT_READONLY)) {
sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
ctx->fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
ext2fs_mark_super_dirty(ctx->fs);
}
}

View File

@ -267,6 +267,7 @@ void e2fsck_pass2(e2fsck_t ctx)
fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
sb->s_feature_ro_compat |=
EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
ext2fs_mark_super_dirty(fs);
}
if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
@ -280,6 +281,7 @@ void e2fsck_pass2(e2fsck_t ctx)
if (fs->flags & EXT2_FLAG_RW) {
sb->s_feature_ro_compat &=
~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
ext2fs_mark_super_dirty(fs);
}
}

View File

@ -335,12 +335,12 @@ static struct e2fsck_problem problem_table[] = {
/* Last mount time is in the future */
{ PR_0_FUTURE_SB_LAST_MOUNT,
N_("@S last mount time is in the future. "),
PROMPT_FIX, PR_PREEN_OK },
PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
/* Last write time is in the future */
{ PR_0_FUTURE_SB_LAST_WRITE,
N_("@S last write time is in the future. "),
PROMPT_FIX, PR_PREEN_OK },
PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
{ PR_0_EXTERNAL_JOURNAL_HINT,
N_("@S hint for external superblock @s %X. "),

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;
@ -681,7 +682,7 @@ void check_super_block(e2fsck_t ctx)
fs->super->s_feature_incompat &=
~EXT2_FEATURE_INCOMPAT_FILETYPE;
ext2fs_mark_super_dirty(fs);
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
}
}
@ -699,6 +700,7 @@ void check_super_block(e2fsck_t ctx)
fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
ext2fs_update_dynamic_rev(fs);
ext2fs_mark_super_dirty(fs);
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
}
check_resize_inode(ctx);
@ -711,18 +713,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;
@ -747,3 +770,61 @@ void check_super_block(e2fsck_t ctx)
return;
}
/*
* Check to see if we should backup the master sb to the backup super
* blocks.
*/
int check_backup_super_block(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
ext2_filsys tfs = 0;
io_manager io_ptr;
errcode_t retval;
dgrp_t g;
blk_t sb;
int ret = 0;
/*
* If we are already writing out the backup blocks, then we
* don't need to test. Also, if the filesystem is invalid, or
* the check was aborted or cancelled, we also don't want to
* do the backup. If the filesystem was opened read-only then
* we can't do the backup.
*/
if (((fs->flags & EXT2_FLAG_MASTER_SB_ONLY) == 0) ||
!ext2fs_test_valid(fs) ||
(fs->super->s_state & EXT2_ERROR_FS) ||
(ctx->flags & (E2F_FLAG_ABORT | E2F_FLAG_CANCEL)) ||
(ctx->options & E2F_OPT_READONLY))
return 0;
for (g = 1; g < fs->group_desc_count; g++) {
if (!ext2fs_bg_has_super(fs, g))
continue;
sb = fs->super->s_first_data_block +
(g * fs->super->s_blocks_per_group);
retval = ext2fs_open(ctx->filesystem_name, 0,
sb, fs->blocksize,
fs->io->manager, &tfs);
if (retval) {
tfs = 0;
continue;
}
#define SUPER_DIFFERENT(x) (fs->super->x != tfs->super->x)
if (SUPER_DIFFERENT(s_feature_compat) ||
SUPER_DIFFERENT(s_feature_incompat) ||
SUPER_DIFFERENT(s_feature_ro_compat) ||
SUPER_DIFFERENT(s_blocks_count) ||
SUPER_DIFFERENT(s_inodes_count) ||
memcmp(fs->super->s_uuid, tfs->super->s_uuid,
sizeof(fs->super->s_uuid)))
ret = 1;
ext2fs_close(tfs);
break;
}
return ret;
}

View File

@ -258,6 +258,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,
@ -268,11 +269,16 @@ static void check_if_skip(e2fsck_t ctx)
if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file || cflag)
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");
else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
reason = _(" was not cleanly unmounted");
else if (check_backup_super_block(ctx))
reason = _(" primary superblock features different from backup");
else if ((fs->super->s_max_mnt_count > 0) &&
(fs->super->s_mnt_count >=
(unsigned) fs->super->s_max_mnt_count)) {
@ -282,8 +288,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) <
@ -840,7 +845,7 @@ static const char *my_ver_date = E2FSPROGS_DATE;
int main (int argc, char *argv[])
{
errcode_t retval = 0;
errcode_t retval = 0, orig_retval = 0;
int exit_value = FSCK_OK;
ext2_filsys fs = 0;
io_manager io_ptr;
@ -940,18 +945,23 @@ restart:
if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
!(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
((retval == EXT2_ET_BAD_MAGIC) ||
(retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
((retval == 0) && ext2fs_check_desc(fs)))) {
if (!fs || (fs->group_desc_count > 1)) {
printf(_("%s trying backup blocks...\n"),
retval ? _("Couldn't find ext2 superblock,") :
printf(_("%s: %s trying backup blocks...\n"),
ctx->program_name,
retval ? _("Superblock invalid,") :
_("Group descriptors look bad..."));
get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
if (fs)
ext2fs_close(fs);
orig_retval = retval;
goto restart;
}
}
if (retval) {
if (orig_retval)
retval = orig_retval;
com_err(ctx->program_name, retval, _("while trying to open %s"),
ctx->filesystem_name);
if (retval == EXT2_ET_REV_TOO_HIGH) {
@ -1203,6 +1213,7 @@ restart:
if (journal_size < 0) {
fs->super->s_feature_compat &=
~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
com_err(ctx->program_name, 0,
_("Couldn't determine journal size"));
goto no_journal;
@ -1242,6 +1253,10 @@ no_journal:
}
if (run_result & E2F_FLAG_ABORT)
fatal_error(ctx, _("aborted"));
if (check_backup_super_block(ctx)) {
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
ext2fs_mark_super_dirty(fs);
}
#ifdef MTRACE
mtrace_print("Cleanup");

View File

@ -847,8 +847,9 @@ static struct blkid_magic type_array[] = {
{ "vfat", 0, 0x36, 5, "MSDOS", probe_fat },
{ "vfat", 0, 0x36, 8, "FAT16 ", probe_fat },
{ "vfat", 0, 0x36, 8, "FAT12 ", probe_fat },
{ "vfat", 0, 0, 2, "\353\220", probe_fat_nomagic },
{ "vfat", 0, 0, 1, "\353", probe_fat_nomagic },
{ "vfat", 0, 0, 1, "\351", probe_fat_nomagic },
{ "vfat", 0, 0x1fe, 2, "\125\252", probe_fat_nomagic },
{ "minix", 1, 0x10, 2, "\177\023", 0 },
{ "minix", 1, 0x10, 2, "\217\023", 0 },
{ "minix", 1, 0x10, 2, "\150\044", 0 },

View File

@ -66,10 +66,15 @@ static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
void *priv_data)
{
struct dir_context *ctx;
int ret;
ctx = (struct dir_context *) priv_data;
ctx->dir = db_info->ino;
ctx->errcode = 0;
return ext2fs_process_dir_block(fs, &db_info->blk,
db_info->blockcnt, 0, 0, priv_data);
ret = ext2fs_process_dir_block(fs, &db_info->blk,
db_info->blockcnt, 0, 0, priv_data);
if ((ret & BLOCK_ABORT) && !ctx->errcode)
return DBLIST_ABORT;
return 0;
}

View File

@ -235,6 +235,10 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
retval = EXT2_ET_CORRUPT_SUPERBLOCK;
goto cleanup;
}
if (EXT2_INODE_SIZE(fs->super) < EXT2_GOOD_OLD_INODE_SIZE) {
retval = EXT2_ET_CORRUPT_SUPERBLOCK;
goto cleanup;
}
fs->fragsize = EXT2_FRAG_SIZE(fs->super);
fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group *
EXT2_INODE_SIZE(fs->super) +

View File

@ -867,6 +867,16 @@ static int ignore(struct fs_info *fs)
if (fs->passno == 0)
return 1;
/*
* If this is a bind mount, ignore it.
*/
if (opt_in_list("bind", fs->opts)) {
fprintf(stderr,
_("%s: skipping bad line in /etc/fstab: bind mount with nonzero fsck pass number\n"),
fs->mountpt);
return 1;
}
interpret_type(fs);
/*

View File

@ -1,3 +1,4 @@
../e2fsck/e2fsck: Superblock invalid, trying backup blocks...
../e2fsck/e2fsck: The ext2 superblock is corrupt while trying to open ./test.img
The superblock could not be read or does not describe a correct ext2

View File

@ -1,4 +1,4 @@
Group descriptors look bad... trying backup blocks...
../e2fsck/e2fsck: Group descriptors look bad... trying backup blocks...
Inode table for group 1 is not in group. (block 0)
WARNING: SEVERE DATA LOSS POSSIBLE.
Relocate? yes

View File

@ -1,4 +1,4 @@
Group descriptors look bad... trying backup blocks...
../e2fsck/e2fsck: Group descriptors look bad... trying backup blocks...
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity

View File

@ -0,0 +1,10 @@
../e2fsck/e2fsck: Superblock invalid, trying backup blocks...
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/2512 files (9.1% non-contiguous), 415/10000 blocks
Exit status is 1

View File

@ -0,0 +1,7 @@
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
test_filesys: 11/2512 files (9.1% non-contiguous), 415/10000 blocks
Exit status is 0

Binary file not shown.

View File

@ -0,0 +1 @@
superblock with a zero inode size

View File

@ -1,4 +1,4 @@
Couldn't find ext2 superblock, trying backup blocks...
../e2fsck/e2fsck: Superblock invalid, trying backup blocks...
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity

View File

@ -94,7 +94,8 @@ $TUNE2FS -c 20 -U clear $TMPFILE >/dev/null 2>&1
echo dumpe2fs test.img >> $OUT
$DUMPE2FS $TMPFILE 2>&1 | sed -f $cmd_dir/filter_dumpe2fs >> $OUT
rm -f $test_name.ok $test_name.failed
rm -f $test_name.ok $test_name.failed $TMPFILE
cmp -s $OUT $EXP
status=$?

View File

@ -80,8 +80,7 @@ $TUNE2FS -c 20 -U clear $TMPFILE >/dev/null 2>&1
echo dumpe2fs test.img >> $OUT
$DUMPE2FS $TMPFILE 2>&1 | sed -f $cmd_dir/filter_dumpe2fs >> $OUT
rm -f $test_name.ok $test_name.failed
rm -f $test_name.ok $test_name.failed $TMPFILE
cmp -s $OUT $EXP
status=$?