aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Dilger <adilger@whamcloud.com>2021-05-31 17:31:23 -0600
committerTheodore Ts'o <tytso@mit.edu>2021-07-06 15:43:21 -0400
commit63f44aafb1f20f8dffdede1e824ce8cbf252bbfc (patch)
tree24f19d2db5e03c987b59016bf4baf895018668b8
parenta39e58bab602dc39cf263954c4484c8d12bf306c (diff)
downloade2fsprogs-63f44aafb1f20f8dffdede1e824ce8cbf252bbfc.tar.gz
e2fsck: fix ".." more gracefully if possible
If the "." entry is corrupted, it will be reset in check_dot(). It is possible that the ".." entry can be recovered from the directory block instead of also resetting it immediately. If it appears that there is a valid ".." entry in the block, allow that to be used, and let check_dotdot() verify the dirent itself. When resetting the "." and ".." entries, use EXT2_FT_DIR as the file type instead of EXT2_FT_UNKNOWN for the very common case of filesystems with the "filetype" feature, to avoid later problems that can be easily avoided. This can't always be done, even if filesystems without "filetype" are totally obsolete, because many old test images do not have this feature enabled. Fixup affected tests using the new "repair-test" script that updates the expect.[12] files from $test.[12].log for the given tests and re-runs the test to ensure it now passes. Signed-off-by: Andreas dilger <adilger@whamcloud.com> Reviewed-by: Artem Blagodarenko <artem.blagodarenko@hpe.com> Lustre-bug-Id: https://jira.whamcloud.com/browse/LU-14710 Change-Id: Ia5e579bcf31a9d9ee260d5640de6dbdb60514823 Reviewed-on: https://review.whamcloud.com/43858 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--e2fsck/pass2.c28
-rw-r--r--tests/f_baddotdir/expect.19
-rw-r--r--tests/f_baddotdir/expect.22
-rw-r--r--tests/f_baddotdir/image.gzbin564 -> 592 bytes
-rw-r--r--tests/f_dir_bad_csum/expect.12
-rw-r--r--tests/f_rebuild_csum_rootdir/expect.12
-rw-r--r--tests/f_resize_inode_meta_bg/expect.14
-rw-r--r--tests/f_uninit_dir/expect.12
-rwxr-xr-xtests/scripts/repair-test9
9 files changed, 36 insertions, 22 deletions
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index e504b30ad..94f92c8bd 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -405,6 +405,7 @@ static int check_dot(e2fsck_t ctx,
int status = 0;
int created = 0;
problem_t problem = 0;
+ int ftype = EXT2_FT_DIR;
if (!dirent->inode)
problem = PR_2_MISSING_DOT;
@@ -416,12 +417,14 @@ static int check_dot(e2fsck_t ctx,
(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
if (problem) {
+ if (!ext2fs_has_feature_filetype(ctx->fs->super))
+ ftype = EXT2_FT_UNKNOWN;
if (fix_problem(ctx, problem, pctx)) {
if (rec_len < 12)
rec_len = dirent->rec_len = 12;
dirent->inode = ino;
ext2fs_dirent_set_name_len(dirent, 1);
- ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
+ ext2fs_dirent_set_file_type(dirent, ftype);
dirent->name[0] = '.';
dirent->name[1] = '\0';
status = 1;
@@ -442,12 +445,18 @@ static int check_dot(e2fsck_t ctx,
nextdir = (struct ext2_dir_entry *)
((char *) dirent + 12);
dirent->rec_len = 12;
- (void) ext2fs_set_rec_len(ctx->fs, new_len,
- nextdir);
- nextdir->inode = 0;
- ext2fs_dirent_set_name_len(nextdir, 0);
- ext2fs_dirent_set_file_type(nextdir,
- EXT2_FT_UNKNOWN);
+ /* if the next entry looks like "..", leave it
+ * and let check_dotdot() verify the dirent,
+ * otherwise zap the following entry. */
+ if (strncmp(nextdir->name, "..", 3) != 0) {
+ (void)ext2fs_set_rec_len(ctx->fs,
+ new_len,
+ nextdir);
+ nextdir->inode = 0;
+ ext2fs_dirent_set_name_len(nextdir, 0);
+ ext2fs_dirent_set_file_type(nextdir,
+ ftype);
+ }
status = 1;
}
}
@@ -466,6 +475,7 @@ static int check_dotdot(e2fsck_t ctx,
{
problem_t problem = 0;
unsigned int rec_len;
+ int ftype = EXT2_FT_DIR;
if (!dirent->inode)
problem = PR_2_MISSING_DOT_DOT;
@@ -478,6 +488,8 @@ static int check_dotdot(e2fsck_t ctx,
(void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
if (problem) {
+ if (!ext2fs_has_feature_filetype(ctx->fs->super))
+ ftype = EXT2_FT_UNKNOWN;
if (fix_problem(ctx, problem, pctx)) {
if (rec_len < 12)
dirent->rec_len = 12;
@@ -488,7 +500,7 @@ static int check_dotdot(e2fsck_t ctx,
*/
dirent->inode = EXT2_ROOT_INO;
ext2fs_dirent_set_name_len(dirent, 2);
- ext2fs_dirent_set_file_type(dirent, EXT2_FT_UNKNOWN);
+ ext2fs_dirent_set_file_type(dirent, ftype);
dirent->name[0] = '.';
dirent->name[1] = '.';
dirent->name[2] = '\0';
diff --git a/tests/f_baddotdir/expect.1 b/tests/f_baddotdir/expect.1
index e24aa94ff..a7ca4e495 100644
--- a/tests/f_baddotdir/expect.1
+++ b/tests/f_baddotdir/expect.1
@@ -29,6 +29,9 @@ Fix? yes
Missing '..' in directory inode 16.
Fix? yes
+Directory entry for '.' in ... (19) is big.
+Split? yes
+
Pass 3: Checking directory connectivity
'..' in /a (12) is <The NULL inode> (0), should be / (2).
Fix? yes
@@ -47,13 +50,13 @@ Fix? yes
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Free blocks count wrong for group #0 (70, counted=71).
+Free blocks count wrong for group #0 (69, counted=70).
Fix? yes
-Free blocks count wrong (70, counted=71).
+Free blocks count wrong (69, counted=70).
Fix? yes
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 18/32 files (0.0% non-contiguous), 29/100 blocks
+test_filesys: 19/32 files (0.0% non-contiguous), 30/100 blocks
Exit status is 1
diff --git a/tests/f_baddotdir/expect.2 b/tests/f_baddotdir/expect.2
index 8b3523cb4..0838aa33d 100644
--- a/tests/f_baddotdir/expect.2
+++ b/tests/f_baddotdir/expect.2
@@ -3,5 +3,5 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-test_filesys: 18/32 files (0.0% non-contiguous), 29/100 blocks
+test_filesys: 19/32 files (0.0% non-contiguous), 30/100 blocks
Exit status is 0
diff --git a/tests/f_baddotdir/image.gz b/tests/f_baddotdir/image.gz
index 8ed90c5d6..71df18f21 100644
--- a/tests/f_baddotdir/image.gz
+++ b/tests/f_baddotdir/image.gz
Binary files differ
diff --git a/tests/f_dir_bad_csum/expect.1 b/tests/f_dir_bad_csum/expect.1
index 2c684fe62..ae4b410eb 100644
--- a/tests/f_dir_bad_csum/expect.1
+++ b/tests/f_dir_bad_csum/expect.1
@@ -24,11 +24,9 @@ Salvage? yes
Missing '.' in directory inode 17.
Fix? yes
-Setting filetype for entry '.' in ??? (17) to 2.
Missing '..' in directory inode 17.
Fix? yes
-Setting filetype for entry '..' in ??? (17) to 2.
Entry 'file' in ??? (18) has invalid inode #: 4294967295.
Clear? yes
diff --git a/tests/f_rebuild_csum_rootdir/expect.1 b/tests/f_rebuild_csum_rootdir/expect.1
index bab07e052..91e6027df 100644
--- a/tests/f_rebuild_csum_rootdir/expect.1
+++ b/tests/f_rebuild_csum_rootdir/expect.1
@@ -6,11 +6,9 @@ Salvage? yes
Missing '.' in directory inode 2.
Fix? yes
-Setting filetype for entry '.' in ??? (2) to 2.
Missing '..' in directory inode 2.
Fix? yes
-Setting filetype for entry '..' in ??? (2) to 2.
Pass 3: Checking directory connectivity
'..' in / (2) is <The NULL inode> (0), should be / (2).
Fix? yes
diff --git a/tests/f_resize_inode_meta_bg/expect.1 b/tests/f_resize_inode_meta_bg/expect.1
index c733c18d9..769f71aea 100644
--- a/tests/f_resize_inode_meta_bg/expect.1
+++ b/tests/f_resize_inode_meta_bg/expect.1
@@ -8,11 +8,9 @@ Pass 2: Checking directory structure
First entry '' (inode=348) in directory inode 2 (???) should be '.'
Fix? yes
-Setting filetype for entry '.' in ??? (2) to 2.
Missing '..' in directory inode 2.
Fix? yes
-Setting filetype for entry '..' in ??? (2) to 2.
Directory inode 2, block #0, offset 860: directory corrupted
Salvage? yes
@@ -25,11 +23,9 @@ Salvage? yes
Missing '.' in directory inode 11.
Fix? yes
-Setting filetype for entry '.' in ??? (11) to 2.
Missing '..' in directory inode 11.
Fix? yes
-Setting filetype for entry '..' in ??? (11) to 2.
Directory inode 11, block #1, offset 0: directory corrupted
Salvage? yes
diff --git a/tests/f_uninit_dir/expect.1 b/tests/f_uninit_dir/expect.1
index f0065f155..31870bda5 100644
--- a/tests/f_uninit_dir/expect.1
+++ b/tests/f_uninit_dir/expect.1
@@ -10,11 +10,9 @@ 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
diff --git a/tests/scripts/repair-test b/tests/scripts/repair-test
new file mode 100755
index 000000000..c164e6e5a
--- /dev/null
+++ b/tests/scripts/repair-test
@@ -0,0 +1,9 @@
+#!/bin/sh
+for T in "$*"; do
+ [ -f "$T.failed" -a -d "$T" ] ||
+ { echo "usage: $0 <test_to_repair>"; exit 1; }
+
+ cp $T.1.log $T/expect.1
+ cp $T.2.log $T/expect.2
+ ./test_one $T
+done