Merge branch 'maint' into next
Conflicts:
e2fsck/pass1.c
e2fsck/problem.h
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 648c578..10ffe39 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -1983,6 +1983,22 @@
}
}
+ /*
+ * Uninitialized blocks in a directory? Clear the flag and
+ * we'll interpret the blocks later.
+ */
+ if (try_repairs && 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;
+ failed_csum = 0;
+ }
+
if (try_repairs && problem) {
report_problem:
pctx->blk = extent.e_pblk;
@@ -2619,6 +2635,21 @@
return 0;
}
+ /*
+ * For a directory, add logical block zero for processing even if it's
+ * not mapped or we'll be perennially stuck with broken "." and ".."
+ * entries.
+ */
+ if (p->is_dir && blockcnt == 0 && blk == 0) {
+ pctx->errcode = ext2fs_add_dir_block2(fs->dblist, p->ino, 0, 0);
+ if (pctx->errcode) {
+ pctx->blk = blk;
+ pctx->num = blockcnt;
+ goto failed_add_dir_block;
+ }
+ p->last_db_block++;
+ }
+
if (blk == 0)
return 0;
@@ -2710,6 +2741,17 @@
blk = *block_nr = 0;
ret_code = BLOCK_CHANGED;
p->inode_modified = 1;
+ /*
+ * If the directory block is too big and is beyond the
+ * end of the FS, don't bother trying to add it for
+ * processing -- the kernel would never have created a
+ * directory this large, and we risk an ENOMEM abort.
+ * In any case, the toobig handler for extent-based
+ * directories also doesn't feed toobig blocks to
+ * pass 2.
+ */
+ if (problem == PR_1_TOOBIG_DIR)
+ return ret_code;
goto mark_dir;
} else
return 0;
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index a1986c6..60c02af 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1043,6 +1043,11 @@
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 ab6ced7..6cd3d50 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -603,6 +603,12 @@
/* 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
*/
@@ -665,9 +671,6 @@
/* 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_emptydir/expect.1 b/tests/f_emptydir/expect.1
new file mode 100644
index 0000000..c612621
--- /dev/null
+++ b/tests/f_emptydir/expect.1
@@ -0,0 +1,19 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12, i_size is 1024, should be 0. Fix? yes
+
+Pass 2: Checking directory structure
+Directory inode 12 has an unallocated block #0. Allocate? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Free blocks count wrong for group #0 (957, counted=956).
+Fix? yes
+
+Free blocks count wrong (957, counted=956).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/256 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 1
diff --git a/tests/f_emptydir/expect.2 b/tests/f_emptydir/expect.2
new file mode 100644
index 0000000..75c0515
--- /dev/null
+++ b/tests/f_emptydir/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: 12/256 files (16.7% non-contiguous), 1092/2048 blocks
+Exit status is 0
diff --git a/tests/f_emptydir/image.gz b/tests/f_emptydir/image.gz
new file mode 100644
index 0000000..1b6f8f8
--- /dev/null
+++ b/tests/f_emptydir/image.gz
Binary files differ
diff --git a/tests/f_emptydir/name b/tests/f_emptydir/name
new file mode 100644
index 0000000..d5bc660
--- /dev/null
+++ b/tests/f_emptydir/name
@@ -0,0 +1,2 @@
+always iterate dir block 0 or e2fsck goes into infinite loop
+
diff --git a/tests/f_hugedir_blocks/expect.1 b/tests/f_hugedir_blocks/expect.1
new file mode 100644
index 0000000..798a7ac
--- /dev/null
+++ b/tests/f_hugedir_blocks/expect.1
@@ -0,0 +1,10 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 is too big. Truncate? yes
+
+Block #1074791435 (13) causes directory to be too big. CLEARED.
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 12/128 files (8.3% non-contiguous), 22/512 blocks
+Exit status is 0
diff --git a/tests/f_hugedir_blocks/expect.2 b/tests/f_hugedir_blocks/expect.2
new file mode 100644
index 0000000..ac5f4c1
--- /dev/null
+++ b/tests/f_hugedir_blocks/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: 12/128 files (8.3% non-contiguous), 22/512 blocks
+Exit status is 0
diff --git a/tests/f_hugedir_blocks/image.gz b/tests/f_hugedir_blocks/image.gz
new file mode 100644
index 0000000..1d54de8
--- /dev/null
+++ b/tests/f_hugedir_blocks/image.gz
Binary files differ
diff --git a/tests/f_hugedir_blocks/name b/tests/f_hugedir_blocks/name
new file mode 100644
index 0000000..d74761b
--- /dev/null
+++ b/tests/f_hugedir_blocks/name
@@ -0,0 +1 @@
+crash e2fsck with a dir with an impossibly high logical blk offset
diff --git a/tests/f_uninit_dir/expect.1 b/tests/f_uninit_dir/expect.1
new file mode 100644
index 0000000..f0065f1
--- /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 <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
index 0000000..7b28f43
--- /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 0000000..ac9131d
--- /dev/null
+++ b/tests/f_uninit_dir/image.gz
Binary files differ
diff --git a/tests/f_uninit_dir/name b/tests/f_uninit_dir/name
new file mode 100644
index 0000000..d7f5bee
--- /dev/null
+++ b/tests/f_uninit_dir/name
@@ -0,0 +1 @@
+fix uninit flag on directory extents and check the dir blocks