ocfs2-tools/0021-fsck.ocfs2-verify-dirent-dx-entry-linkages.patch

93 lines
2.9 KiB
Diff

From 4c1cf61779ee71c828134d956f5779e272a3195e Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Fri, 23 Apr 2010 23:09:05 -0700
Subject: [PATCH 21/30] fsck.ocfs2: verify dirent -> dx entry linkages
During pass2 we can trivially do a lookup on dirents while walking the
directory tree. This will help us make sure that an index entry exists for
each dirent. If an entry is not found, the users is prompted and the parent
directory will be marked for an index rebuild.
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
---
fsck.ocfs2/fsck.ocfs2.checks.8.in | 7 +++++++
fsck.ocfs2/pass2.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 0 deletions(-)
diff --git a/fsck.ocfs2/fsck.ocfs2.checks.8.in b/fsck.ocfs2/fsck.ocfs2.checks.8.in
index 5cda023..cfbb12e 100644
--- a/fsck.ocfs2/fsck.ocfs2.checks.8.in
+++ b/fsck.ocfs2/fsck.ocfs2.checks.8.in
@@ -1061,6 +1061,13 @@ file system.
Answering yes will truncate the invalid index.
+.SS "DX_LOOKUP_FAILED"
+A directory entry is missing an entry in the directory index. Not
+found in directory index. The missing index entry will cause lookups
+on this name to fail.
+
+Answering yes will rebuild the directory index, restoring the missing entry.
+
.SH "SEE ALSO"
.BR fsck.ocfs2(8)
diff --git a/fsck.ocfs2/pass2.c b/fsck.ocfs2/pass2.c
index b999761..e03bd4e 100644
--- a/fsck.ocfs2/pass2.c
+++ b/fsck.ocfs2/pass2.c
@@ -648,6 +648,39 @@ out:
return ret;
}
+static errcode_t fix_dirent_index(o2fsck_dirblock_entry *dbe,
+ struct dirblock_data *dd,
+ struct ocfs2_dir_entry *dirent,
+ unsigned int *flags)
+{
+ errcode_t ret = 0;
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf;
+ uint64_t ino;
+
+ if (!ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super)))
+ goto out;
+
+ if (di->i_dyn_features & OCFS2_INDEXED_DIR_FL) {
+ ret = ocfs2_lookup(dd->fs, dbe->e_ino, dirent->name,
+ dirent->name_len, NULL, &ino);
+ if (ret) {
+ if (ret != OCFS2_ET_FILE_NOT_FOUND)
+ goto out;
+ ret = 0;
+
+ if (prompt(dd->ost, PY, PR_DX_LOOKUP_FAILED,
+ "Directory inode %"PRIu64" is missing "
+ "an index entry for child inode %"PRIu64
+ "\n. Repair this by rebuilding the "
+ "directory index?", dbe->e_ino, ino))
+ *flags |= OCFS2_DIRENT_CHANGED;
+ goto out;
+ }
+ }
+out:
+ return ret;
+}
+
static int corrupt_dirent_lengths(struct ocfs2_dir_entry *dirent, int left)
{
if ((dirent->rec_len >= OCFS2_DIR_REC_LEN(1)) &&
@@ -805,6 +838,10 @@ static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
if (dirent->inode == 0)
goto next;
+ ret = fix_dirent_index(dbe, dd, dirent, &ret_flags);
+ if (ret)
+ goto out;
+
verbosef("dirent %.*s refs ino %"PRIu64"\n", dirent->name_len,
dirent->name, (uint64_t)dirent->inode);
o2fsck_icount_delta(dd->ost->ost_icount_refs, dirent->inode, 1);
--
1.7.0.2