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>
int status = 0;
int created = 0;
problem_t problem = 0;
+ int ftype = EXT2_FT_DIR;
if (!dirent->inode)
problem = PR_2_MISSING_DOT;
(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;
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;
}
}
{
problem_t problem = 0;
unsigned int rec_len;
+ int ftype = EXT2_FT_DIR;
if (!dirent->inode)
problem = PR_2_MISSING_DOT_DOT;
(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;
*/
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';
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
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
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
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
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
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
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
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
--- /dev/null
+#!/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