[Ocfs2-tools-devel] [PATCH 5/6] fsck.ocfs2: Add replay orphan dir in slot recovery.v4

Tao Ma tao.ma at oracle.com
Tue Oct 7 00:29:03 PDT 2008


In o2fsck_pass4, we replay orphan dir. Now in slot recovery, we also
want to replay it, so export it from pass4. There is only one diffrence.
In slot recovery, we should exit the replay process if we meet with any
error, while in pass4, we should go on the process.
We also need to clear the link count of these dirs in the end during
slot recovery.

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 fsck.ocfs2/include/fsck.h          |    1 +
 fsck.ocfs2/include/pass4.h         |    1 +
 fsck.ocfs2/include/slot_recovery.h |    1 +
 fsck.ocfs2/pass4.c                 |   68 +++++++++++++++++++++++++----------
 fsck.ocfs2/slot_recovery.c         |   36 +++++++++++++++++++
 5 files changed, 87 insertions(+), 20 deletions(-)

diff --git a/fsck.ocfs2/include/fsck.h b/fsck.ocfs2/include/fsck.h
index eab7197..28a3264 100644
--- a/fsck.ocfs2/include/fsck.h
+++ b/fsck.ocfs2/include/fsck.h
@@ -72,6 +72,7 @@ typedef struct _o2fsck_state {
  					     * that still indicated mounted */
 			ost_fix_fs_gen:1,
 			ost_has_journal_dirty:1;
+	errcode_t ost_err;
 } o2fsck_state;
 
 errcode_t o2fsck_state_reinit(ocfs2_filesys *fs, o2fsck_state *ost);
diff --git a/fsck.ocfs2/include/pass4.h b/fsck.ocfs2/include/pass4.h
index b240182..a37d02f 100644
--- a/fsck.ocfs2/include/pass4.h
+++ b/fsck.ocfs2/include/pass4.h
@@ -26,6 +26,7 @@
 
 #include "fsck.h"
 
+errcode_t replay_orphan_dir(o2fsck_state *ost, int slot_recovery);
 errcode_t o2fsck_pass4(o2fsck_state *ost);
 
 #endif /* __O2FSCK_PASS4_H__ */
diff --git a/fsck.ocfs2/include/slot_recovery.h b/fsck.ocfs2/include/slot_recovery.h
index dab34ca..14353a7 100644
--- a/fsck.ocfs2/include/slot_recovery.h
+++ b/fsck.ocfs2/include/slot_recovery.h
@@ -24,6 +24,7 @@
 
 errcode_t o2fsck_replay_truncate_logs(ocfs2_filesys *fs);
 errcode_t o2fsck_replay_local_allocs(ocfs2_filesys *fs);
+errcode_t o2fsck_replay_orphan_dirs(o2fsck_state *ost);
 
 #endif /* __O2FSCK_SLOT_RECOVERY_H__ */
 
