[Ocfs2-tools-devel] [PATCH 06/39] libo2cb: Create operation structures for the cluster stack.

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


This allows each stack to handle
begin_group_join/complete_group_join/group_leave as appropriate.
Currently only the classic stack is implemented.

o2cb_init() will now fail if there is a problem reading
/sys/fs/ocfs2/cluster_stack.  If the file does not exist we default to
the classic stack for compatibility with older drivers.

Move the "o2cb" stack operations to static functions, adding them to the
"classic_stack" operation structure.

Finally, have the external APIs merely fill in the default cluster name
and call the stack operations.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 include/o2cb/o2cb.h       |    3 +-
 libo2cb/o2cb_abi.c        |  170 +++++++++++++++++++++++++++++++++++++++++++--
 mount.ocfs2/mount.ocfs2.c |    2 +-
 3 files changed, 166 insertions(+), 9 deletions(-)

diff --git a/include/o2cb/o2cb.h b/include/o2cb/o2cb.h
index 58e1c6e..2abb09e 100644
--- a/include/o2cb/o2cb.h
+++ b/include/o2cb/o2cb.h
@@ -52,6 +52,7 @@
 
 errcode_t o2cb_init(void);
 
+errcode_t o2cb_get_stack_name(const char **name);
 errcode_t o2cb_create_cluster(const char *cluster_name);
 errcode_t o2cb_remove_cluster(const char *cluster_name);
 
