]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
e2fsck: check and fix tails of all bitmap blocks
authorTheodore Ts'o <tytso@mit.edu>
Sun, 5 May 2019 20:43:33 +0000 (16:43 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 6 May 2019 14:15:29 +0000 (10:15 -0400)
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>
Reviewed-by: Jan Kara <jack@suse.cz>
29 files changed:
e2fsck/pass5.c
lib/ext2fs/ext2fs.h
lib/ext2fs/rw_bitmaps.c
tests/f_bitmaps/expect.1
tests/f_dup/expect.1
tests/f_dup2/expect.1
tests/f_dup3/expect.1
tests/f_end-bitmap/expect.1
tests/f_illbbitmap/expect.1
tests/f_illibitmap/expect.1
tests/f_illitable_flexbg/expect.1
tests/f_lpf/expect.1
tests/f_overfsblks/expect.1
tests/f_super_bad_csum/expect.1
tests/j_corrupt_ext_jnl_sb_csum/expect
tests/j_ext_long_trans/expect
tests/j_long_trans/expect
tests/j_long_trans_mcsum_32bit/expect
tests/j_long_trans_mcsum_64bit/expect
tests/j_recover_csum2_32bit/expect.1
tests/j_recover_csum2_64bit/expect.1
tests/j_short_trans/expect
tests/j_short_trans_64bit/expect
tests/j_short_trans_mcsum_64bit/expect
tests/j_short_trans_old_csum/expect
tests/j_short_trans_open_recover/expect
tests/j_short_trans_recover/expect
tests/j_short_trans_recover_mcsum_64bit/expect
tests/t_replay_and_set/expect

index 7803e8b80178031e2e874f7209659b6395a8d79a..810090970b2bfdd0ae0251547f8e758a83ddddc5 100644 (file)
@@ -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);
+       }
 }
-
-
-
index 7d7c346df4f8bc026cf6fdb35e5fb0780bb24f1a..59fd97426f917ac19b8dfdf2231411434bca7372 100644 (file)
@@ -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
index e86bacd5321acd76ab400fca87403ed93c992c15..f1c4188bad1ab22f405455bf2088e5ec2abc3ecb 100644 (file)
@@ -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((unsigned char *) 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((unsigned char *) 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:
index 715984d4dc74665ea24d72f1ce94e4dfa204512d..2e91113db65ab4226caf8a59143825d64c4f5345 100644 (file)
@@ -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 075e62c13a21febddd640d1866103ad591485b3e..635a0dfc8d55e28857ecf7d1658d4269e1a22fb0 100644 (file)
@@ -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 69aa21b4b743a41c872d2727f35936a101d381df..04d7304b400b89acd5b7fb8e864f27beb6652f01 100644 (file)
@@ -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 eab75a8dc8b4fc774b23b64d8beab882811c3d4a..5f79cb891c3a93c4e5797a45665b49b86f613039 100644 (file)
@@ -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 87e2fd647bbbd37e0e369f942c1ed2b97f349129..85c7e67f4a4c284ca37ac267665e7cf8383256d9 100644 (file)
@@ -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
 
 
index 8746d23a5fd544316d91b2e03b3624af2cb9496e..40996cd61ab195d639644d667274b62a3cf74325 100644 (file)
@@ -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 5bae25d140082743c7d2c1b894195b3e82aa700e..bf21df7a77e60f21e8bf632afd05c1f54bdf668b 100644 (file)
@@ -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
index fa42a0f8b1b8b21dde97d17579607ca98a2bdfd4..4ac124639a4b7193c75e44d3b16ee6b4b74ebd7a 100644 (file)
@@ -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
index 4f2853c5b19764becbcde9549a38da4446b01318..6ef996bb6187c38c42de3b5453596b1e8f8826bf 100644 (file)
@@ -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 e5b93f0d552af115d98a3c9abe9286f0640d1c7f..bc8f2a87995c40957d245e0dbe3d54f4d538e60a 100644 (file)
@@ -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
index 25ced5c8a5c06e7615b14971e99933657822b7cc..12adee9708f88fe315069238dcaee1222f34fced 100644 (file)
@@ -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
index 70a4fe721fcd472a9b21a23d513d4eae51e538d1..4212a00076070a66d64e4de0ac65eb2cad69bf4b 100644 (file)
@@ -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
index d379610e7c2af738fea5d135a4c3a91e11a0af38..ea3c87fcbdb3a301b32c6c77ba8999d60ba38b2d 100644 (file)
@@ -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
index 7a175414be5f031bec08769318994ec963e54f19..82b3caf1709088cc5e6ec3fc39d1feeb7f8476bc 100644 (file)
@@ -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.
index a808d9f4d7061dec3cea3ff7c92dbe7b585fc031..ffae07a69b291da5bbcd5bbd320d9cb9f4f39dcd 100644 (file)
@@ -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.
index 76e109a421025dc28676844165a7a85d22c2f6cc..e891def166cfbc935a52a4eeccdcead930736468 100644 (file)
@@ -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.
index 491784a256e270ccbf759e8df6421bbf28a7f534..fdbda36e2b0d6eabd6928887c8a1b5ea4645e748 100644 (file)
@@ -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
index 491784a256e270ccbf759e8df6421bbf28a7f534..fdbda36e2b0d6eabd6928887c8a1b5ea4645e748 100644 (file)
@@ -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
index bcc8fe82a57a4371686c07a817a067780ed4a1cb..2bd0e50698d98ab004cbf04359630db298084e03 100644 (file)
@@ -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
index f9971eba383a4fae3b8f843af444cc48a37af6e9..808dc61dfe80f08e2e0122b0519b0c1c171fefed 100644 (file)
@@ -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
index d876ff095542beca0d62aa03dbe5824d17956ef3..d73e28297ec3308ab323a1eb00a3d54e95f32199 100644 (file)
@@ -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
index 29ac27fb3c9c1eb5e889ed854673a2a809bad504..6cf06d4a2e727cb628c7c8e0a3438873e49a98be 100644 (file)
@@ -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
index be6e363dc8aca6e9be36a2be13385257f2989937..3e868197dad56ca5a42e395db3a17d6787bb11c2 100644 (file)
@@ -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
index 75867337fafdbdba753adcea69f96a7013a95ebc..508858c986f455f991e889616d1260e9fd041cab 100644 (file)
@@ -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
index 9cc3309785607f01f7eb2c5af7fc9ed6ab83b906..8c637f122ea92353a9a67f4abedac35942035fe1 100644 (file)
@@ -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
index f63a73af52ea45ec9c83b7d735f411c08c0856d1..3e19d92e97c082bf2f4457fc6f0bae15bd492abf 100644 (file)
@@ -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