diff --git a/fsck.ocfs2/pass4.c b/fsck.ocfs2/pass4.c
index 0f4cf22..af33185 100644
--- a/fsck.ocfs2/pass4.c
+++ b/fsck.ocfs2/pass4.c
@@ -110,7 +110,7 @@ static int replay_orphan_iterate(struct ocfs2_dir_entry *dirent,
 	struct orphan_dir_ctxt *ctxt = priv_data;
 	o2fsck_state *ost = ctxt->ost;
 	int ret_flags = 0;
-	errcode_t ret;
+	errcode_t ret = 0;
 
 	if (!(ost->ost_fs->fs_flags & OCFS2_FLAG_RW)) {
 		printf("** Skipping orphan dir replay because -n was "
@@ -119,11 +119,13 @@ static int replay_orphan_iterate(struct ocfs2_dir_entry *dirent,
 		goto out;
 	}
 
-	if (!prompt(ost, PY, PR_INODE_ORPHANED,
-		   "Inode %"PRIu64" was found in the orphan directory. "
-		   "Delete its contents and unlink it?",
-		   (uint64_t)dirent->inode)) {
-		goto out;
+	/* Only ask for confirmation in force check. */
+	if (ost->ost_force) {
+		if (!prompt(ost, PY, PR_INODE_ORPHANED,
+			   "Inode %"PRIu64" was found in the orphan directory. "
+			   "Delete its contents and unlink it?",
+			   (uint64_t)dirent->inode))
+			goto out;
 	}
 
 	ret = ocfs2_truncate(ost->ost_fs, dirent->inode, 0);
@@ -142,23 +144,35 @@ static int replay_orphan_iterate(struct ocfs2_dir_entry *dirent,
 		goto out;
 	}
 
-	/* this matches a special case in o2fsck_verify_inode_fields() where
-	 * orphan dir members are recorded as having 1 link count, even
-	 * though they have 0 on disk */
-	o2fsck_icount_delta(ost->ost_icount_in_inodes, dirent->inode, -1);
-
-	/* dirs have this dirent ref and their '.' dirent and we also need to
-	 * handle '..' dirent for their parents. */
-	if (dirent->file_type == OCFS2_FT_DIR) {
-		o2fsck_icount_delta(ost->ost_icount_refs, dirent->inode, -2);
-		o2fsck_icount_delta(ost->ost_icount_refs, ctxt->orphan_dir, -1);
-	} else
-		o2fsck_icount_delta(ost->ost_icount_refs, dirent->inode, -1);
+	/* Only calculate icount in force check. */
+	if (ost->ost_force) {
+		/*
+		 * this matches a special case in o2fsck_verify_inode_fields()
+		 * where orphan dir members are recorded as having 1 link count,
+		 * even though they have 0 on disk
+		 */
+		o2fsck_icount_delta(ost->ost_icount_in_inodes,
+				    dirent->inode, -1);
+
+		/*
+		 * dirs have this dirent ref and their '.' dirent and we also
+		 * need to handle '..' dirent for their parents.
+		 */
+		if (dirent->file_type == OCFS2_FT_DIR) {
+			o2fsck_icount_delta(ost->ost_icount_refs,
+					    dirent->inode, -2);
+			o2fsck_icount_delta(ost->ost_icount_refs,
+					    ctxt->orphan_dir, -1);
+		} else
+			o2fsck_icount_delta(ost->ost_icount_refs,
+					    dirent->inode, -1);
+	}
 
 	dirent->inode = 0;
 	ret_flags |= OCFS2_DIRENT_CHANGED;
 
 out:
+	ost->ost_err = ret;
 	return ret_flags;
 }
 
@@ -194,7 +208,13 @@ bail:
 	return ret;
 }
 
-static errcode_t replay_orphan_dir(o2fsck_state *ost)
+/*
+ * replay_orphan_dir could happen in 2 places and we handle it diffrently.
+ * 1. In slot recovery, we will return any error which lead to a force check.
+ * 2. in o2fsck_pass4, all other errors should be fixed in pass0,1,2 and 3, so
+ *    we try to fix some errors by ourselves.
+ */
+errcode_t replay_orphan_dir(o2fsck_state *ost, int slot_recovery)
 {
 	errcode_t ret = OCFS2_ET_CORRUPT_SUPERBLOCK;
 	char name[PATH_MAX];
@@ -216,6 +236,9 @@ static errcode_t replay_orphan_dir(o2fsck_state *ost)
 		ret = ocfs2_lookup(ost->ost_fs, ost->ost_fs->fs_sysdir_blkno,
 				   name, bytes, NULL, &ino);
 		if (ret) {
+			if (slot_recovery)
+				goto out;
+
 			if (ret != OCFS2_ET_FILE_NOT_FOUND)
 				goto out;
 
@@ -236,9 +259,14 @@ static errcode_t replay_orphan_dir(o2fsck_state *ost)
 		}
 
 		ctxt.orphan_dir = ino;
+		ost->ost_err = 0;
 		ret = ocfs2_dir_iterate(ost->ost_fs, ino,
 					OCFS2_DIRENT_FLAG_EXCLUDE_DOTS, NULL,
 					replay_orphan_iterate, &ctxt);
+		if (!ret)
+			ret = ost->ost_err;
+		if (ret && slot_recovery)
+			break;
 	}
 
 out:
@@ -285,7 +313,7 @@ errcode_t o2fsck_pass4(o2fsck_state *ost)
 
 	printf("Pass 4a: checking for orphaned inodes\n");
 
-	ret = replay_orphan_dir(ost);
+	ret = replay_orphan_dir(ost, 0);
 	if (ret) {
 		com_err(whoami, ret, "while trying to replay the orphan "
 			"directory");
diff --git a/fsck.ocfs2/slot_recovery.c b/fsck.ocfs2/slot_recovery.c
index c4ae166..784602c 100644
--- a/fsck.ocfs2/slot_recovery.c
+++ b/fsck.ocfs2/slot_recovery.c
@@ -20,6 +20,7 @@
 #include <ocfs2/bitops.h>
 #include "util.h"
 #include "slot_recovery.h"
+#include "pass4.h"
 
 static errcode_t ocfs2_clear_truncate_log(ocfs2_filesys *fs,
 					  struct ocfs2_dinode *di,
@@ -167,3 +168,38 @@ errcode_t o2fsck_replay_local_allocs(ocfs2_filesys *fs)
 					LOCAL_ALLOC_SYSTEM_INODE,
 					ocfs2_clear_local_alloc);
 }
+
+static errcode_t ocfs2_clear_link_count(ocfs2_filesys *fs,
+					struct ocfs2_dinode *di,
+					int slot)
+{
+	errcode_t ret = 0;
+
+	if (!(di->i_flags & OCFS2_VALID_FL) ||
+	    !(di->i_flags & OCFS2_SYSTEM_FL) ||
+	    !S_ISDIR(di->i_mode))
+		return OCFS2_ET_INVALID_ARGUMENT;
+
+	if (di->i_links_count == 2)
+		goto bail;
+
+	di->i_links_count = 2;
+	ret = ocfs2_write_inode(fs, di->i_blkno, (char *)di);
+	if (!ret)
+		printf("Slot %d's orphan dir replayed successfully\n", slot);
+
+bail:
+	return ret;
+}
+
+errcode_t o2fsck_replay_orphan_dirs(o2fsck_state *ost)
+{
+	errcode_t ret;
+
+	ret = replay_orphan_dir(ost, 1);
+	if (ret)
+		return ret;
+
+	return handle_slots_system_file(ost->ost_fs, ORPHAN_DIR_SYSTEM_INODE,
+					ocfs2_clear_link_count);
+}
-- 
1.5.4.GIT




More information about the Ocfs2-tools-devel mailing list