}
}
+static void check_super_value64(e2fsck_t ctx, const char *descr,
+ __u64 value, int flags,
+ __u64 min_val, __u64 max_val)
+{
+ struct problem_context pctx;
+
+ if ((flags & MIN_CHECK && value < min_val) ||
+ (flags & MAX_CHECK && value > max_val) ||
+ (flags & LOG2_CHECK && (value & (value - 1)) != 0)) {
+ clear_problem_context(&pctx);
+ pctx.num = value;
+ pctx.str = descr;
+ fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
+ }
+}
+
/*
* helper function to release an inode
*/
pctx->blk = blk;
pctx->blkcount = blockcnt;
- if (HOLE_BLKADDR(blk))
+ if (blk == 0)
return 0;
if ((blk < fs->super->s_first_data_block) ||
block_buf, release_inode_block, &pb);
if (retval) {
com_err("release_inode_blocks", retval,
- _("while calling ext2fs_block_iterate for inode %d"),
+ _("while calling ext2fs_block_iterate for inode %u"),
ino);
return 1;
}
ext2fs_iblk_sub_blocks(fs, inode, pb.truncated_blocks);
if (ext2fs_file_acl_block(fs, inode)) {
- retval = ext2fs_adjust_ea_refcount2(fs,
- ext2fs_file_acl_block(fs, inode),
- block_buf, -1, &count);
+ retval = ext2fs_adjust_ea_refcount3(fs,
+ ext2fs_file_acl_block(fs, inode),
+ block_buf, -1, &count, ino);
if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
retval = 0;
count = 1;
}
if (retval) {
com_err("release_inode_blocks", retval,
- _("while calling ext2fs_adjust_ea_refcount2 for inode %d"),
+ _("while calling ext2fs_adjust_ea_refcount2 for inode %u"),
ino);
return 1;
}
* 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)) {
+ if (!ext2fs_has_feature_resize_inode(fs->super)) {
if (fs->super->s_reserved_gdt_blocks) {
pctx.num = fs->super->s_reserved_gdt_blocks;
if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
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)
+ if (ext2fs_has_feature_resize_inode(fs->super))
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)) {
+ if (!ext2fs_has_feature_resize_inode(fs->super)) {
for (i=0; i < EXT2_N_BLOCKS; i++) {
if (inode.i_block[i])
break;
char c;
if ((ctx->options & E2F_OPT_READONLY) ||
- !(sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
+ !ext2fs_has_feature_dir_index(sb) ||
(sb->s_flags & (EXT2_FLAGS_SIGNED_HASH|EXT2_FLAGS_UNSIGNED_HASH)))
return;
problem_t problem;
blk64_t blocks_per_group = fs->super->s_blocks_per_group;
__u32 bpg_max, cpg_max;
+ __u64 blks_max;
int inodes_per_block;
int inode_size;
int accept_time_fudge;
ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
sizeof(int) * fs->group_desc_count, "invalid_inode_table");
+ blks_max = (1ULL << 32) * EXT2_MAX_BLOCKS_PER_GROUP(fs->super);
+ if (ext2fs_has_feature_64bit(fs->super)) {
+ if (blks_max > ((1ULL << 48) - 1))
+ blks_max = (1ULL << 48) - 1;
+ } else {
+ if (blks_max > ((1ULL << 32) - 1))
+ blks_max = (1ULL << 32) - 1;
+ }
+
clear_problem_context(&pctx);
/*
*/
check_super_value(ctx, "inodes_count", sb->s_inodes_count,
MIN_CHECK, 1, 0);
- check_super_value(ctx, "blocks_count", ext2fs_blocks_count(sb),
- MIN_CHECK, 1, 0);
+ check_super_value64(ctx, "blocks_count", ext2fs_blocks_count(sb),
+ MIN_CHECK | MAX_CHECK, 1, blks_max);
check_super_value(ctx, "first_data_block", sb->s_first_data_block,
MAX_CHECK, 0, ext2fs_blocks_count(sb));
check_super_value(ctx, "log_block_size", sb->s_log_block_size,
return;
}
- should_be = sb->s_inodes_per_group * fs->group_desc_count;
+ should_be = (blk64_t)sb->s_inodes_per_group * fs->group_desc_count;
+ if (should_be > UINT_MAX)
+ should_be = UINT_MAX;
if (sb->s_inodes_count != should_be) {
pctx.ino = sb->s_inodes_count;
pctx.ino2 = should_be;
ext2fs_mark_super_dirty(fs);
}
}
+ if (EXT2_INODE_SIZE(sb) > EXT2_GOOD_OLD_INODE_SIZE) {
+ unsigned min =
+ sizeof(((struct ext2_inode_large *) 0)->i_extra_isize) +
+ sizeof(((struct ext2_inode_large *) 0)->i_checksum_hi);
+ unsigned max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
+ pctx.num = sb->s_min_extra_isize;
+ if (sb->s_min_extra_isize &&
+ (sb->s_min_extra_isize < min ||
+ sb->s_min_extra_isize > max ||
+ sb->s_min_extra_isize & 3) &&
+ fix_problem(ctx, PR_0_BAD_MIN_EXTRA_ISIZE, &pctx)) {
+ sb->s_min_extra_isize =
+ (sizeof(struct ext2_inode_large) -
+ EXT2_GOOD_OLD_INODE_SIZE);
+ ext2fs_mark_super_dirty(fs);
+ }
+ pctx.num = sb->s_want_extra_isize;
+ if (sb->s_want_extra_isize &&
+ (sb->s_want_extra_isize < min ||
+ sb->s_want_extra_isize > max ||
+ sb->s_want_extra_isize & 3) &&
+ fix_problem(ctx, PR_0_BAD_WANT_EXTRA_ISIZE, &pctx)) {
+ sb->s_want_extra_isize =
+ (sizeof(struct ext2_inode_large) -
+ EXT2_GOOD_OLD_INODE_SIZE);
+ ext2fs_mark_super_dirty(fs);
+ }
+ }
+
+ /* Are metadata_csum and uninit_bg both set? */
+ if (ext2fs_has_feature_metadata_csum(fs->super) &&
+ ext2fs_has_feature_gdt_csum(fs->super) &&
+ fix_problem(ctx, PR_0_META_AND_GDT_CSUM_SET, &pctx)) {
+ ext2fs_clear_feature_gdt_csum(fs->super);
+ ext2fs_mark_super_dirty(fs);
+ for (i = 0; i < fs->group_desc_count; i++)
+ ext2fs_group_desc_csum_set(fs, i);
+ }
+
+ /* We can't have ^metadata_csum,metadata_csum_seed */
+ if (!ext2fs_has_feature_metadata_csum(fs->super) &&
+ ext2fs_has_feature_csum_seed(fs->super) &&
+ fix_problem(ctx, PR_0_CSUM_SEED_WITHOUT_META_CSUM, &pctx)) {
+ ext2fs_clear_feature_csum_seed(fs->super);
+ fs->super->s_checksum_seed = 0;
+ ext2fs_mark_super_dirty(fs);
+ }
/* Is 64bit set and extents unset? */
- if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
- EXT4_FEATURE_INCOMPAT_64BIT) &&
- !EXT2_HAS_INCOMPAT_FEATURE(fs->super,
- EXT3_FEATURE_INCOMPAT_EXTENTS) &&
+ if (ext2fs_has_feature_64bit(fs->super) &&
+ !ext2fs_has_feature_extents(fs->super) &&
fix_problem(ctx, PR_0_64BIT_WITHOUT_EXTENTS, &pctx)) {
- fs->super->s_feature_incompat |=
- EXT3_FEATURE_INCOMPAT_EXTENTS;
+ ext2fs_set_feature_extents(fs->super);
ext2fs_mark_super_dirty(fs);
}
+ /* Did user ask us to convert files to extents? */
+ if (ctx->options & E2F_OPT_CONVERT_BMAP) {
+ ext2fs_set_feature_extents(fs->super);
+ ext2fs_mark_super_dirty(fs);
+ }
+
+ if (ext2fs_has_feature_meta_bg(fs->super) &&
+ (fs->super->s_first_meta_bg > fs->desc_blocks)) {
+ pctx.group = fs->desc_blocks;
+ pctx.num = fs->super->s_first_meta_bg;
+ if (fix_problem(ctx, PR_0_FIRST_META_BG_TOO_BIG, &pctx)) {
+ ext2fs_clear_feature_meta_bg(fs->super);
+ fs->super->s_first_meta_bg = 0;
+ ext2fs_mark_super_dirty(fs);
+ }
+ }
+
/*
* Verify the group descriptors....
*/
first_block = sb->s_first_data_block;
last_block = ext2fs_blocks_count(sb)-1;
- csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
+ csum_flag = ext2fs_has_group_desc_csum(fs);
for (i = 0; i < fs->group_desc_count; i++) {
pctx.group = i;
- if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
- EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+ if (!ext2fs_has_feature_flex_bg(fs->super)) {
first_block = ext2fs_group_first_block2(fs, i);
last_block = ext2fs_group_last_block2(fs, i);
}
* if the id changes under the kernel remounting rw may fail.
*/
if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid) &&
+ !ext2fs_has_feature_metadata_csum(ctx->fs->super) &&
(!csum_flag || !(ctx->mount_flags & EXT2_MF_MOUNTED))) {
if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
uuid_generate(sb->s_uuid);
+ ext2fs_init_csum_seed(fs);
fs->flags |= EXT2_FLAG_DIRTY;
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
}
*/
if (!(ctx->options & E2F_OPT_READONLY) &&
fs->super->s_creator_os == EXT2_OS_HURD &&
- (fs->super->s_feature_incompat &
- EXT2_FEATURE_INCOMPAT_FILETYPE)) {
+ ext2fs_has_feature_filetype(fs->super)) {
if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
- fs->super->s_feature_incompat &=
- ~EXT2_FEATURE_INCOMPAT_FILETYPE;
+ ext2fs_clear_feature_filetype(fs->super);
ext2fs_mark_super_dirty(fs);
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
}
}
}
+ e2fsck_validate_quota_inodes(ctx);
+
/*
* Move the ext3 journal file, if necessary.
*/