From 855c2ecb21d1556c26d61df9b014e1c79dbbc956 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 24 May 2017 21:56:36 -0400 Subject: [PATCH] e2fsck: fix sparse bmap to extent conversion When e2fsck is trying to convert a sparse block-mapped file to an extent file, we incorrectly merge block mappings that are physically contiguous but not logically contiguous because of insufficient checking with the extent we're constructing. Therefore, compare the logical offsets for contiguity as well. Signed-off-by: Darrick J. Wong Signed-off-by: Theodore Ts'o --- e2fsck/extents.c | 3 +- lib/support/plausible.h | 1 + tests/f_convert_bmap_sparse/expect.1 | 24 +++++++ tests/f_convert_bmap_sparse/expect.2 | 12 ++++ tests/f_convert_bmap_sparse/image.gz | Bin 0 -> 5585 bytes tests/f_convert_bmap_sparse/name | 1 + tests/f_convert_bmap_sparse/script | 117 +++++++++++++++++++++++++++++++++++ 7 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 tests/f_convert_bmap_sparse/expect.1 create mode 100644 tests/f_convert_bmap_sparse/expect.2 create mode 100644 tests/f_convert_bmap_sparse/image.gz create mode 100644 tests/f_convert_bmap_sparse/name create mode 100644 tests/f_convert_bmap_sparse/script diff --git a/e2fsck/extents.c b/e2fsck/extents.c index 98cf7c3..ef3146d 100644 --- a/e2fsck/extents.c +++ b/e2fsck/extents.c @@ -171,7 +171,8 @@ static int find_blocks(ext2_filsys fs, blk64_t *blocknr, e2_blkcnt_t blockcnt, list->count - 1; blk64_t end = last->e_len + 1; - if (last->e_pblk + last->e_len == *blocknr && + if (last->e_lblk + last->e_len == blockcnt && + last->e_pblk + last->e_len == *blocknr && end < (1ULL << 32)) { last->e_len++; #ifdef DEBUG diff --git a/lib/support/plausible.h b/lib/support/plausible.h index 594e4b1..b85150c 100644 --- a/lib/support/plausible.h +++ b/lib/support/plausible.h @@ -21,6 +21,7 @@ #define CHECK_FS_EXIST 0x0004 #define VERBOSE_CREATE 0x0008 #define NO_SIZE 0x0010 +#define QUIET_CHECK 0x0020 extern int check_plausibility(const char *device, int flags, int *ret_is_dev); diff --git a/tests/f_convert_bmap_sparse/expect.1 b/tests/f_convert_bmap_sparse/expect.1 new file mode 100644 index 0000000..74a8034 --- /dev/null +++ b/tests/f_convert_bmap_sparse/expect.1 @@ -0,0 +1,24 @@ +debugfs: stat /realmode.bin +Inode: 12 Type: regular Mode: 0775 Flags: 0x0 +Generation: 2022334337 Version: 0x00000001 +User: 1000 Group: 1000 Size: 21080 +File ACL: 0 Directory ACL: 0 +Links: 1 Blockcount: 16 +Fragment: Address: 0 Number: 0 Size: 0 +ctime: 0x5924849d -- Tue May 23 18:51:09 2017 +atime: 0x59247d36 -- Tue May 23 18:19:34 2017 +mtime: 0x591e1764 -- Thu May 18 21:51:32 2017 +BLOCKS: +(0):513, (4-8):514-518, (IND):58, (20):2005 +TOTAL: 8 + +Pass 1: Checking inodes, blocks, and sizes +Pass 1E: Optimizing extent trees +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +test_filesys: 12/256 files (8.3% non-contiguous), 65/2048 blocks +Exit status is 0 diff --git a/tests/f_convert_bmap_sparse/expect.2 b/tests/f_convert_bmap_sparse/expect.2 new file mode 100644 index 0000000..e5a3d44 --- /dev/null +++ b/tests/f_convert_bmap_sparse/expect.2 @@ -0,0 +1,12 @@ +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: 12/256 files (8.3% non-contiguous), 65/2048 blocks +Exit status is 0 +debugfs: ex /realmode.bin +Level Entries Logical Physical Length Flags + 0/ 0 1/ 3 0 - 0 513 - 513 1 + 0/ 0 2/ 3 4 - 8 514 - 518 5 + 0/ 0 3/ 3 20 - 20 2005 - 2005 1 diff --git a/tests/f_convert_bmap_sparse/image.gz b/tests/f_convert_bmap_sparse/image.gz new file mode 100644 index 0000000000000000000000000000000000000000..1f594fd4df402b5d50a78962bbebb20e9eae2032 GIT binary patch literal 5585 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 fJJ}sZB-bDL_r`yz*z_&LA=-1D`-cwwc $EXP1 + else + EXP1=$test_dir/expect.1 + fi +fi + +if [ "$EXP2"x = x ]; then + if [ -f $test_dir/expect.2.gz ]; then + EXP2=$test_name.2.tmp + gunzip < $test_dir/expect.2.gz > $EXP2 + else + EXP2=$test_dir/expect.2 + fi +fi + +if [ "$SKIP_GUNZIP" != "true" ] ; then + gunzip < $IMAGE > $TMPFILE +fi + +cp /dev/null $OUT1 + +eval $PREP_CMD + +echo 'stat /realmode.bin' > $TMPFILE.cmd +$DEBUGFS -f $TMPFILE.cmd $TMPFILE > $OUT1.new 2>&1 +rm -rf $TMPFILE.cmd +$TUNE2FS -O extent $TMPFILE >> $OUT1.new 2>&1 +$FSCK $FSCK_OPT -E bmap2extent -N test_filesys $TMPFILE >> $OUT1.new 2>&1 +status=$? +echo Exit status is $status >> $OUT1.new +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT1.new >> $OUT1 +rm -f $OUT1.new + +$FSCK $SECOND_FSCK_OPT -N test_filesys $TMPFILE > $OUT2.new 2>&1 +status=$? +echo Exit status is $status >> $OUT2.new +echo 'ex /realmode.bin' > $TMPFILE.cmd +$DEBUGFS -f $TMPFILE.cmd $TMPFILE >> $OUT2.new 2>&1 +rm -rf $TMPFILE.cmd +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT2.new > $OUT2 +rm -f $OUT2.new + +eval $AFTER_CMD + +if [ "$SKIP_VERIFY" != "true" ] ; then + rm -f $test_name.ok $test_name.failed + cmp -s $OUT1 $EXP1 + status1=$? + if [ "$ONE_PASS_ONLY" != "true" ]; then + cmp -s $OUT2 $EXP2 + status2=$? + else + status2=0 + fi + if [ "$PASS_ZERO" = "true" ]; then + cmp -s $test_name.0.log $test_dir/expect.0 + status3=$? + else + status3=0 + fi + + if [ -z "$test_description" ] ; then + description="$test_name" + else + description="$test_name: $test_description" + fi + + if [ "$status1" -eq 0 -a "$status2" -eq 0 -a "$status3" -eq 0 ] ; then + echo "$description: ok" + touch $test_name.ok + else + echo "$description: failed" + rm -f $test_name.failed + if [ "$PASS_ZERO" = "true" ]; then + diff $DIFF_OPTS $test_dir/expect.0 \ + $test_name.0.log >> $test_name.failed + fi + diff $DIFF_OPTS $EXP1 $OUT1 >> $test_name.failed + if [ "$ONE_PASS_ONLY" != "true" ]; then + diff $DIFF_OPTS $EXP2 $OUT2 >> $test_name.failed + fi + fi + rm -f tmp_expect +fi + +if [ "$SKIP_CLEANUP" != "true" ] ; then + unset IMAGE FSCK_OPT SECOND_FSCK_OPT OUT1 OUT2 EXP1 EXP2 + unset SKIP_VERIFY SKIP_CLEANUP SKIP_GUNZIP ONE_PASS_ONLY PREP_CMD + unset DESCRIPTION SKIP_UNLINK AFTER_CMD PASS_ZERO +fi + -- 1.8.3.1