[Ocfs2-tools-devel] [PATCH 09/11] fsck.ocfs2: Fix cluster information in fsck.ocfs2

Joel Becker joel.becker at oracle.com
Tue May 27 18:44:29 PDT 2008


If the running cluster differs from the cluster information written in
the superblock, fsck.ocfs2 will not be able to lock the filesystem.  fsck
can now replace the information in the superblock with the running
configuration, allowing it to proceed with cluster locking.

The actual code to install the cluster configuration is placed in libocfs2
so tha tunefs can use it too.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 fsck.ocfs2/fsck.c     |   70 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/ocfs2/ocfs2.h |    2 +
 libocfs2/dlm.c        |   46 ++++++++++++++++++++++++++++---
 3 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/fsck.ocfs2/fsck.c b/fsck.ocfs2/fsck.c
index 038a6a9..a09530d 100644
--- a/fsck.ocfs2/fsck.c
+++ b/fsck.ocfs2/fsck.c
@@ -534,6 +534,65 @@ bail:
 	return ret;
 }
 
+static errcode_t recover_cluster_info(o2fsck_state *ost)
+{
+	errcode_t ret;
+	struct o2cb_cluster_desc disk = {NULL, NULL}, running = {NULL, NULL};
+
+	ret = o2cb_running_cluster_desc(&running);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_fill_cluster_desc(ost->ost_fs, &disk);
+	if (ret)
+		goto bail;
+
+	/*
+	 * If the disk matches the running cluster, there is nothing we
+	 * can fix.
+	 */
+	if ((!running.c_stack && !disk.c_stack) ||
+	    (running.c_stack && running.c_cluster &&
+	     disk.c_stack && disk.c_cluster &&
+	     !strcmp(running.c_stack, disk.c_stack) &&
+	     !strcmp(running.c_cluster, disk.c_cluster)))
+		goto bail;
+
+	/* recover the backup information to superblock. */
+	if (prompt(ost, PN, PR_RECOVER_CLUSTER_INFO,
+		   "The running cluster is using the %s stack%s%s, but "
+		   "the filesystem is configured for the %s stack%s%s.  "
+		   "Thus, %s cannot determine whether the filesystem is in "
+		   "use.  %s can reconfigure the filesystem to use the "
+		   "currently running cluster configuration.  DANGER: "
+		   "YOU MUST BE ABSOLUTELY SURE THAT NO OTHER NODE IS "
+		   "USING THIS FILESYSTEM BEFORE MODIFYING ITS CLUSTER "
+		   "CONFIGURATION.  Recover cluster configuration "
+		   "information the running cluster?",
+		   running.c_stack ? running.c_stack : "classic o2cb",
+		   running.c_stack ? " with the cluster name " : "",
+		   running.c_stack ? running.c_cluster : "",
+		   disk.c_stack ? disk.c_stack : "classic o2cb",
+		   disk.c_stack ? " with the cluster name " : "",
+		   disk.c_stack ? disk.c_cluster : "", whoami, whoami)) {
+		ret = ocfs2_set_cluster_desc(ost->ost_fs, &running);
+		if (ret)
+			goto bail;
+	}
+
+	/* no matter whether the user recover the superblock or not above,
+	 * we should return 0 in case the superblock can be opened
+	 * without the recovery.
+	 */
+	ret = 0;
+
+bail:
+	o2cb_free_cluster_desc(&running);
+	o2cb_free_cluster_desc(&disk);
+
+	return ret;
+}
+
 int main(int argc, char **argv)
 {
 	char *filename;
@@ -689,6 +748,17 @@ int main(int argc, char **argv)
 
 		block_signals(SIG_BLOCK);
 		ret = ocfs2_initialize_dlm(ost->ost_fs, whoami);
+		if (ret == O2CB_ET_INVALID_STACK_NAME) {
+			block_signals(SIG_UNBLOCK);
+			ret = recover_cluster_info(ost);
+			if (ret) {
+				com_err(whoami, ret,
+					"while recovering cluster information");
+				goto close;
+			}
+			block_signals(SIG_BLOCK);
+			ret = ocfs2_initialize_dlm(ost->ost_fs, whoami);
+		}
 		if (ret) {
 			block_signals(SIG_UNBLOCK);
 			com_err(whoami, ret, "while initializing the DLM");
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 1cb1b9a..365b52f 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -517,6 +517,8 @@ errcode_t ocfs2_file_write(ocfs2_cached_inode *ci, void *buf, uint32_t count,
 
 errcode_t ocfs2_fill_cluster_desc(ocfs2_filesys *fs,
 				  struct o2cb_cluster_desc *desc);
+errcode_t ocfs2_set_cluster_desc(ocfs2_filesys *fs,
+				 struct o2cb_cluster_desc *desc);
 errcode_t ocfs2_fill_heartbeat_desc(ocfs2_filesys *fs,
 				    struct o2cb_region_desc *desc);
 
diff --git a/libocfs2/dlm.c b/libocfs2/dlm.c
index 1d1b30f..c04ab8d 100644
--- a/libocfs2/dlm.c
+++ b/libocfs2/dlm.c
@@ -105,8 +105,9 @@ errcode_t ocfs2_fill_cluster_desc(ocfs2_filesys *fs,
 				  struct o2cb_cluster_desc *desc)
 {
 	errcode_t ret = 0;
+	struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super);
 
-	if (!ocfs2_userspace_stack(OCFS2_RAW_SB(fs->fs_super))) {
+	if (!ocfs2_userspace_stack(sb)) {
 		desc->c_stack = NULL;
 		desc->c_cluster = NULL;
 		return 0;
@@ -122,16 +123,51 @@ errcode_t ocfs2_fill_cluster_desc(ocfs2_filesys *fs,
 		return ret;
 	}
 
-	memcpy(desc->c_stack,
-	       OCFS2_RAW_SB(fs->fs_super)->s_cluster_info.ci_stack,
+	memcpy(desc->c_stack, sb->s_cluster_info.ci_stack,
 	       OCFS2_STACK_LABEL_LEN);
-	memcpy(desc->c_cluster,
-	       OCFS2_RAW_SB(fs->fs_super)->s_cluster_info.ci_cluster,
+	memcpy(desc->c_cluster, sb->s_cluster_info.ci_cluster,
 	       OCFS2_CLUSTER_NAME_LEN);
 
 	return 0;
 }
 
+errcode_t ocfs2_set_cluster_desc(ocfs2_filesys *fs,
+				 struct o2cb_cluster_desc *desc)
+{
+	errcode_t ret;
+	struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super);
+
+	if (desc->c_stack) {
+		if (!desc->c_stack[0] || !desc->c_cluster ||
+		    !desc->c_cluster[0]) {
+			ret = OCFS2_ET_INVALID_ARGUMENT;
+			goto out;
+		}
+
+		if (!ocfs2_uses_extended_slot_map(sb)) {
+			sb->s_feature_incompat |=
+				OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP;
+			ret = ocfs2_format_slot_map(fs);
+			if (ret)
+				goto out;
+		}
+		sb->s_feature_incompat |=
+			OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK;
+		memcpy(sb->s_cluster_info.ci_stack, desc->c_stack,
+		       OCFS2_STACK_LABEL_LEN);
+		memcpy(sb->s_cluster_info.ci_cluster, desc->c_cluster,
+		       OCFS2_CLUSTER_NAME_LEN);
+	} else {
+		sb->s_feature_incompat &=
+			~OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK;
+	}
+
+	ret = ocfs2_write_super(fs);
+
+out:
+	return ret;
+}
+
 errcode_t ocfs2_initialize_dlm(ocfs2_filesys *fs, const char *service)
 {
 	struct o2dlm_ctxt *dlm_ctxt = NULL;
-- 
1.5.4.5




More information about the Ocfs2-tools-devel mailing list