* [PATCH] e2fsck: Check and fix tails of all bitmaps
@ 2019-03-28 16:42 Jan Kara
2019-05-05 18:21 ` Theodore Ts'o
0 siblings, 1 reply; 4+ messages in thread
From: Jan Kara @ 2019-03-28 16:42 UTC (permalink / raw)
To: Ted Tso; +Cc: linux-ext4, Jan Kara
Currently, e2fsck effectively checks only tail of the last inode and
block bitmap in the filesystem. Thus if some previous bitmap has unset
bits it goes unnoticed. Mostly these tail bits in the bitmap are ignored
however if blocks_per_group are smaller than 8*blocksize, mballoc code
in the kernel can get confused when the tail bits are unset and return
bogus free extent.
Add support to libext2fs to check these bitmap tails when loading
bitmaps (as that's about the only place which has access to the bitmap
tail bits) and make e2fsck use this functionality to detect buggy bitmap
tails and fix them (by rewriting bitmaps).
Signed-off-by: Jan Kara <jack@suse.cz>
---
e2fsck/e2fsck.h | 2 +
e2fsck/pass5.c | 96 +++++++----------------------------------------
e2fsck/problem.c | 5 ---
e2fsck/problem.h | 3 --
e2fsck/util.c | 29 ++++++++++++--
lib/ext2fs/ext2_err.et.in | 6 +++
lib/ext2fs/ext2fs.h | 1 +
lib/ext2fs/rw_bitmaps.c | 22 +++++++++++
8 files changed, 69 insertions(+), 95 deletions(-)
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 1c7a67cba1ce..b32fbf0e8bdf 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -198,6 +198,8 @@ struct resource_track {
#define E2F_FLAG_TIME_INSANE 0x2000 /* Time is insane */
#define E2F_FLAG_PROBLEMS_FIXED 0x4000 /* At least one problem was fixed */
#define E2F_FLAG_ALLOC_OK 0x8000 /* Can we allocate blocks? */
+#define E2F_FLAG_INODE_BMP_TAIL 0x10000 /* Inode bitmap has incorrect tail */
+#define E2F_FLAG_BLOCK_BMP_TAIL 0x20000 /* Block bitmap has incorrect tail */
#define E2F_RESET_FLAGS (E2F_FLAG_TIME_INSANE | E2F_FLAG_PROBLEMS_FIXED)
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index 7803e8b80178..c8e2278eb305 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -23,8 +23,7 @@
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_bitmap_tails(e2fsck_t ctx);
static void check_inode_bitmap_checksum(e2fsck_t ctx);
static void check_block_bitmap_checksum(e2fsck_t ctx);
@@ -57,10 +56,7 @@ void e2fsck_pass5(e2fsck_t ctx)
check_inode_bitmaps(ctx);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return;
- check_inode_end(ctx);
- if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
- return;
- check_block_end(ctx);
+ check_bitmap_tails(ctx);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return;
@@ -833,93 +829,27 @@ errout:
ext2fs_free_mem(&dir_array);
}
-static void check_inode_end(e2fsck_t ctx)
+static void check_bitmap_tails(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
- ext2_ino_t end, save_inodes_count, i;
struct problem_context pctx;
clear_problem_context(&pctx);
- end = 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) {
- pctx.num = 1;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
- if (save_inodes_count == end)
- return;
-
- /* 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)) {
- if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
- for (; i <= end; i++)
- ext2fs_mark_inode_bitmap(fs->inode_map,
- i);
- ext2fs_mark_ib_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- break;
- }
- }
-
- pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
- save_inodes_count, 0);
- if (pctx.errcode) {
- pctx.num = 2;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
+ if (ctx->flags & E2F_FLAG_INODE_BMP_TAIL) {
+ 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;
clear_problem_context(&pctx);
- end = ext2fs_get_block_bitmap_start2(fs->block_map) +
- 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) {
- pctx.num = 3;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
- }
- if (save_blocks_count == end)
- return;
-
- /* 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))) {
- if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
- for (; i <= end; i++)
- ext2fs_mark_block_bitmap2(fs->block_map,
- EXT2FS_C2B(fs, i));
- ext2fs_mark_bb_dirty(fs);
- } else
- ext2fs_unmark_valid(fs);
- break;
- }
- }
-
- pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
- save_blocks_count, 0);
- if (pctx.errcode) {
- pctx.num = 4;
- fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- ctx->flags |= E2F_FLAG_ABORT; /* fatal */
- return;
+ if (ctx->flags & E2F_FLAG_BLOCK_BMP_TAIL) {
+ if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx))
+ ext2fs_mark_bb_dirty(fs);
+ else
+ ext2fs_unmark_valid(fs);
}
}
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 0e6bacec21ab..c341f560b67f 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1993,11 +1993,6 @@ static struct e2fsck_problem problem_table[] = {
"match calculated @B endpoints (%i, %j)\n"),
PROMPT_NONE, PR_FATAL, 0, 0, 0 },
- /* Internal error: fudging end of bitmap */
- { PR_5_FUDGE_BITMAP_ERROR,
- N_("Internal error: fudging end of bitmap (%N)\n"),
- PROMPT_NONE, PR_FATAL, 0, 0, 0 },
-
/* Error copying in replacement inode bitmap */
{ PR_5_COPY_IBITMAP_ERROR,
N_("Error copying in replacement @i @B: %m\n"),
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 2c79169ef33b..11c89627387a 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -1200,9 +1200,6 @@ struct problem_context {
/* Programming error: bitmap endpoints don't match */
#define PR_5_BMAP_ENDPOINTS 0x050010
-/* Internal error: fudging end of bitmap */
-#define PR_5_FUDGE_BITMAP_ERROR 0x050011
-
/* Error copying in replacement inode bitmap */
#define PR_5_COPY_IBITMAP_ERROR 0x050012
diff --git a/e2fsck/util.c b/e2fsck/util.c
index db6a1cc11a23..3468fccc3327 100644
--- a/e2fsck/util.c
+++ b/e2fsck/util.c
@@ -310,7 +310,7 @@ void e2fsck_read_bitmaps(e2fsck_t ctx)
errcode_t retval;
const char *old_op;
unsigned int save_type;
- int flags;
+ int flags, mask;
if (ctx->invalid_bitmaps) {
com_err(ctx->program_name, 0,
@@ -322,11 +322,32 @@ void e2fsck_read_bitmaps(e2fsck_t ctx)
old_op = ehandler_operation(_("reading inode and block bitmaps"));
e2fsck_set_bitmap_type(fs, EXT2FS_BMAP64_RBTREE, "fs_bitmaps",
&save_type);
+ mask = EXT2_FLAG_IGNORE_CSUM_ERRORS | EXT2_FLAG_VERIFY_BITMAP_TAILS;
flags = ctx->fs->flags;
- ctx->fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
+ ctx->fs->flags |= mask;
retval = ext2fs_read_bitmaps(fs);
- ctx->fs->flags = (flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) |
- (ctx->fs->flags & ~EXT2_FLAG_IGNORE_CSUM_ERRORS);
+ if (retval == EXT2_ET_BLOCK_BITMAP_TAIL ||
+ retval == EXT2_ET_INODE_BITMAP_TAIL) {
+ /*
+ * Read bitmaps one after another to find out which ones have
+ * wrong tails.
+ */
+ retval = ext2fs_read_inode_bitmap(fs);
+ if (retval == EXT2_ET_INODE_BITMAP_TAIL)
+ ctx->flags |= E2F_FLAG_INODE_BMP_TAIL;
+ else if (retval)
+ goto restore_flags;
+ retval = ext2fs_read_block_bitmap(fs);
+ if (retval == EXT2_ET_BLOCK_BITMAP_TAIL)
+ ctx->flags |= E2F_FLAG_BLOCK_BMP_TAIL;
+ else if (retval)
+ goto restore_flags;
+ /* Now read the failed ones without checking */
+ ctx->fs->flags &= ~EXT2_FLAG_VERIFY_BITMAP_TAILS;
+ retval = ext2fs_read_bitmaps(fs);
+ }
+restore_flags:
+ ctx->fs->flags = (flags & mask) | (ctx->fs->flags & ~mask);
fs->default_bitmap_type = save_type;
ehandler_operation(old_op);
if (retval) {
diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in
index b2ba71ad2fd5..c2beece13100 100644
--- a/lib/ext2fs/ext2_err.et.in
+++ b/lib/ext2fs/ext2_err.et.in
@@ -545,4 +545,10 @@ ec EXT2_ET_INODE_CORRUPTED,
ec EXT2_ET_EA_INODE_CORRUPTED,
"Inode containing extended attribute value is corrupted"
+ec EXT2_ET_BLOCK_BITMAP_TAIL,
+ "Block bitmap tail is not completely set"
+
+ec EXT2_ET_INODE_BITMAP_TAIL,
+ "Inode bitmap tail is not completely set"
+
end
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 9e76ffaaa873..3b223b3322a3 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -204,6 +204,7 @@ typedef struct ext2_file *ext2_file_t;
#define EXT2_FLAG_IGNORE_CSUM_ERRORS 0x200000
#define EXT2_FLAG_SHARE_DUP 0x400000
#define EXT2_FLAG_IGNORE_SB_ERRORS 0x800000
+#define EXT2_FLAG_VERIFY_BITMAP_TAILS 0x1000000
/*
* Special flag in the ext2 inode i_flag field that means that this is
diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
index e86bacd5321a..1d578283d08f 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -195,6 +195,16 @@ static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs)
return 0;
}
+static int bitmap_tail_verify(unsigned char *bitmap, int first, int last)
+{
+ int i;
+
+ for (i = first; i <= last; i++)
+ if (bitmap[i] != 0xff)
+ return 0;
+ return 1;
+}
+
static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
{
dgrp_t i;
@@ -315,6 +325,12 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
EXT2_ET_BLOCK_BITMAP_CSUM_INVALID;
goto cleanup;
}
+ if (fs->flags & EXT2_FLAG_VERIFY_BITMAP_TAILS
+ && !bitmap_tail_verify(block_bitmap,
+ block_nbytes, fs->blocksize - 1)) {
+ retval = EXT2_ET_BLOCK_BITMAP_TAIL;
+ goto cleanup;
+ }
} else
memset(block_bitmap, 0, block_nbytes);
cnt = block_nbytes << 3;
@@ -347,6 +363,12 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
EXT2_ET_INODE_BITMAP_CSUM_INVALID;
goto cleanup;
}
+ if (fs->flags & EXT2_FLAG_VERIFY_BITMAP_TAILS
+ && !bitmap_tail_verify(inode_bitmap,
+ inode_nbytes, fs->blocksize - 1)) {
+ retval = EXT2_ET_INODE_BITMAP_TAIL;
+ goto cleanup;
+ }
} else
memset(inode_bitmap, 0, inode_nbytes);
cnt = inode_nbytes << 3;
--
2.16.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] e2fsck: Check and fix tails of all bitmaps
2019-03-28 16:42 [PATCH] e2fsck: Check and fix tails of all bitmaps Jan Kara
@ 2019-05-05 18:21 ` Theodore Ts'o
2019-05-05 21:48 ` Theodore Ts'o
0 siblings, 1 reply; 4+ messages in thread
From: Theodore Ts'o @ 2019-05-05 18:21 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-ext4
On Thu, Mar 28, 2019 at 05:42:18PM +0100, Jan Kara wrote:
> Currently, e2fsck effectively checks only tail of the last inode and
> block bitmap in the filesystem. Thus if some previous bitmap has unset
> bits it goes unnoticed. Mostly these tail bits in the bitmap are ignored
> however if blocks_per_group are smaller than 8*blocksize, mballoc code
> in the kernel can get confused when the tail bits are unset and return
> bogus free extent.
This patch isn't quite right; there are two different kinds of "bitmap
tails". The one which e2fsck currently validates is the one only
happens at the last inode and block bitmap, and happens when the
number of blocks or inodes is not a multiple of the 8*blocksize.
The second is the ones when number of blocks/inodes per block group is
less than 8*blocksize, and you're quite right that we weren't
correctly testing for this.
The patch adds a test for the second, but the test added in this patch
to read_bitmaps() *only* tests for the second, and not the first. But
it removes the tests for set bits for the first type of bitmap tails,
so we would no longer be testing for this kind of file system
corruption.
I noticed this by inspecting the code, but it was also picked up by
the regression tests, such as f_end-bitmap. There were also a large
number of regression test failures that were *added* by this commit,
since some of the images for the existing tests had tails at the end
of inode bitmaps. So it's pretty obvious that "make -j16 check"
wasn't run after making this change. :-/
Tests failed: f_bitmaps f_dup2 f_dup3 f_dup f_end-bitmap f_illbbitmap f_illibitmap f_illitable_flexbg f_lpf f_overfsblks f_super_bad_csum j_corrupt_ext_jnl_sb_csum j_ext_long_trans j_long_trans j_long_trans_mcsum_32bit j_long_trans_mcsum_64bit j_recover_csum2_32bit j_recover_csum2_64bit j_short_trans_64bit j_short_trans j_short_trans_mcsum_64bit j_short_trans_old_csum j_short_trans_open_recover j_short_trans_recover j_short_trans_recover_mcsum_64bit t_replay_and_set
I'm also going to propose that we go about this slightly differently.
The check to see if the bitmaps have invalid tail bits doesn't take
that much extra time. So instead of having a set of flags which
*request* that we do the check, let's unconditionally do the check,
but instead of returning an error if there is a problem, we'll reserve
two flags, and set them if read_bitmaps() detects a tail bitmap
problem while reading the block or inode problem.
This simplifies the logic in e2fsck, since we don't have to retry the
call to ext2fs_read_bitmaps() without the tail check if it fails.
Instead, we just have to check the two new flag bits after calling
ext2fs_read_bitmaps().
And we'll have to keep check_block_bitmaps() and check_inode_bitmaps()
to test the first kind of tail bitmaps.
- Ted
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] e2fsck: Check and fix tails of all bitmaps
2019-05-05 18:21 ` Theodore Ts'o
@ 2019-05-05 21:48 ` Theodore Ts'o
2019-05-06 9:08 ` Jan Kara
0 siblings, 1 reply; 4+ messages in thread
From: Theodore Ts'o @ 2019-05-05 21:48 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-ext4
Hi Jan,
Here's my proposed approach to solving the problem you've identified.
Cheers,
- Ted
From 6d0b48896247dc70b16482a8ff4123d570285a2a Mon Sep 17 00:00:00 2001
From: Theodore Ts'o <tytso@mit.edu>
Date: Sun, 5 May 2019 16:43:33 -0400
Subject: [PATCH] e2fsck: check and fix tails of all bitmap blocks
Currently, e2fsck effectively checks only tail of the last inode and
block bitmap in the filesystem. Thus if some previous bitmap has unset
bits it goes unnoticed. Mostly these tail bits in the bitmap are
ignored; however, if blocks_per_group are smaller than 8*blocksize,
the multi-block allocator in the kernel can get confused when the tail
bits are unset and return bogus free extent.
Add support to libext2fs to check these bitmap tails when loading
bitmaps (as that's about the only place which has access to the bitmap
tail bits) and make e2fsck use this functionality to detect buggy bitmap
tails and fix them (by rewriting the bitmaps).
Reported-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
e2fsck/pass5.c | 40 ++++++++++++++++---
lib/ext2fs/ext2fs.h | 2 +
lib/ext2fs/rw_bitmaps.c | 26 +++++++++++-
tests/f_bitmaps/expect.1 | 2 +
tests/f_dup/expect.1 | 2 +
tests/f_dup2/expect.1 | 2 +
tests/f_dup3/expect.1 | 2 +
tests/f_end-bitmap/expect.1 | 2 +
tests/f_illbbitmap/expect.1 | 2 +
tests/f_illibitmap/expect.1 | 2 +
tests/f_illitable_flexbg/expect.1 | 2 +
tests/f_lpf/expect.1 | 2 +
tests/f_overfsblks/expect.1 | 2 +
tests/f_super_bad_csum/expect.1 | 4 +-
tests/j_corrupt_ext_jnl_sb_csum/expect | 2 +
tests/j_ext_long_trans/expect | 2 +
tests/j_long_trans/expect | 2 +
tests/j_long_trans_mcsum_32bit/expect | 2 +
tests/j_long_trans_mcsum_64bit/expect | 2 +
tests/j_recover_csum2_32bit/expect.1 | 2 +
tests/j_recover_csum2_64bit/expect.1 | 2 +
tests/j_short_trans/expect | 2 +
tests/j_short_trans_64bit/expect | 2 +
tests/j_short_trans_mcsum_64bit/expect | 2 +
tests/j_short_trans_old_csum/expect | 2 +
tests/j_short_trans_open_recover/expect | 2 +
tests/j_short_trans_recover/expect | 2 +
.../j_short_trans_recover_mcsum_64bit/expect | 2 +
tests/t_replay_and_set/expect | 2 +
29 files changed, 113 insertions(+), 9 deletions(-)
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index 7803e8b80..810090970 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -838,6 +838,7 @@ static void check_inode_end(e2fsck_t ctx)
ext2_filsys fs = ctx->fs;
ext2_ino_t end, save_inodes_count, i;
struct problem_context pctx;
+ int asked = 0;
clear_problem_context(&pctx);
@@ -851,11 +852,12 @@ static void check_inode_end(e2fsck_t ctx)
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,
@@ -875,6 +877,20 @@ static void check_inode_end(e2fsck_t ctx)
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)
@@ -882,6 +898,7 @@ 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);
@@ -896,12 +913,13 @@ static void check_block_end(e2fsck_t ctx)
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,
@@ -921,7 +939,19 @@ static void check_block_end(e2fsck_t ctx)
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);
+ }
}
-
-
-
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 7d7c346df..59fd97426 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -204,6 +204,8 @@ typedef struct ext2_file *ext2_file_t;
#define EXT2_FLAG_IGNORE_CSUM_ERRORS 0x200000
#define EXT2_FLAG_SHARE_DUP 0x400000
#define EXT2_FLAG_IGNORE_SB_ERRORS 0x800000
+#define EXT2_FLAG_BBITMAP_TAIL_PROBLEM 0x1000000
+#define EXT2_FLAG_IBITMAP_TAIL_PROBLEM 0x2000000
/*
* Special flag in the ext2 inode i_flag field that means that this is
diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
index e86bacd53..27c684d62 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -195,6 +195,16 @@ static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs)
return 0;
}
+static int bitmap_tail_verify(unsigned char *bitmap, int first, int last)
+{
+ int i;
+
+ for (i = first; i <= last; i++)
+ if (bitmap[i] != 0xff)
+ return 0;
+ return 1;
+}
+
static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
{
dgrp_t i;
@@ -203,6 +213,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
errcode_t retval;
int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
+ int tail_flags = 0;
int csum_flag;
unsigned int cnt;
blk64_t blk;
@@ -315,6 +326,9 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
EXT2_ET_BLOCK_BITMAP_CSUM_INVALID;
goto cleanup;
}
+ if (!bitmap_tail_verify(block_bitmap,
+ block_nbytes, fs->blocksize - 1))
+ tail_flags |= EXT2_FLAG_BBITMAP_TAIL_PROBLEM;
} else
memset(block_bitmap, 0, block_nbytes);
cnt = block_nbytes << 3;
@@ -347,6 +361,9 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
EXT2_ET_INODE_BITMAP_CSUM_INVALID;
goto cleanup;
}
+ if (!bitmap_tail_verify(inode_bitmap,
+ inode_nbytes, fs->blocksize - 1))
+ tail_flags |= EXT2_FLAG_IBITMAP_TAIL_PROBLEM;
} else
memset(inode_bitmap, 0, inode_nbytes);
cnt = inode_nbytes << 3;
@@ -366,10 +383,15 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
}
success_cleanup:
- if (inode_bitmap)
+ if (inode_bitmap) {
ext2fs_free_mem(&inode_bitmap);
- if (block_bitmap)
+ fs->flags &= ~EXT2_FLAG_IBITMAP_TAIL_PROBLEM;
+ }
+ if (block_bitmap) {
ext2fs_free_mem(&block_bitmap);
+ fs->flags &= ~EXT2_FLAG_BBITMAP_TAIL_PROBLEM;
+ }
+ fs->flags |= tail_flags;
return 0;
cleanup:
diff --git a/tests/f_bitmaps/expect.1 b/tests/f_bitmaps/expect.1
index 715984d4d..2e91113db 100644
--- a/tests/f_bitmaps/expect.1
+++ b/tests/f_bitmaps/expect.1
@@ -11,6 +11,8 @@ Fix? yes
Inode bitmap differences: +11 -15
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (9.1% non-contiguous), 22/100 blocks
diff --git a/tests/f_dup/expect.1 b/tests/f_dup/expect.1
index 075e62c13..635a0dfc8 100644
--- a/tests/f_dup/expect.1
+++ b/tests/f_dup/expect.1
@@ -30,6 +30,8 @@ Fix? yes
Free blocks count wrong (62, counted=60).
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
Padding at end of block bitmap is not set. Fix? yes
diff --git a/tests/f_dup2/expect.1 b/tests/f_dup2/expect.1
index 69aa21b4b..04d7304b4 100644
--- a/tests/f_dup2/expect.1
+++ b/tests/f_dup2/expect.1
@@ -37,6 +37,8 @@ Fix? yes
Free blocks count wrong (26, counted=22).
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
Padding at end of block bitmap is not set. Fix? yes
diff --git a/tests/f_dup3/expect.1 b/tests/f_dup3/expect.1
index eab75a8dc..5f79cb891 100644
--- a/tests/f_dup3/expect.1
+++ b/tests/f_dup3/expect.1
@@ -39,6 +39,8 @@ Fix? yes
Free blocks count wrong (20, counted=19).
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 16/16 files (25.0% non-contiguous), 81/100 blocks
diff --git a/tests/f_end-bitmap/expect.1 b/tests/f_end-bitmap/expect.1
index 87e2fd647..85c7e67f4 100644
--- a/tests/f_end-bitmap/expect.1
+++ b/tests/f_end-bitmap/expect.1
@@ -8,6 +8,8 @@ Pass 5: Checking group summary information
Free blocks count wrong for group #0 (44, counted=63).
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
Padding at end of block bitmap is not set. Fix? yes
diff --git a/tests/f_illbbitmap/expect.1 b/tests/f_illbbitmap/expect.1
index 8746d23a5..40996cd61 100644
--- a/tests/f_illbbitmap/expect.1
+++ b/tests/f_illbbitmap/expect.1
@@ -22,6 +22,8 @@ Fix? yes
Inode bitmap differences: -(12--21)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks
diff --git a/tests/f_illibitmap/expect.1 b/tests/f_illibitmap/expect.1
index 5bae25d14..bf21df7a7 100644
--- a/tests/f_illibitmap/expect.1
+++ b/tests/f_illibitmap/expect.1
@@ -19,6 +19,8 @@ Pass 5: Checking group summary information
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks
diff --git a/tests/f_illitable_flexbg/expect.1 b/tests/f_illitable_flexbg/expect.1
index fa42a0f8b..4ac124639 100644
--- a/tests/f_illitable_flexbg/expect.1
+++ b/tests/f_illitable_flexbg/expect.1
@@ -18,6 +18,8 @@ Pass 5: Checking group summary information
Inode bitmap differences: -(65--128)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/256 files (0.0% non-contiguous), 31163/32768 blocks
diff --git a/tests/f_lpf/expect.1 b/tests/f_lpf/expect.1
index 4f2853c5b..6ef996bb6 100644
--- a/tests/f_lpf/expect.1
+++ b/tests/f_lpf/expect.1
@@ -42,6 +42,8 @@ Fix? yes
Free inodes count wrong (1, counted=0).
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 16/16 files (12.5% non-contiguous), 67/100 blocks
diff --git a/tests/f_overfsblks/expect.1 b/tests/f_overfsblks/expect.1
index e5b93f0d5..bc8f2a879 100644
--- a/tests/f_overfsblks/expect.1
+++ b/tests/f_overfsblks/expect.1
@@ -13,6 +13,8 @@ Pass 5: Checking group summary information
Inode bitmap differences: -(12--21)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks
diff --git a/tests/f_super_bad_csum/expect.1 b/tests/f_super_bad_csum/expect.1
index 25ced5c8a..12adee970 100644
--- a/tests/f_super_bad_csum/expect.1
+++ b/tests/f_super_bad_csum/expect.1
@@ -5,8 +5,8 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Inode bitmap differences: Group 1 inode bitmap does not match checksum.
-FIXED.
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/1024 files (0.0% non-contiguous), 1557/16384 blocks
diff --git a/tests/j_corrupt_ext_jnl_sb_csum/expect b/tests/j_corrupt_ext_jnl_sb_csum/expect
index 70a4fe721..4212a0007 100644
--- a/tests/j_corrupt_ext_jnl_sb_csum/expect
+++ b/tests/j_corrupt_ext_jnl_sb_csum/expect
@@ -12,6 +12,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/128 files (0.0% non-contiguous), 66/2048 blocks
diff --git a/tests/j_ext_long_trans/expect b/tests/j_ext_long_trans/expect
index d379610e7..ea3c87fcb 100644
--- a/tests/j_ext_long_trans/expect
+++ b/tests/j_ext_long_trans/expect
@@ -98,6 +98,8 @@ Fix? yes
Free inodes count wrong (16372, counted=16373).
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/16384 files (0.0% non-contiguous), 6228/262144 blocks
diff --git a/tests/j_long_trans/expect b/tests/j_long_trans/expect
index 7a175414b..82b3caf17 100644
--- a/tests/j_long_trans/expect
+++ b/tests/j_long_trans/expect
@@ -96,6 +96,8 @@ Fix? yes
Free inodes count wrong (16372, counted=16373).
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
Recreate journal? yes
Creating journal (8192 blocks): Done.
diff --git a/tests/j_long_trans_mcsum_32bit/expect b/tests/j_long_trans_mcsum_32bit/expect
index a808d9f4d..ffae07a69 100644
--- a/tests/j_long_trans_mcsum_32bit/expect
+++ b/tests/j_long_trans_mcsum_32bit/expect
@@ -135,6 +135,8 @@ Fix? yes
Free inodes count wrong (32756, counted=32757).
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
Recreate journal? yes
Creating journal (16384 blocks): Done.
diff --git a/tests/j_long_trans_mcsum_64bit/expect b/tests/j_long_trans_mcsum_64bit/expect
index 76e109a42..e891def16 100644
--- a/tests/j_long_trans_mcsum_64bit/expect
+++ b/tests/j_long_trans_mcsum_64bit/expect
@@ -134,6 +134,8 @@ Fix? yes
Free inodes count wrong (32756, counted=32757).
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
Recreate journal? yes
Creating journal (16384 blocks): Done.
diff --git a/tests/j_recover_csum2_32bit/expect.1 b/tests/j_recover_csum2_32bit/expect.1
index 491784a25..fdbda36e2 100644
--- a/tests/j_recover_csum2_32bit/expect.1
+++ b/tests/j_recover_csum2_32bit/expect.1
@@ -10,6 +10,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/8192 files (0.0% non-contiguous), 7739/131072 blocks
diff --git a/tests/j_recover_csum2_64bit/expect.1 b/tests/j_recover_csum2_64bit/expect.1
index 491784a25..fdbda36e2 100644
--- a/tests/j_recover_csum2_64bit/expect.1
+++ b/tests/j_recover_csum2_64bit/expect.1
@@ -10,6 +10,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/8192 files (0.0% non-contiguous), 7739/131072 blocks
diff --git a/tests/j_short_trans/expect b/tests/j_short_trans/expect
index bcc8fe82a..2bd0e5069 100644
--- a/tests/j_short_trans/expect
+++ b/tests/j_short_trans/expect
@@ -32,6 +32,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
diff --git a/tests/j_short_trans_64bit/expect b/tests/j_short_trans_64bit/expect
index f9971eba3..808dc61df 100644
--- a/tests/j_short_trans_64bit/expect
+++ b/tests/j_short_trans_64bit/expect
@@ -34,6 +34,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/16384 files (0.0% non-contiguous), 5196/65536 blocks
diff --git a/tests/j_short_trans_mcsum_64bit/expect b/tests/j_short_trans_mcsum_64bit/expect
index d876ff095..d73e28297 100644
--- a/tests/j_short_trans_mcsum_64bit/expect
+++ b/tests/j_short_trans_mcsum_64bit/expect
@@ -34,6 +34,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32768 files (0.0% non-contiguous), 6353/131072 blocks
diff --git a/tests/j_short_trans_old_csum/expect b/tests/j_short_trans_old_csum/expect
index 29ac27fb3..6cf06d4a2 100644
--- a/tests/j_short_trans_old_csum/expect
+++ b/tests/j_short_trans_old_csum/expect
@@ -34,6 +34,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
diff --git a/tests/j_short_trans_open_recover/expect b/tests/j_short_trans_open_recover/expect
index be6e363dc..3e868197d 100644
--- a/tests/j_short_trans_open_recover/expect
+++ b/tests/j_short_trans_open_recover/expect
@@ -37,6 +37,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
diff --git a/tests/j_short_trans_recover/expect b/tests/j_short_trans_recover/expect
index 75867337f..508858c98 100644
--- a/tests/j_short_trans_recover/expect
+++ b/tests/j_short_trans_recover/expect
@@ -34,6 +34,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
diff --git a/tests/j_short_trans_recover_mcsum_64bit/expect b/tests/j_short_trans_recover_mcsum_64bit/expect
index 9cc330978..8c637f122 100644
--- a/tests/j_short_trans_recover_mcsum_64bit/expect
+++ b/tests/j_short_trans_recover_mcsum_64bit/expect
@@ -36,6 +36,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32768 files (0.0% non-contiguous), 6353/131072 blocks
diff --git a/tests/t_replay_and_set/expect b/tests/t_replay_and_set/expect
index f63a73af5..3e19d92e9 100644
--- a/tests/t_replay_and_set/expect
+++ b/tests/t_replay_and_set/expect
@@ -30,6 +30,8 @@ Fix? yes
Inode bitmap differences: +(1--11)
Fix? yes
+Padding at end of inode bitmap is not set. Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
--
2.19.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] e2fsck: Check and fix tails of all bitmaps
2019-05-05 21:48 ` Theodore Ts'o
@ 2019-05-06 9:08 ` Jan Kara
0 siblings, 0 replies; 4+ messages in thread
From: Jan Kara @ 2019-05-06 9:08 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Jan Kara, linux-ext4
Hi Ted!
On Sun 05-05-19 17:48:35, Theodore Ts'o wrote:
> Here's my proposed approach to solving the problem you've identified.
Thanks for the patch! It looks good to me and it's indeed somewhat cleaner
that what I've suggested. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
And yes, I forgot about running make check. Sorry for that.
Honza
> From 6d0b48896247dc70b16482a8ff4123d570285a2a Mon Sep 17 00:00:00 2001
> From: Theodore Ts'o <tytso@mit.edu>
> Date: Sun, 5 May 2019 16:43:33 -0400
> Subject: [PATCH] e2fsck: check and fix tails of all bitmap blocks
>
> Currently, e2fsck effectively checks only tail of the last inode and
> block bitmap in the filesystem. Thus if some previous bitmap has unset
> bits it goes unnoticed. Mostly these tail bits in the bitmap are
> ignored; however, if blocks_per_group are smaller than 8*blocksize,
> the multi-block allocator in the kernel can get confused when the tail
> bits are unset and return bogus free extent.
>
> Add support to libext2fs to check these bitmap tails when loading
> bitmaps (as that's about the only place which has access to the bitmap
> tail bits) and make e2fsck use this functionality to detect buggy bitmap
> tails and fix them (by rewriting the bitmaps).
>
> Reported-by: Jan Kara <jack@suse.cz>
> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> ---
> e2fsck/pass5.c | 40 ++++++++++++++++---
> lib/ext2fs/ext2fs.h | 2 +
> lib/ext2fs/rw_bitmaps.c | 26 +++++++++++-
> tests/f_bitmaps/expect.1 | 2 +
> tests/f_dup/expect.1 | 2 +
> tests/f_dup2/expect.1 | 2 +
> tests/f_dup3/expect.1 | 2 +
> tests/f_end-bitmap/expect.1 | 2 +
> tests/f_illbbitmap/expect.1 | 2 +
> tests/f_illibitmap/expect.1 | 2 +
> tests/f_illitable_flexbg/expect.1 | 2 +
> tests/f_lpf/expect.1 | 2 +
> tests/f_overfsblks/expect.1 | 2 +
> tests/f_super_bad_csum/expect.1 | 4 +-
> tests/j_corrupt_ext_jnl_sb_csum/expect | 2 +
> tests/j_ext_long_trans/expect | 2 +
> tests/j_long_trans/expect | 2 +
> tests/j_long_trans_mcsum_32bit/expect | 2 +
> tests/j_long_trans_mcsum_64bit/expect | 2 +
> tests/j_recover_csum2_32bit/expect.1 | 2 +
> tests/j_recover_csum2_64bit/expect.1 | 2 +
> tests/j_short_trans/expect | 2 +
> tests/j_short_trans_64bit/expect | 2 +
> tests/j_short_trans_mcsum_64bit/expect | 2 +
> tests/j_short_trans_old_csum/expect | 2 +
> tests/j_short_trans_open_recover/expect | 2 +
> tests/j_short_trans_recover/expect | 2 +
> .../j_short_trans_recover_mcsum_64bit/expect | 2 +
> tests/t_replay_and_set/expect | 2 +
> 29 files changed, 113 insertions(+), 9 deletions(-)
>
> diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
> index 7803e8b80..810090970 100644
> --- a/e2fsck/pass5.c
> +++ b/e2fsck/pass5.c
> @@ -838,6 +838,7 @@ static void check_inode_end(e2fsck_t ctx)
> ext2_filsys fs = ctx->fs;
> ext2_ino_t end, save_inodes_count, i;
> struct problem_context pctx;
> + int asked = 0;
>
> clear_problem_context(&pctx);
>
> @@ -851,11 +852,12 @@ static void check_inode_end(e2fsck_t ctx)
> 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,
> @@ -875,6 +877,20 @@ static void check_inode_end(e2fsck_t ctx)
> 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)
> @@ -882,6 +898,7 @@ 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);
>
> @@ -896,12 +913,13 @@ static void check_block_end(e2fsck_t ctx)
> 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,
> @@ -921,7 +939,19 @@ static void check_block_end(e2fsck_t ctx)
> 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);
> + }
> }
> -
> -
> -
> diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
> index 7d7c346df..59fd97426 100644
> --- a/lib/ext2fs/ext2fs.h
> +++ b/lib/ext2fs/ext2fs.h
> @@ -204,6 +204,8 @@ typedef struct ext2_file *ext2_file_t;
> #define EXT2_FLAG_IGNORE_CSUM_ERRORS 0x200000
> #define EXT2_FLAG_SHARE_DUP 0x400000
> #define EXT2_FLAG_IGNORE_SB_ERRORS 0x800000
> +#define EXT2_FLAG_BBITMAP_TAIL_PROBLEM 0x1000000
> +#define EXT2_FLAG_IBITMAP_TAIL_PROBLEM 0x2000000
>
> /*
> * Special flag in the ext2 inode i_flag field that means that this is
> diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
> index e86bacd53..27c684d62 100644
> --- a/lib/ext2fs/rw_bitmaps.c
> +++ b/lib/ext2fs/rw_bitmaps.c
> @@ -195,6 +195,16 @@ static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs)
> return 0;
> }
>
> +static int bitmap_tail_verify(unsigned char *bitmap, int first, int last)
> +{
> + int i;
> +
> + for (i = first; i <= last; i++)
> + if (bitmap[i] != 0xff)
> + return 0;
> + return 1;
> +}
> +
> static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
> {
> dgrp_t i;
> @@ -203,6 +213,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
> errcode_t retval;
> int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
> int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
> + int tail_flags = 0;
> int csum_flag;
> unsigned int cnt;
> blk64_t blk;
> @@ -315,6 +326,9 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
> EXT2_ET_BLOCK_BITMAP_CSUM_INVALID;
> goto cleanup;
> }
> + if (!bitmap_tail_verify(block_bitmap,
> + block_nbytes, fs->blocksize - 1))
> + tail_flags |= EXT2_FLAG_BBITMAP_TAIL_PROBLEM;
> } else
> memset(block_bitmap, 0, block_nbytes);
> cnt = block_nbytes << 3;
> @@ -347,6 +361,9 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
> EXT2_ET_INODE_BITMAP_CSUM_INVALID;
> goto cleanup;
> }
> + if (!bitmap_tail_verify(inode_bitmap,
> + inode_nbytes, fs->blocksize - 1))
> + tail_flags |= EXT2_FLAG_IBITMAP_TAIL_PROBLEM;
> } else
> memset(inode_bitmap, 0, inode_nbytes);
> cnt = inode_nbytes << 3;
> @@ -366,10 +383,15 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
> }
>
> success_cleanup:
> - if (inode_bitmap)
> + if (inode_bitmap) {
> ext2fs_free_mem(&inode_bitmap);
> - if (block_bitmap)
> + fs->flags &= ~EXT2_FLAG_IBITMAP_TAIL_PROBLEM;
> + }
> + if (block_bitmap) {
> ext2fs_free_mem(&block_bitmap);
> + fs->flags &= ~EXT2_FLAG_BBITMAP_TAIL_PROBLEM;
> + }
> + fs->flags |= tail_flags;
> return 0;
>
> cleanup:
> diff --git a/tests/f_bitmaps/expect.1 b/tests/f_bitmaps/expect.1
> index 715984d4d..2e91113db 100644
> --- a/tests/f_bitmaps/expect.1
> +++ b/tests/f_bitmaps/expect.1
> @@ -11,6 +11,8 @@ Fix? yes
> Inode bitmap differences: +11 -15
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/32 files (9.1% non-contiguous), 22/100 blocks
> diff --git a/tests/f_dup/expect.1 b/tests/f_dup/expect.1
> index 075e62c13..635a0dfc8 100644
> --- a/tests/f_dup/expect.1
> +++ b/tests/f_dup/expect.1
> @@ -30,6 +30,8 @@ Fix? yes
> Free blocks count wrong (62, counted=60).
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
> Padding at end of block bitmap is not set. Fix? yes
>
>
> diff --git a/tests/f_dup2/expect.1 b/tests/f_dup2/expect.1
> index 69aa21b4b..04d7304b4 100644
> --- a/tests/f_dup2/expect.1
> +++ b/tests/f_dup2/expect.1
> @@ -37,6 +37,8 @@ Fix? yes
> Free blocks count wrong (26, counted=22).
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
> Padding at end of block bitmap is not set. Fix? yes
>
>
> diff --git a/tests/f_dup3/expect.1 b/tests/f_dup3/expect.1
> index eab75a8dc..5f79cb891 100644
> --- a/tests/f_dup3/expect.1
> +++ b/tests/f_dup3/expect.1
> @@ -39,6 +39,8 @@ Fix? yes
> Free blocks count wrong (20, counted=19).
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 16/16 files (25.0% non-contiguous), 81/100 blocks
> diff --git a/tests/f_end-bitmap/expect.1 b/tests/f_end-bitmap/expect.1
> index 87e2fd647..85c7e67f4 100644
> --- a/tests/f_end-bitmap/expect.1
> +++ b/tests/f_end-bitmap/expect.1
> @@ -8,6 +8,8 @@ Pass 5: Checking group summary information
> Free blocks count wrong for group #0 (44, counted=63).
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
> Padding at end of block bitmap is not set. Fix? yes
>
>
> diff --git a/tests/f_illbbitmap/expect.1 b/tests/f_illbbitmap/expect.1
> index 8746d23a5..40996cd61 100644
> --- a/tests/f_illbbitmap/expect.1
> +++ b/tests/f_illbbitmap/expect.1
> @@ -22,6 +22,8 @@ Fix? yes
> Inode bitmap differences: -(12--21)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks
> diff --git a/tests/f_illibitmap/expect.1 b/tests/f_illibitmap/expect.1
> index 5bae25d14..bf21df7a7 100644
> --- a/tests/f_illibitmap/expect.1
> +++ b/tests/f_illibitmap/expect.1
> @@ -19,6 +19,8 @@ Pass 5: Checking group summary information
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks
> diff --git a/tests/f_illitable_flexbg/expect.1 b/tests/f_illitable_flexbg/expect.1
> index fa42a0f8b..4ac124639 100644
> --- a/tests/f_illitable_flexbg/expect.1
> +++ b/tests/f_illitable_flexbg/expect.1
> @@ -18,6 +18,8 @@ Pass 5: Checking group summary information
> Inode bitmap differences: -(65--128)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 12/256 files (0.0% non-contiguous), 31163/32768 blocks
> diff --git a/tests/f_lpf/expect.1 b/tests/f_lpf/expect.1
> index 4f2853c5b..6ef996bb6 100644
> --- a/tests/f_lpf/expect.1
> +++ b/tests/f_lpf/expect.1
> @@ -42,6 +42,8 @@ Fix? yes
> Free inodes count wrong (1, counted=0).
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 16/16 files (12.5% non-contiguous), 67/100 blocks
> diff --git a/tests/f_overfsblks/expect.1 b/tests/f_overfsblks/expect.1
> index e5b93f0d5..bc8f2a879 100644
> --- a/tests/f_overfsblks/expect.1
> +++ b/tests/f_overfsblks/expect.1
> @@ -13,6 +13,8 @@ Pass 5: Checking group summary information
> Inode bitmap differences: -(12--21)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks
> diff --git a/tests/f_super_bad_csum/expect.1 b/tests/f_super_bad_csum/expect.1
> index 25ced5c8a..12adee970 100644
> --- a/tests/f_super_bad_csum/expect.1
> +++ b/tests/f_super_bad_csum/expect.1
> @@ -5,8 +5,8 @@ Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Pass 5: Checking group summary information
> -Inode bitmap differences: Group 1 inode bitmap does not match checksum.
> -FIXED.
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/1024 files (0.0% non-contiguous), 1557/16384 blocks
> diff --git a/tests/j_corrupt_ext_jnl_sb_csum/expect b/tests/j_corrupt_ext_jnl_sb_csum/expect
> index 70a4fe721..4212a0007 100644
> --- a/tests/j_corrupt_ext_jnl_sb_csum/expect
> +++ b/tests/j_corrupt_ext_jnl_sb_csum/expect
> @@ -12,6 +12,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/128 files (0.0% non-contiguous), 66/2048 blocks
> diff --git a/tests/j_ext_long_trans/expect b/tests/j_ext_long_trans/expect
> index d379610e7..ea3c87fcb 100644
> --- a/tests/j_ext_long_trans/expect
> +++ b/tests/j_ext_long_trans/expect
> @@ -98,6 +98,8 @@ Fix? yes
> Free inodes count wrong (16372, counted=16373).
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/16384 files (0.0% non-contiguous), 6228/262144 blocks
> diff --git a/tests/j_long_trans/expect b/tests/j_long_trans/expect
> index 7a175414b..82b3caf17 100644
> --- a/tests/j_long_trans/expect
> +++ b/tests/j_long_trans/expect
> @@ -96,6 +96,8 @@ Fix? yes
> Free inodes count wrong (16372, counted=16373).
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
> Recreate journal? yes
>
> Creating journal (8192 blocks): Done.
> diff --git a/tests/j_long_trans_mcsum_32bit/expect b/tests/j_long_trans_mcsum_32bit/expect
> index a808d9f4d..ffae07a69 100644
> --- a/tests/j_long_trans_mcsum_32bit/expect
> +++ b/tests/j_long_trans_mcsum_32bit/expect
> @@ -135,6 +135,8 @@ Fix? yes
> Free inodes count wrong (32756, counted=32757).
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
> Recreate journal? yes
>
> Creating journal (16384 blocks): Done.
> diff --git a/tests/j_long_trans_mcsum_64bit/expect b/tests/j_long_trans_mcsum_64bit/expect
> index 76e109a42..e891def16 100644
> --- a/tests/j_long_trans_mcsum_64bit/expect
> +++ b/tests/j_long_trans_mcsum_64bit/expect
> @@ -134,6 +134,8 @@ Fix? yes
> Free inodes count wrong (32756, counted=32757).
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
> Recreate journal? yes
>
> Creating journal (16384 blocks): Done.
> diff --git a/tests/j_recover_csum2_32bit/expect.1 b/tests/j_recover_csum2_32bit/expect.1
> index 491784a25..fdbda36e2 100644
> --- a/tests/j_recover_csum2_32bit/expect.1
> +++ b/tests/j_recover_csum2_32bit/expect.1
> @@ -10,6 +10,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/8192 files (0.0% non-contiguous), 7739/131072 blocks
> diff --git a/tests/j_recover_csum2_64bit/expect.1 b/tests/j_recover_csum2_64bit/expect.1
> index 491784a25..fdbda36e2 100644
> --- a/tests/j_recover_csum2_64bit/expect.1
> +++ b/tests/j_recover_csum2_64bit/expect.1
> @@ -10,6 +10,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/8192 files (0.0% non-contiguous), 7739/131072 blocks
> diff --git a/tests/j_short_trans/expect b/tests/j_short_trans/expect
> index bcc8fe82a..2bd0e5069 100644
> --- a/tests/j_short_trans/expect
> +++ b/tests/j_short_trans/expect
> @@ -32,6 +32,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
> diff --git a/tests/j_short_trans_64bit/expect b/tests/j_short_trans_64bit/expect
> index f9971eba3..808dc61df 100644
> --- a/tests/j_short_trans_64bit/expect
> +++ b/tests/j_short_trans_64bit/expect
> @@ -34,6 +34,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/16384 files (0.0% non-contiguous), 5196/65536 blocks
> diff --git a/tests/j_short_trans_mcsum_64bit/expect b/tests/j_short_trans_mcsum_64bit/expect
> index d876ff095..d73e28297 100644
> --- a/tests/j_short_trans_mcsum_64bit/expect
> +++ b/tests/j_short_trans_mcsum_64bit/expect
> @@ -34,6 +34,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/32768 files (0.0% non-contiguous), 6353/131072 blocks
> diff --git a/tests/j_short_trans_old_csum/expect b/tests/j_short_trans_old_csum/expect
> index 29ac27fb3..6cf06d4a2 100644
> --- a/tests/j_short_trans_old_csum/expect
> +++ b/tests/j_short_trans_old_csum/expect
> @@ -34,6 +34,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
> diff --git a/tests/j_short_trans_open_recover/expect b/tests/j_short_trans_open_recover/expect
> index be6e363dc..3e868197d 100644
> --- a/tests/j_short_trans_open_recover/expect
> +++ b/tests/j_short_trans_open_recover/expect
> @@ -37,6 +37,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
> diff --git a/tests/j_short_trans_recover/expect b/tests/j_short_trans_recover/expect
> index 75867337f..508858c98 100644
> --- a/tests/j_short_trans_recover/expect
> +++ b/tests/j_short_trans_recover/expect
> @@ -34,6 +34,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
> diff --git a/tests/j_short_trans_recover_mcsum_64bit/expect b/tests/j_short_trans_recover_mcsum_64bit/expect
> index 9cc330978..8c637f122 100644
> --- a/tests/j_short_trans_recover_mcsum_64bit/expect
> +++ b/tests/j_short_trans_recover_mcsum_64bit/expect
> @@ -36,6 +36,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/32768 files (0.0% non-contiguous), 6353/131072 blocks
> diff --git a/tests/t_replay_and_set/expect b/tests/t_replay_and_set/expect
> index f63a73af5..3e19d92e9 100644
> --- a/tests/t_replay_and_set/expect
> +++ b/tests/t_replay_and_set/expect
> @@ -30,6 +30,8 @@ Fix? yes
> Inode bitmap differences: +(1--11)
> Fix? yes
>
> +Padding at end of inode bitmap is not set. Fix? yes
> +
>
> test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
> --
> 2.19.1
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2019-05-06 9:08 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-03-28 16:42 [PATCH] e2fsck: Check and fix tails of all bitmaps Jan Kara
2019-05-05 18:21 ` Theodore Ts'o
2019-05-05 21:48 ` Theodore Ts'o
2019-05-06 9:08 ` Jan Kara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox