Whamcloud - gitweb
e2fsck: handle multiple *ind block collisions with critical metadata
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 27 Jan 2015 18:05:51 +0000 (13:05 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 27 Jan 2015 18:12:59 +0000 (13:12 -0500)
An earlier patch tried to detect indirect blocks that conflicted with
critical FS metadata for the purpose of preventing corrections being
made to those indirect blocks.  Unfortunately, that patch cannot
handle more than one conflicting *ind block per file; therefore, use
the ref_block parameter to test the metadata block map to decide if
we need to avoid fixing the *ind block when we're iterating the
block's entries.  (We have to iterate the block to capture any blocks
that the block points to, as they could be in use.)

As a side note, in 1B we'll reallocate all those conflicting *ind
blocks and restart fsck, so the contents will be checked eventually.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
e2fsck/pass1.c
tests/f_ind_inode_collision/expect.1 [new file with mode: 0644]
tests/f_ind_inode_collision/expect.2 [new file with mode: 0644]
tests/f_ind_inode_collision/image.gz [new file with mode: 0644]
tests/f_ind_inode_collision/name [new file with mode: 0644]

index faafa7c..2089943 100644 (file)
@@ -93,7 +93,6 @@ struct process_block_struct {
        struct problem_context *pctx;
        ext2fs_block_bitmap fs_meta_blocks;
        e2fsck_t        ctx;
-       blk64_t         bad_ref;
        region_t        region;
 };
 
@@ -2791,7 +2790,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
        pb.pctx = pctx;
        pb.ctx = ctx;
        pb.inode_modified = 0;
-       pb.bad_ref = 0;
        pctx->ino = ino;
        pctx->errcode = 0;
 
