While deleting a bad inode in fsck pass2, we should remove clusters only once. We do it by remembering last released cluster while deleting clusters one by one. Signed-off-by: Harshad Shirwadkar <harshads@xxxxxxxxxx> --- e2fsck/pass2.c | 12 ++++++++++-- tests/f_bigalloc_badinode/expect.1 | 12 ++++++++++++ tests/f_bigalloc_badinode/expect.2 | 7 +++++++ tests/f_bigalloc_badinode/name | 1 + tests/f_bigalloc_badinode/script | 24 ++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 tests/f_bigalloc_badinode/expect.1 create mode 100644 tests/f_bigalloc_badinode/expect.2 create mode 100644 tests/f_bigalloc_badinode/name create mode 100644 tests/f_bigalloc_badinode/script diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index e922876d..c6aff71a 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -1610,6 +1610,7 @@ abort_free_dict: struct del_block { e2fsck_t ctx; e2_blkcnt_t num; + blk64_t last_cluster; }; /* @@ -1624,14 +1625,20 @@ static int deallocate_inode_block(ext2_filsys fs, void *priv_data) { struct del_block *p = priv_data; + blk64_t cluster = EXT2FS_B2C(fs, *block_nr); if (*block_nr == 0) return 0; + + if (cluster == p->last_cluster) + return 0; + + p->last_cluster = cluster; if ((*block_nr < fs->super->s_first_data_block) || (*block_nr >= ext2fs_blocks_count(fs->super))) return 0; - if ((*block_nr % EXT2FS_CLUSTER_RATIO(fs)) == 0) - ext2fs_block_alloc_stats2(fs, *block_nr, -1); + + ext2fs_block_alloc_stats2(fs, *block_nr, -1); p->num++; return 0; } @@ -1692,6 +1699,7 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) del_block.ctx = ctx; del_block.num = 0; + del_block.last_cluster = 0; pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf, deallocate_inode_block, &del_block); diff --git a/tests/f_bigalloc_badinode/expect.1 b/tests/f_bigalloc_badinode/expect.1 new file mode 100644 index 00000000..10ba096f --- /dev/null +++ b/tests/f_bigalloc_badinode/expect.1 @@ -0,0 +1,12 @@ +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Symlink /testfile (inode #12) is invalid. +Clear? yes + +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +test_filesys: 11/64 files (0.0% non-contiguous), 96/1024 blocks +Exit status is 1 diff --git a/tests/f_bigalloc_badinode/expect.2 b/tests/f_bigalloc_badinode/expect.2 new file mode 100644 index 00000000..30392d42 --- /dev/null +++ b/tests/f_bigalloc_badinode/expect.2 @@ -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/64 files (0.0% non-contiguous), 96/1024 blocks +Exit status is 0 diff --git a/tests/f_bigalloc_badinode/name b/tests/f_bigalloc_badinode/name new file mode 100644 index 00000000..e1ed2160 --- /dev/null +++ b/tests/f_bigalloc_badinode/name @@ -0,0 +1 @@ +delete bad inode handling for bigalloc filesystems diff --git a/tests/f_bigalloc_badinode/script b/tests/f_bigalloc_badinode/script new file mode 100644 index 00000000..9113e9c8 --- /dev/null +++ b/tests/f_bigalloc_badinode/script @@ -0,0 +1,24 @@ +if test -x $DEBUGFS_EXE; then + +SKIP_GUNZIP="true" +TEST_DATA="$test_name.tmp" + +dd if=$TEST_BITS of=$TEST_DATA bs=4k count=2 seek=1> /dev/null 2>&1 + +touch $TMPFILE +mke2fs -Fq -t ext4 -O bigalloc -C 16384 $TMPFILE 1M > /dev/null 2>&1 +debugfs -w $TMPFILE << EOF > /dev/null 2>&1 +write $TEST_DATA testfile +set_inode_field testfile i_mode 0120000 +quit +EOF + +. $cmd_dir/run_e2fsck + +rm -f $TEST_DATA + +unset E2FSCK_TIME TEST_DATA + +else #if test -x $DEBUGFS_EXE; then + echo "$test_name: $test_description: skipped" +fi -- 2.17.0.rc0.231.g781580f067-goog