diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index e05bf6f9..dc15db29 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -1806,6 +1806,21 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, (1 << (21 - ctx->fs->super->s_log_block_size)))) problem = PR_1_TOOBIG_DIR; + /* + * Uninitialized blocks in a directory? Clear the flag and + * we'll interpret the blocks later. + */ + if (is_dir && problem == 0 && + (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + fix_problem(ctx, PR_1_UNINIT_DBLOCK, pctx)) { + extent.e_flags &= ~EXT2_EXTENT_FLAGS_UNINIT; + pb->inode_modified = 1; + pctx->errcode = ext2fs_extent_replace(ehandle, 0, + &extent); + if (pctx->errcode) + return; + } + if (problem) { report_problem: pctx->blk = extent.e_pblk; diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 837d1110..a7291e55 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -972,6 +972,11 @@ static struct e2fsck_problem problem_table[] = { N_("@d @i %i @b %b should be at @b %c. "), PROMPT_FIX, 0 }, + /* Extents/inlinedata flag set on a device or socket inode */ + { PR_1_UNINIT_DBLOCK, + N_("@d @i %i has @x marked uninitialized at @b %c. "), + PROMPT_FIX, PR_PREEN_OK }, + /* Pass 1b errors */ /* Pass 1B: Rescan for duplicate/bad blocks */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index d3e66ad6..0a3347f9 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -565,6 +565,22 @@ struct problem_context { #define PR_1_EXTENT_INDEX_START_INVALID 0x01006D #define PR_1_EXTENT_END_OUT_OF_BOUNDS 0x01006E + +/* Inode has inline data, but superblock is missing INLINE_DATA feature. */ +#define PR_1_INLINE_DATA_FEATURE 0x01006F + +/* INLINE_DATA feature is set in a non-inline-data filesystem */ +#define PR_1_INLINE_DATA_SET 0x010070 + +/* file metadata collides with critical metadata */ +#define PR_1_CRITICAL_METADATA_COLLISION 0x010071 + +/* Directory inode has a missing block (hole) */ +#define PR_1_COLLAPSE_DBLOCK 0x010072 + +/* uninit directory block */ +#define PR_1_UNINIT_DBLOCK 0x010073 + /* * Pass 1b errors */ @@ -624,9 +640,6 @@ struct problem_context { /* Couldn't clone file (error) */ #define PR_1D_CLONE_ERROR 0x013008 -/* Directory inode has a missing block (hole) */ -#define PR_1_COLLAPSE_DBLOCK 0x010072 - /* * Pass 2 errors */ diff --git a/tests/f_uninit_dir/expect.1 b/tests/f_uninit_dir/expect.1 new file mode 100644 index 00000000..f0065f15 --- /dev/null +++ b/tests/f_uninit_dir/expect.1 @@ -0,0 +1,27 @@ +Pass 1: Checking inodes, blocks, and sizes +Directory inode 12 has extent marked uninitialized at block 0. Fix? yes + +Directory inode 14 has extent marked uninitialized at block 0. Fix? yes + +Pass 2: Checking directory structure +Directory inode 14, block #0, offset 0: directory corrupted +Salvage? yes + +Missing '.' in directory inode 14. +Fix? yes + +Setting filetype for entry '.' in ??? (14) to 2. +Missing '..' in directory inode 14. +Fix? yes + +Setting filetype for entry '..' in ??? (14) to 2. +Pass 3: Checking directory connectivity +'..' in /abc (14) is (0), should be / (2). +Fix? yes + +Pass 4: Checking reference counts +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +test_filesys: 14/128 files (0.0% non-contiguous), 20/512 blocks +Exit status is 1 diff --git a/tests/f_uninit_dir/expect.2 b/tests/f_uninit_dir/expect.2 new file mode 100644 index 00000000..7b28f436 --- /dev/null +++ b/tests/f_uninit_dir/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: 14/128 files (0.0% non-contiguous), 20/512 blocks +Exit status is 0 diff --git a/tests/f_uninit_dir/image.gz b/tests/f_uninit_dir/image.gz new file mode 100644 index 00000000..ac9131d2 Binary files /dev/null and b/tests/f_uninit_dir/image.gz differ diff --git a/tests/f_uninit_dir/name b/tests/f_uninit_dir/name new file mode 100644 index 00000000..d7f5bee3 --- /dev/null +++ b/tests/f_uninit_dir/name @@ -0,0 +1 @@ +fix uninit flag on directory extents and check the dir blocks