#include "e2fsck.h"
#include "problem.h"
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-
static void check_block_bitmaps(e2fsck_t ctx);
static void check_inode_bitmaps(e2fsck_t ctx);
static void check_inode_end(e2fsck_t ctx);
static void check_block_end(e2fsck_t ctx);
+static void check_inode_bitmap_checksum(e2fsck_t ctx);
+static void check_block_bitmap_checksum(e2fsck_t ctx);
void e2fsck_pass5(e2fsck_t ctx)
{
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return;
+ check_inode_bitmap_checksum(ctx);
+ check_block_bitmap_checksum(ctx);
+
ext2fs_free_inode_bitmap(ctx->inode_used_map);
ctx->inode_used_map = 0;
ext2fs_free_inode_bitmap(ctx->inode_dir_map);
ctx->inode_dir_map = 0;
ext2fs_free_block_bitmap(ctx->block_found_map);
ctx->block_found_map = 0;
+ ext2fs_free_block_bitmap(ctx->block_metadata_map);
+ ctx->block_metadata_map = 0;
print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io);
}
+static void check_inode_bitmap_checksum(e2fsck_t ctx)
+{
+ struct problem_context pctx;
+ char *buf = NULL;
+ dgrp_t i;
+ int nbytes;
+ ext2_ino_t ino_itr;
+ errcode_t retval;
+
+ if (!ext2fs_has_feature_metadata_csum(ctx->fs->super))
+ return;
+
+ /* If bitmap is dirty from being fixed, checksum will be corrected */
+ if (ext2fs_test_ib_dirty(ctx->fs))
+ return;
+
+ nbytes = (size_t)(EXT2_INODES_PER_GROUP(ctx->fs->super) / 8);
+ retval = ext2fs_get_mem(ctx->fs->blocksize, &buf);
+ if (retval) {
+ com_err(ctx->program_name, 0, "%s",
+ _("check_inode_bitmap_checksum: Memory allocation error"));
+ fatal_error(ctx, 0);
+ }
+
+ clear_problem_context(&pctx);
+ for (i = 0; i < ctx->fs->group_desc_count; i++) {
+ if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_INODE_UNINIT))
+ continue;
+
+ ino_itr = 1 + (i * (nbytes << 3));
+ retval = ext2fs_get_inode_bitmap_range2(ctx->fs->inode_map,
+ ino_itr, nbytes << 3,
+ buf);
+ if (retval)
+ break;
+
+ if (ext2fs_inode_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
+ continue;
+ pctx.group = i;
+ if (!fix_problem(ctx, PR_5_INODE_BITMAP_CSUM_INVALID, &pctx))
+ continue;
+
+ /*
+ * Fixing one checksum will rewrite all of them. The bitmap
+ * will be checked against the one we made during pass1 for
+ * discrepancies, and fixed if need be.
+ */
+ ext2fs_mark_ib_dirty(ctx->fs);
+ break;
+ }
+
+ ext2fs_free_mem(&buf);
+}
+
+static void check_block_bitmap_checksum(e2fsck_t ctx)
+{
+ struct problem_context pctx;
+ char *buf = NULL;
+ dgrp_t i;
+ int nbytes;
+ blk64_t blk_itr;
+ errcode_t retval;
+
+ if (!ext2fs_has_feature_metadata_csum(ctx->fs->super))
+ return;
+
+ /* If bitmap is dirty from being fixed, checksum will be corrected */
+ if (ext2fs_test_bb_dirty(ctx->fs))
+ return;
+
+ nbytes = (size_t)(EXT2_CLUSTERS_PER_GROUP(ctx->fs->super) / 8);
+ retval = ext2fs_get_mem(ctx->fs->blocksize, &buf);
+ if (retval) {
+ com_err(ctx->program_name, 0, "%s",
+ _("check_block_bitmap_checksum: Memory allocation error"));
+ fatal_error(ctx, 0);
+ }
+
+ clear_problem_context(&pctx);
+ for (i = 0; i < ctx->fs->group_desc_count; i++) {
+ if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_BLOCK_UNINIT))
+ continue;
+
+ blk_itr = EXT2FS_B2C(ctx->fs,
+ ctx->fs->super->s_first_data_block) +
+ ((blk64_t) i * (nbytes << 3));
+ retval = ext2fs_get_block_bitmap_range2(ctx->fs->block_map,
+ blk_itr, nbytes << 3,
+ buf);
+ if (retval)
+ break;
+
+ if (ext2fs_block_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
+ continue;
+ pctx.group = i;
+ if (!fix_problem(ctx, PR_5_BLOCK_BITMAP_CSUM_INVALID, &pctx))
+ continue;
+
+ /*
+ * Fixing one checksum will rewrite all of them. The bitmap
+ * will be checked against the one we made during pass1 for
+ * discrepancies, and fixed if need be.
+ */
+ ext2fs_mark_bb_dirty(ctx->fs);
+ break;
+ }
+
+ ext2fs_free_mem(&buf);
+}
+
static void e2fsck_discard_blocks(e2fsck_t ctx, blk64_t start,
blk64_t count)
{
pctx->ino = pctx->ino2 = 0;
}
-/* Just to be more succint */
+/* Just to be more succinct */
#define B2C(x) EXT2FS_B2C(fs, (x))
#define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
#define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
problem_t problem, save_problem;
int fixit, had_problem;
errcode_t retval;
- int csum_flag;
- int old_desc_blocks = 0;
- int count = 0;
- int cmp_block = 0;
int redo_flag = 0;
- blk64_t super_blk, old_desc_blk, new_desc_blk;
char *actual_buf, *bitmap_buf;
actual_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize,
goto errout;
}
- csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
redo_counts:
had_problem = 0;
save_problem = 0;
* to do a discard operation.
*/
if (!first_block_in_bg ||
- (group == (int)fs->group_desc_count - 1) ||
+ (group == fs->group_desc_count - 1) ||
(ctx->options & E2F_OPT_DISCARD))
goto no_optimize;
goto errout;
}
- csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
+ csum_flag = ext2fs_has_group_desc_csum(fs);
redo_counts:
had_problem = 0;
save_problem = 0;
ext2_filsys fs = ctx->fs;
ext2_ino_t end, save_inodes_count, i;
struct problem_context pctx;
+ int asked = 0;
clear_problem_context(&pctx);
- end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
+ end = (__u64)EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
&save_inodes_count);
if (pctx.errcode) {
return;
}
if (save_inodes_count == end)
- return;
+ goto check_intra_bg_tail;
/* protect loop from wrap-around if end is maxed */
for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
+ asked = 1;
if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
for (; i <= end; i++)
ext2fs_mark_inode_bitmap(fs->inode_map,
ctx->flags |= E2F_FLAG_ABORT; /* fatal */
return;
}
+ /*
+ * If the number of inodes per block group != blocksize, we
+ * can also have a potential problem with the tail bits in
+ * each individual inode bitmap block. If there is a problem,
+ * it would have been noticed when the bitmap was loaded. And
+ * fixing this is easy; all we need to do force the bitmap to
+ * be written back to disk.
+ */
+check_intra_bg_tail:
+ if (!asked && fs->flags & EXT2_FLAG_IBITMAP_TAIL_PROBLEM) {
+ if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx))
+ ext2fs_mark_ib_dirty(fs);
+ else
+ ext2fs_unmark_valid(fs);
+ }
}
static void check_block_end(e2fsck_t ctx)
ext2_filsys fs = ctx->fs;
blk64_t end, save_blocks_count, i;
struct problem_context pctx;
+ int asked = 0;
clear_problem_context(&pctx);
end = ext2fs_get_block_bitmap_start2(fs->block_map) +
- ((blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
+ EXT2_GROUPS_TO_CLUSTERS(fs->super, fs->group_desc_count) - 1;
pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
&save_blocks_count);
if (pctx.errcode) {
return;
}
if (save_blocks_count == end)
- return;
+ goto check_intra_bg_tail;
/* Protect loop from wrap-around if end is maxed */
for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
if (!ext2fs_test_block_bitmap2(fs->block_map,
EXT2FS_C2B(fs, i))) {
+ asked = 1;
if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
for (; i <= end; i++)
ext2fs_mark_block_bitmap2(fs->block_map,
ctx->flags |= E2F_FLAG_ABORT; /* fatal */
return;
}
+ /*
+ * If the number of blocks per block group != blocksize, we
+ * can also have a potential problem with the tail bits in
+ * each individual block bitmap block. If there is a problem,
+ * it would have been noticed when the bitmap was loaded. And
+ * fixing this is easy; all we need to do force the bitmap to
+ * be written back to disk.
+ */
+check_intra_bg_tail:
+ if (!asked && fs->flags & EXT2_FLAG_BBITMAP_TAIL_PROBLEM) {
+ if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx))
+ ext2fs_mark_bb_dirty(fs);
+ else
+ ext2fs_unmark_valid(fs);
+ }
}
-
-
-