1dc728923Sopenharmony_ciFrom 79a7b5e1f387caf907ec88460cdb39b8364bfb0b Mon Sep 17 00:00:00 2001
2dc728923Sopenharmony_ciFrom: Theodore Ts'o <tytso@mit.edu>
3dc728923Sopenharmony_ciDate: Thu, 16 Mar 2023 22:57:10 -0400
4dc728923Sopenharmony_ciSubject: e2fsck: fix bad htree checksums in preen mode
5dc728923Sopenharmony_ci
6dc728923Sopenharmony_ciWe attempt to fix directories which have a bad/corrupted htree index
7dc728923Sopenharmony_cinode by completely rebuilding the directory htree nodes.  Since this
8dc728923Sopenharmony_ciis a very safe thing to do and has no risk of losing directory
9dc728923Sopenharmony_cientries, we've enabled this for preen mode.  Unfortunately, subsequent
10dc728923Sopenharmony_ciindex nodes look like empty directory entries that fill the entire
11dc728923Sopenharmony_ciblock --- without a checksum at the end of the directory.  So these
12dc728923Sopenharmony_cinodes will be treated as a completely corrupted directory block, and
13dc728923Sopenharmony_cithis will *not* be fixed while in preen mode.
14dc728923Sopenharmony_ci
15dc728923Sopenharmony_ciSo add code to treat an empty directory entry which covers the entire
16dc728923Sopenharmony_ciblock as valid if the directory is already on the list of inodes to be
17dc728923Sopenharmony_cirebuilt.
18dc728923Sopenharmony_ci
19dc728923Sopenharmony_ciAddresses-Gooogle-Bug: 178607853
20dc728923Sopenharmony_ciSigned-off-by: Theodore Ts'o <tytso@mit.edu>
21dc728923Sopenharmony_ci---
22dc728923Sopenharmony_ci e2fsck/pass2.c | 16 ++++++++++++++--
23dc728923Sopenharmony_ci 1 file changed, 14 insertions(+), 2 deletions(-)
24dc728923Sopenharmony_ci
25dc728923Sopenharmony_cidiff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
26dc728923Sopenharmony_ciindex 287360943..2700e3409 100644
27dc728923Sopenharmony_ci--- a/e2fsck/pass2.c
28dc728923Sopenharmony_ci+++ b/e2fsck/pass2.c
29dc728923Sopenharmony_ci@@ -1341,7 +1341,18 @@ skip_checksum:
30dc728923Sopenharmony_ci 			    (rec_len < min_dir_len) ||
31dc728923Sopenharmony_ci 			    ((rec_len % 4) != 0) ||
32dc728923Sopenharmony_ci 			    ((ext2fs_dir_rec_len(ext2fs_dirent_name_len(dirent),
33dc728923Sopenharmony_ci-						 extended)) > rec_len)) {
34dc728923Sopenharmony_ci+						 extended)) > rec_len))
35dc728923Sopenharmony_ci+				problem = PR_2_DIR_CORRUPTED;
36dc728923Sopenharmony_ci+			if (problem) {
37dc728923Sopenharmony_ci+				if ((offset == 0) &&
38dc728923Sopenharmony_ci+				    (rec_len == fs->blocksize) &&
39dc728923Sopenharmony_ci+				    (dirent->inode == 0) &&
40dc728923Sopenharmony_ci+				    e2fsck_dir_will_be_rehashed(ctx, ino)) {
41dc728923Sopenharmony_ci+					problem = 0;
42dc728923Sopenharmony_ci+					max_block_size = fs->blocksize;
43dc728923Sopenharmony_ci+				}
44dc728923Sopenharmony_ci+			}
45dc728923Sopenharmony_ci+			if (problem) {
46dc728923Sopenharmony_ci 				if (fix_problem(ctx, PR_2_DIR_CORRUPTED,
47dc728923Sopenharmony_ci 						&cd->pctx)) {
48dc728923Sopenharmony_ci #ifdef WORDS_BIGENDIAN
49dc728923Sopenharmony_ci@@ -1573,7 +1584,8 @@ skip_checksum:
50dc728923Sopenharmony_ci 		 */
51dc728923Sopenharmony_ci 		if (!(ctx->flags & E2F_FLAG_RESTART_LATER) &&
52dc728923Sopenharmony_ci 		    !(ext2fs_test_inode_bitmap2(ctx->inode_used_map,
53dc728923Sopenharmony_ci-						dirent->inode)))
54dc728923Sopenharmony_ci+						dirent->inode))
55dc728923Sopenharmony_ci+			)
56dc728923Sopenharmony_ci 			problem = PR_2_UNUSED_INODE;
57dc728923Sopenharmony_ci 
58dc728923Sopenharmony_ci 		if (problem) {
59dc728923Sopenharmony_ci-- 
60dc728923Sopenharmony_cicgit 
61