* Pass 2 relies on the following information from previous passes:
* - The directory information collected in pass 1.
* - The inode_used_map bitmap
- * - The inode_bad_map bitmap
+ * - The inode_badness bitmap
* - The inode_dir_map bitmap
*
* Pass 2 frees the following data structures
- * - The inode_bad_map bitmap
* - The inode_reg_map bitmap
*/
ext2fs_free_mem(&buf);
ext2fs_free_dblist(fs->dblist);
- if (ctx->inode_bad_map) {
- ext2fs_free_inode_bitmap(ctx->inode_bad_map);
- ctx->inode_bad_map = 0;
- }
if (ctx->inode_reg_map) {
ext2fs_free_inode_bitmap(ctx->inode_reg_map);
ctx->inode_reg_map = 0;
{
int filetype = dirent->name_len >> 8;
int should_be = EXT2_FT_UNKNOWN;
+ __u16 result;
struct ext2_inode inode;
if (!(ctx->fs->super->s_feature_incompat &
return 1;
}
+ if (ctx->inode_badness)
+ ext2fs_icount_fetch(ctx->inode_badness, dirent->inode,
+ &result);
+
if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) {
should_be = EXT2_FT_DIR;
} else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map,
dirent->inode)) {
should_be = EXT2_FT_REG_FILE;
- } else if (ctx->inode_bad_map &&
- ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
- dirent->inode))
+ } else if (ctx->inode_badness && result >= BADNESS_BAD_MODE) {
should_be = 0;
- else {
+ } else {
e2fsck_read_inode(ctx, dirent->inode, &inode,
"check_filetype");
should_be = ext2_file_type(inode.i_mode);
* (We wait until now so that we can display the
* pathname to the user.)
*/
- if (ctx->inode_bad_map &&
- ext2fs_test_inode_bitmap2(ctx->inode_bad_map,
- dirent->inode)) {
- if (e2fsck_process_bad_inode(ctx, ino,
- dirent->inode,
+ if (ctx->inode_badness &&
+ ext2fs_icount_is_set(ctx->inode_badness, dirent->inode)) {
+ if (e2fsck_process_bad_inode(ctx, ino, dirent->inode,
buf + fs->blocksize)) {
dirent->inode = 0;
dir_modified++;
struct problem_context pctx;
__u32 count;
struct del_block del_block;
+ int extent_fs = 0;
e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
+ /* ext2fs_block_iterate2() depends on the extents flags */
+ if (inode.i_flags & EXT4_EXTENTS_FL)
+ extent_fs = 1;
e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode");
+ if (extent_fs) {
+ inode.i_flags |= EXT4_EXTENTS_FL;
+ e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
+ }
clear_problem_context(&pctx);
pctx.ino = ino;
ext2fs_block_alloc_stats2(fs,
ext2fs_file_acl_block(fs, &inode), -1);
}
+ if (ctx->inode_badness)
+ ext2fs_icount_store(ctx->inode_badness, ino, 0);
ext2fs_file_acl_block_set(fs, &inode, 0);
}
int not_fixed = 0;
unsigned char *frag, *fsize;
struct problem_context pctx;
- int problem = 0;
+ int problem = 0;
+ __u16 badness;
+ if (ctx->inode_badness)
+ ext2fs_icount_fetch(ctx->inode_badness, ino, &badness);
e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
clear_problem_context(&pctx);
inode_modified++;
} else
not_fixed++;
+ badness += BADNESS_NORMAL;
}
if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
} else
not_fixed++;
problem = 0;
+ /*
+ * A high value is associated with bad mode in order to detect
+ * that mode was corrupt in check_filetype()
+ */
+ badness += BADNESS_BAD_MODE;
}
if (inode.i_faddr) {
inode_modified++;
} else
not_fixed++;
+ badness += BADNESS_NORMAL;
}
switch (fs->super->s_creator_os) {
inode_modified++;
} else
not_fixed++;
+ badness += BADNESS_NORMAL;
pctx.num = 0;
}
if (fsize && *fsize) {
inode_modified++;
} else
not_fixed++;
+ badness += BADNESS_NORMAL;
pctx.num = 0;
}
+ /* In pass1 these conditions were used to mark inode bad so that
+ * it calls e2fsck_process_bad_inode and make an extensive check
+ * plus prompt for action to be taken. To compensate for badness
+ * incremented in pass1 by this condition, decrease it.
+ */
+ if ((inode.i_faddr || frag || fsize ||
+ (LINUX_S_ISDIR(inode.i_mode) && inode.i_dir_acl)) ||
+ (inode.i_file_acl &&
+ (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
+ (inode.i_file_acl < fs->super->s_first_data_block) ||
+ (inode.i_file_acl >= fs->super->s_blocks_count)))) {
+ /* badness can be 0 if called from pass4. */
+ if (badness)
+ badness -= BADNESS_NORMAL;
+ }
+
if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
!(fs->super->s_feature_ro_compat &
EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
inode.osd2.linux2.l_i_blocks_hi = 0;
inode_modified++;
}
+ /* Badness was increased in pass1 for this condition */
+ /* badness += BADNESS_NORMAL; */
}
if (!(fs->super->s_feature_incompat &
inode_modified++;
} else
not_fixed++;
+ badness += BADNESS_NORMAL;
}
if (ext2fs_file_acl_block(fs, &inode) &&
inode_modified++;
} else
not_fixed++;
+ badness += BADNESS_NORMAL;
}
if (inode.i_dir_acl &&
LINUX_S_ISDIR(inode.i_mode)) {
inode_modified++;
} else
not_fixed++;
+ badness += BADNESS_NORMAL;
+ }
+
+ /*
+ * The high value due to BADNESS_BAD_MODE should not delete the inode.
+ */
+ if (ctx->inode_badness && (badness - (badness >= BADNESS_BAD_MODE ?
+ BADNESS_BAD_MODE : 0)) >=
+ ctx->inode_badness_threshold) {
+ pctx.num = badness;
+ if (fix_problem(ctx, PR_2_INODE_TOOBAD, &pctx)) {
+ deallocate_inode(ctx, ino, 0);
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ return 0;
+ return 1;
+ }
+ not_fixed++;
}
if (inode_modified)
e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
- if (!not_fixed && ctx->inode_bad_map)
- ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino);
+ if (ctx->inode_badness)
+ ext2fs_icount_store(ctx->inode_badness, ino, 0);
return 0;
}