b1cbb812be
Rev SUSE:SLE-12:Update/5 Md5 fe895511cbe274cb847ab3dde5f22c5b 2019-07-05 12:10:32 mschnitzer None
356 lines
12 KiB
Diff
356 lines
12 KiB
Diff
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
|
|
References: bsc#1128383
|
|
|
|
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(-)
|
|
|
|
Index: e2fsprogs-1.42.11/e2fsck/pass5.c
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/e2fsck/pass5.c
|
|
+++ e2fsprogs-1.42.11/e2fsck/pass5.c
|
|
@@ -731,6 +731,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);
|
|
|
|
@@ -744,11 +745,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,
|
|
@@ -768,6 +770,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)
|
|
@@ -775,6 +791,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);
|
|
|
|
@@ -789,12 +806,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,
|
|
@@ -814,7 +832,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);
|
|
+ }
|
|
}
|
|
-
|
|
-
|
|
-
|
|
Index: e2fsprogs-1.42.11/lib/ext2fs/ext2fs.h
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/lib/ext2fs/ext2fs.h
|
|
+++ e2fsprogs-1.42.11/lib/ext2fs/ext2fs.h
|
|
@@ -192,6 +192,8 @@ typedef struct ext2_file *ext2_file_t;
|
|
#define EXT2_FLAG_PRINT_PROGRESS 0x40000
|
|
#define EXT2_FLAG_DIRECT_IO 0x80000
|
|
#define EXT2_FLAG_SKIP_MMP 0x100000
|
|
+#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
|
|
Index: e2fsprogs-1.42.11/lib/ext2fs/rw_bitmaps.c
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/lib/ext2fs/rw_bitmaps.c
|
|
+++ e2fsprogs-1.42.11/lib/ext2fs/rw_bitmaps.c
|
|
@@ -182,6 +182,16 @@ static errcode_t mark_uninit_bg_group_bl
|
|
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;
|
|
@@ -190,6 +200,7 @@ static errcode_t read_bitmaps(ext2_filsy
|
|
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 = 0;
|
|
unsigned int cnt;
|
|
blk64_t blk;
|
|
@@ -297,6 +308,9 @@ static errcode_t read_bitmaps(ext2_filsy
|
|
retval = EXT2_ET_BLOCK_BITMAP_READ;
|
|
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;
|
|
@@ -319,6 +333,9 @@ static errcode_t read_bitmaps(ext2_filsy
|
|
retval = EXT2_ET_INODE_BITMAP_READ;
|
|
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;
|
|
@@ -338,10 +355,15 @@ static errcode_t read_bitmaps(ext2_filsy
|
|
}
|
|
|
|
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:
|
|
Index: e2fsprogs-1.42.11/tests/f_bitmaps/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_bitmaps/expect.1
|
|
+++ e2fsprogs-1.42.11/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
|
|
Index: e2fsprogs-1.42.11/tests/f_dup/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_dup/expect.1
|
|
+++ e2fsprogs-1.42.11/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
|
|
|
|
|
|
Index: e2fsprogs-1.42.11/tests/f_dup2/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_dup2/expect.1
|
|
+++ e2fsprogs-1.42.11/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
|
|
|
|
|
|
Index: e2fsprogs-1.42.11/tests/f_dup3/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_dup3/expect.1
|
|
+++ e2fsprogs-1.42.11/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
|
|
Index: e2fsprogs-1.42.11/tests/f_end-bitmap/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_end-bitmap/expect.1
|
|
+++ e2fsprogs-1.42.11/tests/f_end-bitmap/expect.1
|
|
@@ -8,6 +8,8 @@ Pass 5: Checking group summary informati
|
|
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
|
|
|
|
|
|
Index: e2fsprogs-1.42.11/tests/f_illbbitmap/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_illbbitmap/expect.1
|
|
+++ e2fsprogs-1.42.11/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
|
|
Index: e2fsprogs-1.42.11/tests/f_illibitmap/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_illibitmap/expect.1
|
|
+++ e2fsprogs-1.42.11/tests/f_illibitmap/expect.1
|
|
@@ -19,6 +19,8 @@ Pass 5: Checking group summary informati
|
|
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
|
|
Index: e2fsprogs-1.42.11/tests/f_illitable_flexbg/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_illitable_flexbg/expect.1
|
|
+++ e2fsprogs-1.42.11/tests/f_illitable_flexbg/expect.1
|
|
@@ -18,6 +18,8 @@ Pass 5: Checking group summary informati
|
|
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
|
|
Index: e2fsprogs-1.42.11/tests/f_lpf/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_lpf/expect.1
|
|
+++ e2fsprogs-1.42.11/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
|
|
Index: e2fsprogs-1.42.11/tests/f_overfsblks/expect.1
|
|
===================================================================
|
|
--- e2fsprogs-1.42.11.orig/tests/f_overfsblks/expect.1
|
|
+++ e2fsprogs-1.42.11/tests/f_overfsblks/expect.1
|
|
@@ -13,6 +13,8 @@ Pass 5: Checking group summary informati
|
|
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
|