[Ocfs2-tools-devel] [PATCH 28/39] mkfs.ocfs2: Add the cluster stack options.

Joel Becker joel.becker at oracle.com
Fri Mar 14 16:52:51 PDT 2008


This code detects the running cluster stack and cluster name as well as
accepting them from the user.  It checks for conflicts or missing
information.  It then writes the out to the disk, setting the
USERSPACE_STACK feature flag when appropriate.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 mkfs.ocfs2/check.c |  204 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 mkfs.ocfs2/mkfs.c  |   57 +++++++++++++++
 mkfs.ocfs2/mkfs.h  |    3 +
 3 files changed, 264 insertions(+), 0 deletions(-)

diff --git a/mkfs.ocfs2/check.c b/mkfs.ocfs2/check.c
index bd4d7ac..901132c 100644
--- a/mkfs.ocfs2/check.c
+++ b/mkfs.ocfs2/check.c
@@ -27,12 +27,216 @@
 
 #define WHOAMI "mkfs.ocfs2"
 
+/* For ocfs2_fill_cluster_information().  Errors are to be ignored */
+static void cluster_fill(char **stack_name, char **cluster_name)
+{
+	errcode_t err;
+	char **clusters = NULL;
+	const char *name = NULL;
+
+	err = o2cb_init();
+	if (err)
+		return;
+
+	err = o2cb_get_stack_name(&name);
+	if (err)
+		return;
+
+	*stack_name = strdup(name);
+
+	err = o2cb_list_clusters(&clusters);
+	if (err)
+		return;
+
+	/* The first cluster is the default cluster */
+	if (clusters[0])
+		*cluster_name = strdup(clusters[0]);
+
+	o2cb_free_cluster_list(clusters);
+}
+
+/* For ocfs2_fill_cluster_information().  Errors are to be ignored */
+static void disk_fill(const char *device, char **stack_name,
+		      char **cluster_name)
+{
+	errcode_t err;
+	ocfs2_filesys *fs = NULL;
+	struct o2cb_cluster_desc desc;
+
+	err = ocfs2_open(device, OCFS2_FLAG_RO, 0, 0, &fs);
+	if (err)
+		return;
+
+	if (!ocfs2_userspace_stack(OCFS2_RAW_SB(fs->fs_super))) {
+		*stack_name = strdup("o2cb");
+		goto close;
+	}
+
+	err = ocfs2_fill_cluster_desc(fs, &desc);
+	if (err)
+		goto close;
+
+	*stack_name = strdup(desc.c_stack);
+	*cluster_name = strdup(desc.c_cluster);
+
+close:
+	ocfs2_close(fs);
+}
+
+static int pick_one(State *s, const char *what_is_it,
+		    const char *user_value, const char *o2cb_value,
+		    const char *disk_value, char **ret_value)
+{
+	int rc = -1;
+
+	/*
+	 * First, compare o2cb and disk values.  If we get past this
+	 * block (via match or override), the o2cb value takes precedence.
+	 */
+	if (disk_value) {
+		if (o2cb_value) {
+			if (strcmp(o2cb_value, disk_value)) {
+				fprintf(stderr,
+					"%s is configured to use %s \"%s\", but \"%s\" is currently running.\n"
+					"%s will not be able to determine if the filesystem is in use.\n",
+					s->device_name, what_is_it,
+					disk_value, o2cb_value,
+					s->progname);
+				if (!s->force) {
+					fprintf(stderr,
+						"To skip this check, use --force or -F\n");
+					goto out;
+				}
+				fprintf(stdout,
+					"Overwrite of disk information forced\n");
+			}
+		}
+	}
+
+	if (user_value) {
+		if (o2cb_value) {
+			if (strcmp(o2cb_value, user_value)) {
+				fprintf(stderr, "%s \"%s\" was requested, but \"%s\" is running.\n",
+				what_is_it, user_value, o2cb_value);
+				if (!s->force) {
+					fprintf(stderr,
+						"To skip this check, use --force or -F\n");
+					goto out;
+				}
+				fprintf(stdout, "%s forced\n", what_is_it);
+			}
+		} else if (disk_value) {
+			if (strcmp(disk_value, user_value)) {
+				fprintf(stderr, "%s \"%s\" was requested, but %s is configured for \"%s\".\n",
+					what_is_it, user_value,
+					s->device_name, disk_value);
+				if (!s->force) {
+					fprintf(stderr,
+						"To skip this check, use --force or -F\n");
+					goto out;
+				}
+				fprintf(stderr, "%s forced\n", what_is_it);
+			}
+		}
+		*ret_value = strdup(user_value);
+	} else if (o2cb_value)
+		*ret_value = strdup(o2cb_value);
+	else if (disk_value)
+		*ret_value = strdup(disk_value);
+
+	rc = 0;
+
+out:
+	return rc;;
+}
+
+/*
+ * Try to connect to the cluster and look at the disk to fill in default
+ * cluster values.  If we can't connect, that's OK for now.  The only errors
+ * are when values are missing or conflict with option arguments.
+ */
+int ocfs2_fill_cluster_information(State *s)
+{
+	int rc = -1;
+	char *user_cluster_name = NULL;
+	char *user_stack_name = NULL;
+	char *o2cb_cluster_name = NULL;
+	char *o2cb_stack_name = NULL;
+	char *disk_cluster_name = NULL;
+	char *disk_stack_name = NULL;
+
+	if (s->mount == MOUNT_LOCAL)
+		return 0;
+
+	cluster_fill(&o2cb_stack_name, &o2cb_cluster_name);
+	disk_fill(s->device_name, &disk_stack_name, &disk_cluster_name);
+	user_stack_name = s->cluster_stack;
+	user_cluster_name = s->cluster_name;
+
+	if (pick_one(s, "cluster stack", user_stack_name, o2cb_stack_name,
+		     disk_stack_name, &s->cluster_stack))
+		return -1;
+
+	if (pick_one(s, "cluster name", user_cluster_name,
+		     o2cb_cluster_name, disk_cluster_name,
+		     &s->cluster_name))
+		return -1;
+
+	if (s->cluster_stack) {
+		if (!strcmp(s->cluster_stack, "o2cb")) {
+			/*
+			 * We've already checked for conflicts above.  Now
+			 * clear out the stack so that fill_super knows
+			 * it's a classic filesystem.
+			 */
+			free(s->cluster_stack);
+			s->cluster_stack = NULL;
+		} else if (!s->cluster_name) {
+			fprintf(stderr,
+				"Cluster name required for stack \"%s\".\n",
+				s->cluster_stack);
+			goto out;
+		}
+	}
+	if (!s->cluster_stack && s->cluster_name) {
+		/* The classic stack doesn't write a name */
+		free(s->cluster_name);
+		s->cluster_name = NULL;
+	}
+	if (s->cluster_stack)
+		fprintf(stdout, "Cluster stack: %s\nCluster name: %s\n",
+			s->cluster_stack, s->cluster_name);
+	else
+		fprintf(stdout, "Cluster stack: classic o2cb\n");
+
+	rc = 0;
+
+out:
+	if (user_stack_name)
+		free(user_stack_name);
+	if (user_cluster_name)
+		free(user_cluster_name);
+	if (o2cb_stack_name)
+		free(o2cb_stack_name);
+	if (o2cb_cluster_name)
+		free(o2cb_cluster_name);
+	if (disk_stack_name)
+		free(disk_stack_name);
+	if (disk_cluster_name)
+		free(disk_cluster_name);
+
+	return rc;
+}
+
 int ocfs2_check_volume(State *s)
 {
 	ocfs2_filesys *fs = NULL;
 	errcode_t ret;
 	int mount_flags;
 
+	if (ocfs2_fill_cluster_information(s))
+		return -1;
+
 	ret = ocfs2_check_if_mounted(s->device_name, &mount_flags);
 	if (ret) {
 		com_err(s->progname, ret,
diff --git a/mkfs.ocfs2/mkfs.c b/mkfs.ocfs2/mkfs.c
index 09b0723..f43daf2 100644
--- a/mkfs.ocfs2/mkfs.c
+++ b/mkfs.ocfs2/mkfs.c
@@ -118,6 +118,8 @@ enum {
 	BACKUP_SUPER_OPTION = CHAR_MAX + 1,
 	FEATURE_LEVEL,
 	FEATURES_OPTION,
+	CLUSTER_STACK_OPTION,
+	CLUSTER_NAME_OPTION,
 };
 
 static uint64_t align_bytes_to_clusters_ceil(State *s,
@@ -509,6 +511,8 @@ get_state(int argc, char **argv)
 	unsigned int blocksize = 0;
 	unsigned int cluster_size = 0;
 	char *vol_label = NULL;
+	char *stack_name = NULL;
+	char *cluster_name = NULL;
 	unsigned int initial_slots = 0;
 	char *dummy;
 	State *s;
@@ -540,6 +544,8 @@ get_state(int argc, char **argv)
 		{ "no-backup-super", 0, 0, BACKUP_SUPER_OPTION },
 		{ "fs-feature-level=", 1, 0, FEATURE_LEVEL },
 		{ "fs-features=", 1, 0, FEATURES_OPTION },
+		{ "cluster-stack=", 1, 0, CLUSTER_STACK_OPTION },
+		{ "cluster-name=", 1, 0, CLUSTER_NAME_OPTION },
 		{ 0, 0, 0, 0}
 	};
 
@@ -694,6 +700,38 @@ get_state(int argc, char **argv)
 			}
 			break;
 
+		case CLUSTER_STACK_OPTION:
+			if (!optarg || !strlen(optarg)) {
+				com_err(progname, 0,
+					"Option --cluster-stack requires an argument");
+				exit(1);
+			}
+			if (strlen(optarg) != OCFS2_STACK_LABEL_LEN) {
+				com_err(progname, 0,
+					"Invalid argument to --cluster-stack");
+				exit(1);
+			}
+			if (stack_name)
+				free(stack_name);
+			stack_name = strdup(optarg);
+			break;
+
+		case CLUSTER_NAME_OPTION:
+			if (!optarg || !strlen(optarg)) {
+				com_err(progname, 0,
+					"Option --cluster-name requires an argument");
+				exit(1);
+			}
+			if (strlen(optarg) > OCFS2_CLUSTER_NAME_LEN) {
+				com_err(progname, 0,
+					"Cluster name is too long");
+				exit(1);
+			}
+			if (cluster_name)
+				free(cluster_name);
+			cluster_name = strdup(optarg);
+			break;
+
 		default:
 			usage(progname);
 			break;
@@ -781,6 +819,16 @@ get_state(int argc, char **argv)
 	if (mount != -1)
 		s->mount = mount;
 
+	if ((stack_name || cluster_name) && (s->mount == MOUNT_LOCAL)) {
+		com_err(progname, 0,
+			"Local mount is incompatible with specifying a cluster stack");
+		exit(1);
+	}
+	if (stack_name)
+		s->cluster_stack = stack_name;
+	if (cluster_name)
+		s->cluster_name = cluster_name;
+
 	if (no_backup_super != -1)
 		s->no_backup_super = no_backup_super;
 
@@ -1807,6 +1855,15 @@ format_superblock(State *s, SystemFileDiskRecord *rec,
 	if (s->mount == MOUNT_LOCAL)
 		s->feature_flags.incompat |=
 					 OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT;
+
+	if (s->cluster_stack) {
+		s->feature_flags.incompat |= OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK;
+		memcpy(di->id2.i_super.s_cluster_info.ci_stack,
+		       s->cluster_stack, OCFS2_STACK_LABEL_LEN);
+		memcpy(di->id2.i_super.s_cluster_info.ci_cluster,
+		       s->cluster_name, OCFS2_CLUSTER_NAME_LEN);
+	}
+
 	/*
 	 * we clear the "backup_sb" here since it should be written by
 	 * format_backup_super, not by us. And we have already set the
diff --git a/mkfs.ocfs2/mkfs.h b/mkfs.ocfs2/mkfs.h
index 2e7db4b..6159cfb 100644
--- a/mkfs.ocfs2/mkfs.h
+++ b/mkfs.ocfs2/mkfs.h
@@ -222,6 +222,8 @@ struct _State {
 	char *vol_label;
 	char *device_name;
 	unsigned char *uuid;
+	char *cluster_stack;
+	char *cluster_name;
 	uint32_t vol_generation;
 
 	int fd;
@@ -241,4 +243,5 @@ struct _State {
 	enum ocfs2_fs_types fs_type;
 };
 
+int ocfs2_fill_cluster_information(State *s);
 int ocfs2_check_volume(State *s);
-- 
1.5.3.8




More information about the Ocfs2-tools-devel mailing list