@@ -3175,7 +3173,6 @@ static int process_block(ext2_filsys fs,
        if (blockcnt < 0 &&
            p->ino != EXT2_RESIZE_INO &&
            ext2fs_test_block_bitmap2(ctx->block_metadata_map, blk)) {
-               p->bad_ref = blk;
                pctx->blk = blk;
                fix_problem(ctx, PR_1_CRITICAL_METADATA_COLLISION, pctx);
                ctx->flags |= E2F_FLAG_RESTART_LATER;
@@ -3185,13 +3182,23 @@ static int process_block(ext2_filsys fs,
                p->num_illegal_blocks++;
                /*
                 * A bit of subterfuge here -- we're trying to fix a block
-                * mapping, but know that the IND/DIND/TIND block has collided
+                * mapping, but the IND/DIND/TIND block could have collided
                 * with some critical metadata.  So, fix the in-core mapping so
                 * iterate won't go insane, but return 0 instead of
                 * BLOCK_CHANGED so that it won't write the remapping out to
                 * our multiply linked block.
+                *
+                * Even if we previously determined that an *IND block
+                * conflicts with critical metadata, we must still try to
+                * iterate the *IND block as if it is an *IND block to find and
+                * mark the blocks it points to.  Better to be overly cautious
+                * with the used_blocks map so that we don't move the *IND
+                * block to a block that's really in use!
                 */
-               if (p->bad_ref && ref_block == p->bad_ref) {
+               if (p->ino != EXT2_RESIZE_INO &&
+                   ref_block != 0 &&
+                   ext2fs_test_block_bitmap2(ctx->block_metadata_map,
+                                             ref_block)) {
                        *block_nr = 0;
                        return 0;
                }
diff --git a/tests/f_ind_inode_collision/expect.1 b/tests/f_ind_inode_collision/expect.1
new file mode 100644 (file)
index 0000000..012cd9f
--- /dev/null
@@ -0,0 +1,147 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 block 41 conflicts with critical metadata, skipping block checks.
+Inode 12 block 40 conflicts with critical metadata, skipping block checks.
+Inode 12 block 34 conflicts with critical metadata, skipping block checks.
+Illegal block number passed to ext2fs_test_block_bitmap #16777215 for metadata block map
+Inode 12 block 1 conflicts with critical metadata, skipping block checks.
+Inode 12, i_size is 33, should be 25227264.  Fix? yes
+
+Inode 12, i_blocks is 999, should be 184.  Fix? yes
+
+
+Running additional passes to resolve blocks claimed by more than one inode...
+Pass 1B: Rescanning for multiply-claimed blocks
+Multiply-claimed block(s) in inode 2: 3
+Multiply-claimed block(s) in inode 7: 11
+Multiply-claimed block(s) in inode 11: 4--7
+Multiply-claimed block(s) in inode 12: 41 40Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #16877 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #4096 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #196608 for multiply claimed block map
+ 34 8 3Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #33152 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #4243456 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #65536 for multiply claimed block map
+ 28 8 11 1Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #16832 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #16384 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #131072 for multiply claimed block map
+ 28 4--7Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #33206 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #25227264 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529397 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529397 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529397 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #65536 for multiply claimed block map
+ 28 41Illegal block number passed to ext2fs_test_block_bitmap #1421529397 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #16777215 for multiply claimed block map
+ 28
+Error while iterating over blocks in inode 12 (pass1b): Illegal indirect block found
+Pass 1C: Scanning directories for inodes with multiply-claimed blocks
+Pass 1D: Reconciling multiply-claimed blocks
+(There are 3 inodes containing multiply-claimed blocks.)
+
+File / (inode #2, mod time Sat Jan 17 21:16:16 2015) 
+  has 1 multiply-claimed block(s), shared with 1 file(s):
+       /a (inode #12, mod time Sat Jan 17 21:16:37 2015)
+Clone multiply-claimed blocks? yes
+
+File /lost+found (inode #11, mod time Sat Jan 17 21:16:16 2015) 
+  has 4 multiply-claimed block(s), shared with 1 file(s):
+       /a (inode #12, mod time Sat Jan 17 21:16:37 2015)
+Clone multiply-claimed blocks? yes
+
+File /a (inode #12, mod time Sat Jan 17 21:16:37 2015) 
+  has 17 multiply-claimed block(s), shared with 4 file(s):
+       <filesystem metadata>
+       /lost+found (inode #11, mod time Sat Jan 17 21:16:16 2015)
+       <The group descriptor inode> (inode #7, mod time Sat Jan 17 21:16:16 2015)
+       / (inode #2, mod time Sat Jan 17 21:16:16 2015)
+Clone multiply-claimed blocks? yes
+
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #16877 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #4096 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #196608 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #33152 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #4243456 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #65536 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #16832 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #16384 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #131072 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529376 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #33206 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #25227264 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529397 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529397 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529397 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #65536 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #1421529397 for multiply claimed block map
+Illegal block number passed to ext2fs_test_block_bitmap #16777215 for multiply claimed block map
+Pass 2: Checking directory structure
+Restarting e2fsck from the beginning...
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 has illegal block(s).  Clear? yes
+
+Illegal block #1038 (1421529376) in inode 12.  CLEARED.
+Illegal block #1039 (1421529376) in inode 12.  CLEARED.
+Illegal block #1040 (1421529376) in inode 12.  CLEARED.
+Illegal block #1100 (16877) in inode 12.  CLEARED.
+Illegal block #1101 (4096) in inode 12.  CLEARED.
+Illegal block #1102 (1421529376) in inode 12.  CLEARED.
+Illegal block #1103 (1421529376) in inode 12.  CLEARED.
+Illegal block #1104 (1421529376) in inode 12.  CLEARED.
+Illegal block #1106 (196608) in inode 12.  CLEARED.
+Illegal block #1136 (1421529376) in inode 12.  CLEARED.
+Illegal block #1420 (33152) in inode 12.  CLEARED.
+Too many illegal blocks in inode 12.
+Clear inode? yes
+
+Restarting e2fsck from the beginning...
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Entry 'a' in / (2) has deleted/unused inode 12.  Clear? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences:  -(3--7) -(15--17) -(19--24)
+Fix? yes
+
+Inode bitmap differences:  -12
+Fix? yes
+
+Free inodes count wrong for group #0 (116, counted=117).
+Fix? yes
+
+Free inodes count wrong (116, counted=117).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/128 files (9.1% non-contiguous), 18/512 blocks
+Exit status is 1
diff --git a/tests/f_ind_inode_collision/expect.2 b/tests/f_ind_inode_collision/expect.2
new file mode 100644 (file)
index 0000000..d0a6dac
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/128 files (9.1% non-contiguous), 18/512 blocks
+Exit status is 0
diff --git a/tests/f_ind_inode_collision/image.gz b/tests/f_ind_inode_collision/image.gz
new file mode 100644 (file)
index 0000000..924d220
Binary files /dev/null and b/tests/f_ind_inode_collision/image.gz differ
diff --git a/tests/f_ind_inode_collision/name b/tests/f_ind_inode_collision/name
new file mode 100644 (file)
index 0000000..11feee3
--- /dev/null
@@ -0,0 +1 @@
+multiple *ind collisions with critical metadata