}
if (retval) {
com_err("release_inode_blocks", retval,
- _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
+ _("while calling ext2fs_adjust_ea_refcount for inode %d"),
ino);
return 1;
}
if (!inode.i_links_count) {
ext2fs_inode_alloc_stats2(fs, ino, -1,
LINUX_S_ISDIR(inode.i_mode));
- inode.i_dtime = time(0);
+ inode.i_dtime = ctx->now;
} else {
inode.i_dtime = 0;
}
errcode_t retval;
clear_problem_context(&pctx);
- pctx.ino = EXT2_RESIZE_INO;
- retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
- if (retval) {
- ctx->flags |= E2F_FLAG_RESIZE_INODE;
- return;
- }
/*
- * If the resize inode feature isn't set, then
- * s_reserved_gdt_blocks must be zero, and the resize inode
- * must be cleared.
+ * If the resize inode feature isn't set, then
+ * s_reserved_gdt_blocks must be zero.
*/
if (!(fs->super->s_feature_compat &
EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
ext2fs_mark_super_dirty(fs);
}
}
+ }
+
+ /* Read the resize inode */
+ pctx.ino = EXT2_RESIZE_INO;
+ retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
+ if (retval) {
+ if (fs->super->s_feature_compat &
+ EXT2_FEATURE_COMPAT_RESIZE_INODE)
+ ctx->flags |= E2F_FLAG_RESIZE_INODE;
+ return;
+ }
+
+ /*
+ * If the resize inode feature isn't set, check to make sure
+ * the resize inode is cleared; then we're done.
+ */
+ if (!(fs->super->s_feature_compat &
+ EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
for (i=0; i < EXT2_N_BLOCKS; i++) {
if (inode.i_block[i])
break;
}
return;
}
+
/*
* The resize inode feature is enabled; check to make sure the
* only block in use is the double indirect block
if (i != EXT2_DIND_BLOCK && inode.i_block[i])
break;
}
- if ((i < EXT2_N_BLOCKS) || !blk ||
+ if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
+ !(inode.i_mode & LINUX_S_IFREG) ||
(blk < fs->super->s_first_data_block ||
blk >= fs->super->s_blocks_count)) {
resize_inode_invalid:
blk_t bpg_max;
int inodes_per_block;
int ipg_max;
+ int inode_size;
dgrp_t i;
blk_t should_be;
struct problem_context pctx;
check_super_value(ctx, "reserved_gdt_blocks",
sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
fs->blocksize/4);
-
+ inode_size = EXT2_INODE_SIZE(sb);
+ check_super_value(ctx, "inode_size",
+ inode_size, MIN_CHECK | MAX_CHECK,
+ EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
+ if (inode_size & (inode_size - 1)) {
+ pctx.num = inode_size;
+ pctx.str = "inode_size";
+ fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
+ return;
+ }
+
if (!ctx->num_blocks) {
pctx.errcode = e2fsck_get_device_size(ctx);
if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
* Verify the group descriptors....
*/
first_block = sb->s_first_data_block;
- last_block = first_block + blocks_per_group;
for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
pctx.group = i;
-
- if (i == fs->group_desc_count - 1)
- last_block = sb->s_blocks_count;
+
+ first_block = ext2fs_group_first_block(fs, i);
+ last_block = ext2fs_group_last_block(fs, i);
+
if ((gd->bg_block_bitmap < first_block) ||
- (gd->bg_block_bitmap >= last_block)) {
+ (gd->bg_block_bitmap > last_block)) {
pctx.blk = gd->bg_block_bitmap;
if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
gd->bg_block_bitmap = 0;
ctx->invalid_bitmaps++;
}
if ((gd->bg_inode_bitmap < first_block) ||
- (gd->bg_inode_bitmap >= last_block)) {
+ (gd->bg_inode_bitmap > last_block)) {
pctx.blk = gd->bg_inode_bitmap;
if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
gd->bg_inode_bitmap = 0;
}
if ((gd->bg_inode_table < first_block) ||
((gd->bg_inode_table +
- fs->inode_blocks_per_group - 1) >= last_block)) {
+ fs->inode_blocks_per_group - 1) > last_block)) {
pctx.blk = gd->bg_inode_table;
if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
gd->bg_inode_table = 0;
}
free_blocks += gd->bg_free_blocks_count;
free_inodes += gd->bg_free_inodes_count;
- first_block += sb->s_blocks_per_group;
- last_block += sb->s_blocks_per_group;
if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
(gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
ext2fs_mark_super_dirty(fs);
}
+ /*
+ * Check to see if the superblock last mount time or last
+ * write time is in the future.
+ */
+ if (fs->super->s_mtime > ctx->now) {
+ 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 > ctx->now) {
+ pctx.num = fs->super->s_wtime;
+ if (fix_problem(ctx, PR_0_FUTURE_SB_LAST_WRITE, &pctx)) {
+ fs->super->s_wtime = ctx->now;
+ ext2fs_mark_super_dirty(fs);
+ }
+ }
+
/*
* Move the ext3 journal file, if necessary.
*/
e2fsck_move_ext3_journal(ctx);
+
+ /*
+ * Fix journal hint, if necessary
+ */
+ e2fsck_fix_ext3_journal_hint(ctx);
+
return;
}