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, to avoid extra problems
later can easily be avoided.
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.
Change-Id: Ia5e579bcf31a9d9ee260d5640de6dbdb60514823
Signed-off-by: Andreas dilger <adilger@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/43858
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Artem Blagodarenko <artem.blagodarenko@hpe.com>
int created = 0;
problem_t problem = 0;
int dir_data_error;
+ 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 && dir_data_error)
+ 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 dir_data_error;
+ 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 && dir_data_error)
+ if (rec_len < 12)
dirent->rec_len = 12;
/*
* Note: we don't have the parent inode just
*/
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