Whamcloud - gitweb
e2fsck: clear uninit flag on directory extents
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 18 Jul 2014 22:55:21 +0000 (15:55 -0700)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 25 Jul 2014 12:50:23 +0000 (08:50 -0400)
Directories can't have uninitialized extents, so offer to clear the
uninit flag when we find this situation.  The actual directory blocks
will be checked in pass 2 and 3 regardless of the uninit flag.

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

index e05bf6f..dc15db2 100644 (file)
@@ -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;
index 837d111..a7291e5 100644 (file)
@@ -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 */
index d3e66ad..0a3347f 100644 (file)
@@ -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 (file)
index 0000000..f0065f1
--- /dev/null
@@ -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 <The NULL inode> (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 (file)
index 0000000..7b28f43
--- /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: 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 (file)
index 0000000..ac9131d
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 (file)
index 0000000..d7f5bee
--- /dev/null
@@ -0,0 +1 @@
+fix uninit flag on directory extents and check the dir blocks