aboutsummaryrefslogtreecommitdiff
path: root/e2fsck/pass1.c
diff options
context:
space:
mode:
Diffstat (limited to 'e2fsck/pass1.c')
-rw-r--r--e2fsck/pass1.c54
1 files changed, 32 insertions, 22 deletions
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 9d430895..78540119 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -79,8 +79,8 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
static void mark_table_blocks(e2fsck_t ctx);
static void alloc_bb_map(e2fsck_t ctx);
static void alloc_imagic_map(e2fsck_t ctx);
-static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
-static void add_casefolded_dir(e2fsck_t ctx, ino_t ino);
+static void mark_inode_bad(e2fsck_t ctx, ext2_ino_t ino);
+static void add_casefolded_dir(e2fsck_t ctx, ext2_ino_t ino);
static void handle_fs_bad_blocks(e2fsck_t ctx);
static void process_inodes(e2fsck_t ctx, char *block_buf);
static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
@@ -331,7 +331,7 @@ static problem_t check_large_ea_inode(e2fsck_t ctx,
blk64_t *quota_blocks)
{
struct ext2_inode inode;
- __u32 hash;
+ __u32 hash, signed_hash;
errcode_t retval;
/* Check if inode is within valid range */
@@ -343,7 +343,8 @@ static problem_t check_large_ea_inode(e2fsck_t ctx,
e2fsck_read_inode(ctx, entry->e_value_inum, &inode, "pass1");
- retval = ext2fs_ext_attr_hash_entry2(ctx->fs, entry, NULL, &hash);
+ retval = ext2fs_ext_attr_hash_entry3(ctx->fs, entry, NULL, &hash,
+ &signed_hash);
if (retval) {
com_err("check_large_ea_inode", retval,
_("while hashing entry with e_value_inum = %u"),
@@ -351,7 +352,7 @@ static problem_t check_large_ea_inode(e2fsck_t ctx,
fatal_error(ctx, 0);
}
- if (hash == entry->e_hash) {
+ if ((hash == entry->e_hash) || (signed_hash == entry->e_hash)) {
*quota_blocks = size_to_quota_blocks(ctx->fs,
entry->e_value_size);
} else {
@@ -389,13 +390,13 @@ static problem_t check_large_ea_inode(e2fsck_t ctx,
static void inc_ea_inode_refs(e2fsck_t ctx, struct problem_context *pctx,
struct ext2_ext_attr_entry *first, void *end)
{
- struct ext2_ext_attr_entry *entry;
+ struct ext2_ext_attr_entry *entry = first;
+ struct ext2_ext_attr_entry *np = EXT2_EXT_ATTR_NEXT(entry);
- for (entry = first;
- (void *)entry < end && !EXT2_EXT_IS_LAST_ENTRY(entry);
- entry = EXT2_EXT_ATTR_NEXT(entry)) {
+ while ((void *) entry < end && (void *) np < end &&
+ !EXT2_EXT_IS_LAST_ENTRY(entry)) {
if (!entry->e_value_inum)
- continue;
+ goto next;
if (!ctx->ea_inode_refs) {
pctx->errcode = ea_refcount_create(0,
&ctx->ea_inode_refs);
@@ -408,6 +409,9 @@ static void inc_ea_inode_refs(e2fsck_t ctx, struct problem_context *pctx,
}
ea_refcount_increment(ctx->ea_inode_refs, entry->e_value_inum,
0);
+ next:
+ entry = np;
+ np = EXT2_EXT_ATTR_NEXT(entry);
}
}
@@ -492,7 +496,10 @@ static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx,
}
hash = ext2fs_ext_attr_hash_entry(entry,
- start + entry->e_value_offs);
+ start + entry->e_value_offs);
+ if (entry->e_hash != 0 && entry->e_hash != hash)
+ hash = ext2fs_ext_attr_hash_entry_signed(entry,
+ start + entry->e_value_offs);
/* e_hash may be 0 in older inode's ea */
if (entry->e_hash != 0 && entry->e_hash != hash) {
@@ -1326,7 +1333,7 @@ void e2fsck_pass1(e2fsck_t ctx)
goto endit;
}
block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
- "block interate buffer");
+ "block iterate buffer");
if (EXT2_INODE_SIZE(fs->super) == EXT2_GOOD_OLD_INODE_SIZE)
e2fsck_use_inode_shortcuts(ctx, 1);
e2fsck_intercept_block_allocations(ctx);
@@ -2058,9 +2065,7 @@ void e2fsck_pass1(e2fsck_t ctx)
goto endit;
}
- if (ctx->large_dirs && !ext2fs_has_feature_largedir(ctx->fs->super)) {
- ext2_filsys fs = ctx->fs;
-
+ if (ctx->large_dirs && !ext2fs_has_feature_largedir(fs->super)) {
if (fix_problem(ctx, PR_2_FEATURE_LARGE_DIRS, &pctx)) {
ext2fs_set_feature_largedir(fs->super);
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
@@ -2204,7 +2209,7 @@ static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
/*
* Mark an inode as being bad in some what
*/
-static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
+static void mark_inode_bad(e2fsck_t ctx, ext2_ino_t ino)
{
struct problem_context pctx;
@@ -2225,7 +2230,7 @@ static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
ext2fs_mark_inode_bitmap2(ctx->inode_bad_map, ino);
}
-static void add_casefolded_dir(e2fsck_t ctx, ino_t ino)
+static void add_casefolded_dir(e2fsck_t ctx, ext2_ino_t ino)
{
struct problem_context pctx;
@@ -2555,8 +2560,9 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
break;
}
if (entry->e_value_inum == 0) {
- if (entry->e_value_offs + entry->e_value_size >
- fs->blocksize) {
+ if (entry->e_value_size > EXT2_XATTR_SIZE_MAX ||
+ (entry->e_value_offs + entry->e_value_size >
+ fs->blocksize)) {
if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
goto clear_extattr;
break;
@@ -2571,6 +2577,9 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
hash = ext2fs_ext_attr_hash_entry(entry, block_buf +
entry->e_value_offs);
+ if (entry->e_hash != hash)
+ hash = ext2fs_ext_attr_hash_entry_signed(entry,
+ block_buf + entry->e_value_offs);
if (entry->e_hash != hash) {
pctx->num = entry->e_hash;
@@ -2728,7 +2737,7 @@ static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
if (root->indirect_levels > ext2_dir_htree_level(fs) &&
!ext2fs_has_feature_largedir(fs->super)) {
int blockbits = EXT2_BLOCK_SIZE_BITS(fs->super) + 10;
- int idx_pb = 1 << (blockbits - 3);
+ unsigned idx_pb = 1 << (blockbits - 3);
/* compare inode size/blocks vs. max-sized 2-level htree */
if (EXT2_I_SIZE(pctx->inode) <
@@ -2840,7 +2849,8 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
if (pctx->errcode)
return;
if (!(ctx->options & E2F_OPT_FIXES_ONLY) &&
- !pb->eti.force_rebuild) {
+ !pb->eti.force_rebuild &&
+ info.curr_level < MAX_EXTENT_DEPTH_COUNT) {
struct extent_tree_level *etl;
etl = pb->eti.ext_info + info.curr_level;
@@ -4064,7 +4074,7 @@ static void new_table_block(e2fsck_t ctx, blk64_t first_block, dgrp_t group,
*/
is_flexbg = ext2fs_has_feature_flex_bg(fs->super);
if (is_flexbg) {
- flexbg_size = 1 << fs->super->s_log_groups_per_flex;
+ flexbg_size = 1U << fs->super->s_log_groups_per_flex;
flexbg = group / flexbg_size;
first_block = ext2fs_group_first_block2(fs,
flexbg_size * flexbg);