@@ -80,7 +81,7 @@ struct o2cb_region_desc {
 /* Expected use case for the region descriptor is to allocate it on
  * the stack and completely fill it before calling
  * begin_group_join().  Regular programs (not mount.ocfs2) should provide
- * a mountpoint that does not begin with a '/'.  Eg, fsck could use ":fsck"
+ * a mountpoint that does not begin with a '/'.  Eg, fsck could use "fsck"
  */
 errcode_t o2cb_begin_group_join(const char *cluster_name,
 				struct o2cb_region_desc *desc);
diff --git a/libo2cb/o2cb_abi.c b/libo2cb/o2cb_abi.c
index 1d80100..3ff490d 100644
--- a/libo2cb/o2cb_abi.c
+++ b/libo2cb/o2cb_abi.c
@@ -46,8 +46,100 @@
 #include "o2cb_abi.h"
 #include "o2cb_crc32.h"
 
+#define CLUSTER_STACK_FILE	"/sys/fs/ocfs2/cluster_stack"
+#define OCFS2_STACK_LABEL_LEN	4
+
+
+struct o2cb_group_ops {
+	errcode_t (*begin_group_join)(const char *cluster_name,
+				      struct o2cb_region_desc *desc);
+	errcode_t (*complete_group_join)(const char *cluster_name,
+					 struct o2cb_region_desc *desc,
+					 int error);
+	errcode_t (*group_leave)(const char *cluster_name,
+				 struct o2cb_region_desc *desc);
+};
+
+struct o2cb_stack {
+	char *s_name;
+	struct o2cb_group_ops *s_ops;
+};
+
+static errcode_t classic_begin_group_join(const char *cluster_name,
+					  struct o2cb_region_desc *desc);
+static errcode_t classic_complete_group_join(const char *cluster_name,
+					     struct o2cb_region_desc *desc,
+					     int error);
+static errcode_t classic_group_leave(const char *cluster_name,
+				     struct o2cb_region_desc *desc);
+static struct o2cb_group_ops classic_ops = {
+	.begin_group_join	= classic_begin_group_join,
+	.complete_group_join	= classic_complete_group_join,
+	.group_leave		= classic_group_leave,
+};
+static struct o2cb_stack classic_stack = {
+	.s_name 	= "o2cb",
+	.s_ops		= &classic_ops,
+};
+
+static struct o2cb_stack *current_stack;
+
 static char *configfs_path;
 
+
+static ssize_t read_stack_file(char *line, size_t count)
+{
+	ssize_t ret = 0;
+	FILE *f;
+
+	f = fopen(CLUSTER_STACK_FILE, "r");
+	if (f) {
+		if (fgets(line, count, f))
+			ret = strlen(line);
+		fclose(f);
+	} else
+		ret = -errno;
+
+	return ret;
+}
+
+static errcode_t determine_stack(void)
+{
+	ssize_t len;
+	char line[100];
+	errcode_t err = O2CB_ET_SERVICE_UNAVAILABLE;
+
+	len = read_stack_file(line, sizeof(line));
+	if (len > 0) {
+		if (line[len - 1] == '\n') {
+			line[len - 1] = '\0';
+			len--;
+		}
+
+		if (len != OCFS2_STACK_LABEL_LEN)
+			err = O2CB_ET_INTERNAL_FAILURE;
+		else if (!strcmp(line, classic_stack.s_name)) {
+			current_stack = &classic_stack;
+			err = 0;
+		}
+	} else if (len == -ENOENT) {
+		current_stack = &classic_stack;
+		err = 0;
+	}
+
+	return err;
+}
+
+errcode_t o2cb_get_stack_name(const char **name)
+{
+	if (!current_stack)
+		return O2CB_ET_SERVICE_UNAVAILABLE;
+
+	*name = current_stack->s_name;
+	return 0;
+}
+
+
 errcode_t o2cb_create_cluster(const char *cluster_name)
 {
 	char path[PATH_MAX];
@@ -493,6 +585,10 @@ errcode_t o2cb_init(void)
 	errcode_t err;
 	char revision_string[16];
 
+	err = determine_stack();
+	if (err)
+		return err;
+
 	err = try_file(O2CB_INTERFACE_REVISION_PATH, &fd);
 	if (err == O2CB_ET_SERVICE_UNAVAILABLE)
 		err = try_file(O2CB_INTERFACE_REVISION_PATH_OLD_SYS, &fd);
@@ -998,8 +1094,8 @@ out:
  * to drop the reference taken during startup, otherwise that
  * reference was dropped automatically at process shutdown so there's
  * no need to drop one here. */
-errcode_t o2cb_group_leave(const char *cluster_name,
-			   struct o2cb_region_desc *desc)
+static errcode_t classic_group_leave(const char *cluster_name,
+				     struct o2cb_region_desc *desc)
 {
 	errcode_t ret, up_ret;
 	int hb_refs;
@@ -1049,8 +1145,8 @@ done:
 	return ret;
 }
 
-errcode_t o2cb_begin_group_join(const char *cluster_name,
-				struct o2cb_region_desc *desc)
+static errcode_t classic_begin_group_join(const char *cluster_name,
+					  struct o2cb_region_desc *desc)
 {
 	errcode_t ret, up_ret;
 	int semid;
@@ -1078,9 +1174,9 @@ up:
 	return ret;
 }
 
-errcode_t o2cb_complete_group_join(const char *cluster_name,
-				   struct o2cb_region_desc *desc,
-				   int error)
+static errcode_t classic_complete_group_join(const char *cluster_name,
+					     struct o2cb_region_desc *desc,
+					     int error)
 {
 	errcode_t ret = 0;
 
@@ -1090,6 +1186,66 @@ errcode_t o2cb_complete_group_join(const char *cluster_name,
 	return ret;
 }
 
+errcode_t o2cb_begin_group_join(const char *cluster_name,
+				struct o2cb_region_desc *desc)
+{
+	errcode_t err;
+	char _fake_cluster_name[NAME_MAX];
+
+	if (!current_stack)
+		return O2CB_ET_SERVICE_UNAVAILABLE;
+
+	if (!cluster_name) {
+		err = _fake_default_cluster(_fake_cluster_name);
+		if (err)
+			return err;
+		cluster_name = _fake_cluster_name;
+	}
+
+	return current_stack->s_ops->begin_group_join(cluster_name, desc);
+}
+
+errcode_t o2cb_complete_group_join(const char *cluster_name,
+				   struct o2cb_region_desc *desc,
+				   int error)
+{
+	errcode_t err;
+	char _fake_cluster_name[NAME_MAX];
+
+	if (!current_stack)
+		return O2CB_ET_SERVICE_UNAVAILABLE;
+
+	if (!cluster_name) {
+		err = _fake_default_cluster(_fake_cluster_name);
+		if (err)
+			return err;
+		cluster_name = _fake_cluster_name;
+	}
+
+	return current_stack->s_ops->complete_group_join(cluster_name,
+							 desc, error);
+}
+
+errcode_t o2cb_group_leave(const char *cluster_name,
+			   struct o2cb_region_desc *desc)
+{
+	errcode_t err;
+	char _fake_cluster_name[NAME_MAX];
+
+	if (!current_stack)
+		return O2CB_ET_SERVICE_UNAVAILABLE;
+
+	if (!cluster_name) {
+		err = _fake_default_cluster(_fake_cluster_name);
+		if (err)
+			return err;
+		cluster_name = _fake_cluster_name;
+	}
+
+	return current_stack->s_ops->group_leave(cluster_name, desc);
+}
+
+
 static inline int is_dots(const char *name)
 {
 	size_t len = strlen(name);
diff --git a/mount.ocfs2/mount.ocfs2.c b/mount.ocfs2/mount.ocfs2.c
index de8e99b..4aa76a9 100644
--- a/mount.ocfs2/mount.ocfs2.c
+++ b/mount.ocfs2/mount.ocfs2.c
@@ -302,7 +302,7 @@ int main(int argc, char **argv)
 	if (clustered) {
 		ret = o2cb_init();
 		if (ret) {
-			com_err(progname, ret, "Cannot initialize cluster");
+			com_err(progname, ret, "while trying initialize cluster");
 			goto bail;
 		}
 
-- 
1.5.3.8




More information about the Ocfs2-tools-devel mailing list