[Ocfs2-tools-devel] [PATCH 24/39] libo2cb: Provide the controld group operations.

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


For userspace cluster stacks, the user group operations will connect to
a running control daemon and ask for joins.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 include/o2cb/o2cb.h |    2 +-
 libo2cb/o2cb_abi.c  |  319 ++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 305 insertions(+), 16 deletions(-)

diff --git a/include/o2cb/o2cb.h b/include/o2cb/o2cb.h
index 2abb09e..2d94813 100644
--- a/include/o2cb/o2cb.h
+++ b/include/o2cb/o2cb.h
@@ -87,7 +87,7 @@ errcode_t o2cb_begin_group_join(const char *cluster_name,
 				struct o2cb_region_desc *desc);
 errcode_t o2cb_complete_group_join(const char *cluster_name,
 				   struct o2cb_region_desc *desc,
-				   int error);
+				   int result);
 errcode_t o2cb_group_leave(const char *cluster_name,
 			   struct o2cb_region_desc *desc);
 
diff --git a/libo2cb/o2cb_abi.c b/libo2cb/o2cb_abi.c
index 3ff490d..0851635 100644
--- a/libo2cb/o2cb_abi.c
+++ b/libo2cb/o2cb_abi.c
@@ -5,21 +5,16 @@
  *
  * Kernel<->User ABI for modifying cluster configuration.
  *
- * Copyright (C) 2004 Oracle.  All rights reserved.
+ * Copyright (C) 2004,2007 Oracle.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
- * License, version 2,  as published by the Free Software Foundation.
+ * License, version 2, as published by the Free Software Foundation.
  * 
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
  */
 
 #define _XOPEN_SOURCE 600  /* Triggers XOPEN2K in features.h */
@@ -43,6 +38,7 @@
 #include <linux/types.h>
 
 #include "o2cb/o2cb.h"
+#include "o2cb/o2cb_client_proto.h"
 #include "o2cb_abi.h"
 #include "o2cb_crc32.h"
 
@@ -55,13 +51,13 @@ struct o2cb_group_ops {
 				      struct o2cb_region_desc *desc);
 	errcode_t (*complete_group_join)(const char *cluster_name,
 					 struct o2cb_region_desc *desc,
-					 int error);
+					 int result);
 	errcode_t (*group_leave)(const char *cluster_name,
 				 struct o2cb_region_desc *desc);
 };
 
 struct o2cb_stack {
-	char *s_name;
+	char s_name[OCFS2_STACK_LABEL_LEN + 1];
 	struct o2cb_group_ops *s_ops;
 };
 
@@ -69,7 +65,7 @@ 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);
+					     int result);
 static errcode_t classic_group_leave(const char *cluster_name,
 				     struct o2cb_region_desc *desc);
 static struct o2cb_group_ops classic_ops = {
@@ -82,7 +78,24 @@ static struct o2cb_stack classic_stack = {
 	.s_ops		= &classic_ops,
 };
 
+static errcode_t user_begin_group_join(const char *cluster_name,
+				       struct o2cb_region_desc *desc);
+static errcode_t user_complete_group_join(const char *cluster_name,
+					  struct o2cb_region_desc *desc,
+					  int result);
+static errcode_t user_group_leave(const char *cluster_name,
+				  struct o2cb_region_desc *desc);
+static struct o2cb_group_ops user_ops = {
+	.begin_group_join	= user_begin_group_join,
+	.complete_group_join	= user_complete_group_join,
+	.group_leave		= user_group_leave,
+};
+static struct o2cb_stack user_stack = {
+	.s_ops		= &user_ops,
+};
+
 static struct o2cb_stack *current_stack;
+static int controld_fd = -1;
 
 static char *configfs_path;
 
@@ -121,6 +134,11 @@ static errcode_t determine_stack(void)
 		else if (!strcmp(line, classic_stack.s_name)) {
 			current_stack = &classic_stack;
 			err = 0;
+		} else {
+			strncpy(user_stack.s_name, line,
+				OCFS2_STACK_LABEL_LEN);
+			current_stack = &user_stack;
+			err = 0;
 		}
 	} else if (len == -ENOENT) {
 		current_stack = &classic_stack;
@@ -1176,16 +1194,287 @@ up:
 
 static errcode_t classic_complete_group_join(const char *cluster_name,
 					     struct o2cb_region_desc *desc,
-					     int error)
+					     int result)
 {
 	errcode_t ret = 0;
 
-	if (error)
-		ret = o2cb_group_leave(cluster_name, desc);
+	if (result)
+		ret = classic_group_leave(cluster_name, desc);
 
 	return ret;
 }
 
+static errcode_t user_parse_status(char **args, int *error, char **error_msg)
+{
+	errcode_t err = O2CB_ET_IO;
+	long result;
+	char *ptr = NULL;
+
+	result = strtol(args[0], &ptr, 10);
+	if (ptr && *ptr != '\0') {
+		/* fprintf(stderr, "Invalid error code string: %s", args[0]); */
+	} else if ((result == LONG_MIN) || (result == LONG_MAX) ||
+		   (result < INT_MIN) || (result > INT_MAX)) {
+		/* fprintf(stderr, "Error code %ld out of range", err); */
+	} else {
+		*error_msg = args[1];
+		*error = result;
+		err = 0;
+	}
+
+	return err;
+}
+
+static errcode_t user_begin_group_join(const char *cluster_name,
+				       struct o2cb_region_desc *desc)
+{
+	errcode_t err;
+	int rc;
+	int error;
+	char *error_msg;
+	client_message message;
+	char *argv[OCFS2_CONTROLD_MAXARGS + 1];
+	char buf[OCFS2_CONTROLD_MAXLINE];
+
+	if (controld_fd != -1) {
+		/* fprintf(stderr, "Join already in progress!\n"); */
+		err = O2CB_ET_INTERNAL_FAILURE;
+		goto out;
+	}
+
+	rc = ocfs2_client_connect();
+	if (rc < 0) {
+		/* fprintf(stderr, "Unable to connect to ocfs2_controld: %s\n",
+			strerror(-rc)); */
+		switch (rc) {
+			case -EACCES:
+			case -EPERM:
+				err = O2CB_ET_PERMISSION_DENIED;
+				break;
+
+			default:
+				err = O2CB_ET_SERVICE_UNAVAILABLE;
+				break;
+		}
+		goto out;
+	}
+	controld_fd = rc;
+
+	rc = send_message(controld_fd, CM_MOUNT, OCFS2_FS_NAME,
+			  desc->r_name, cluster_name, desc->r_device_name,
+			  desc->r_service);
+	if (rc) {
+		/* fprintf(stderr, "Unable to send MOUNT message: %s\n",
+			strerror(-rc)); */
+		err = O2CB_ET_IO;
+		goto out;
+	}
+
+	rc = receive_message(controld_fd, buf, &message, argv);
+	if (rc < 0) {
+		/* fprintf(stderr, "Error reading from daemon: %s\n",
+			strerror(-rc)); */
+		err = O2CB_ET_IO;
+		goto out;
+	}
+
+	switch (message) {
+		case CM_STATUS:
+			err = user_parse_status(argv, &error, &error_msg);
+			if (err) {
+				/* fprintf(stderr, "Bad status message: %s\n",
+					strerror(-rc)); */
+				goto out;
+			}
+			if (error && (error != EALREADY)) {
+				/* fprintf(stderr,
+					"Error %d from daemon: %s\n",
+					error, error_msg); */
+				err = O2CB_ET_CONFIGURATION_ERROR;
+				goto out;
+			}
+			break;
+
+		default:
+			/* fprintf(stderr,
+				"Unexpected message %s from daemon\n",
+				message_to_string(message)); */
+			err = O2CB_ET_INTERNAL_FAILURE;
+			goto out;
+			break;
+	}
+
+	err = 0;
+
+out:
+	if (err && (controld_fd != -1)) {
+		close(controld_fd);
+		controld_fd = -1;
+	}
+
+	return err;
+}
+
+static errcode_t user_complete_group_join(const char *cluster_name,
+					  struct o2cb_region_desc *desc,
+					  int result)
+{
+	errcode_t err = O2CB_ET_SERVICE_UNAVAILABLE;
+	int rc;
+	int error;
+	char *error_msg;
+	client_message message;
+	char *argv[OCFS2_CONTROLD_MAXARGS + 1];
+	char buf[OCFS2_CONTROLD_MAXLINE];
+
+	if (controld_fd == -1) {
+		/* fprintf(stderr, "Join not started!\n"); */
+		err = O2CB_ET_SERVICE_UNAVAILABLE;
+		goto out;
+	}
+
+	rc = send_message(controld_fd, CM_MRESULT, OCFS2_FS_NAME,
+			  desc->r_name, result, desc->r_service);
+	if (rc) {
+		/* fprintf(stderr, "Unable to send MRESULT message: %s\n",
+			strerror(-rc)); */
+		err = O2CB_ET_IO;
+		goto out;
+	}
+
+	rc = receive_message(controld_fd, buf, &message, argv);
+	if (rc < 0) {
+		/* fprintf(stderr, "Error reading from daemon: %s\n",
+			strerror(-rc)); */
+		err = O2CB_ET_IO;
+		goto out;
+	}
+
+	switch (message) {
+		case CM_STATUS:
+			err = user_parse_status(argv, &error, &error_msg);
+			if (err) {
+				/* fprintf(stderr, "Bad status message: %s\n",
+					strerror(-rc)); */
+				goto out;
+			}
+			if (error) {
+				/* fprintf(stderr,
+					"Error %d from daemon: %s\n",
+					error, error_msg); */
+				err = O2CB_ET_CONFIGURATION_ERROR;
+			}
+			break;
+
+		default:
+			/* fprintf(stderr,
+				"Unexpected message %s from daemon\n",
+				message_to_string(message)); */
+			err = O2CB_ET_INTERNAL_FAILURE;
+			goto out;
+			break;
+	}
+
+	err = 0;
+
+out:
+	if (controld_fd != -1) {
+		close(controld_fd);
+		controld_fd = -1;
+	}
+
+	return err;
+}
+
+static errcode_t user_group_leave(const char *cluster_name,
+				  struct o2cb_region_desc *desc)
+{
+	errcode_t err = O2CB_ET_SERVICE_UNAVAILABLE;
+	int rc;
+	int error;
+	char *error_msg;
+	client_message message;
+	char *argv[OCFS2_CONTROLD_MAXARGS + 1];
+	char buf[OCFS2_CONTROLD_MAXLINE];
+
+	if (controld_fd != -1) {
+		/* fprintf(stderr, "Join in progress!\n"); */
+		err = O2CB_ET_INTERNAL_FAILURE;
+		goto out;
+	}
+
+	rc = ocfs2_client_connect();
+	if (rc < 0) {
+		/* fprintf(stderr, "Unable to connect to ocfs2_controld: %s\n",
+			strerror(-rc)); */
+		switch (rc) {
+			case -EACCES:
+			case -EPERM:
+				err = O2CB_ET_PERMISSION_DENIED;
+				break;
+
+			default:
+				err = O2CB_ET_SERVICE_UNAVAILABLE;
+				break;
+		}
+		goto out;
+	}
+	controld_fd = rc;
+
+	rc = send_message(controld_fd, CM_UNMOUNT, OCFS2_FS_NAME,
+			  desc->r_name, desc->r_service);
+	if (rc) {
+		/* fprintf(stderr, "Unable to send UNMOUNT message: %s\n",
+			strerror(-rc)); */
+		err = O2CB_ET_IO;
+		goto out;
+	}
+
+	rc = receive_message(controld_fd, buf, &message, argv);
+	if (rc < 0) {
+		/* fprintf(stderr, "Error reading from daemon: %s\n",
+			strerror(-rc)); */
+		err = O2CB_ET_IO;
+		goto out;
+	}
+
+	switch (message) {
+		case CM_STATUS:
+			err = user_parse_status(argv, &error, &error_msg);
+			if (err) {
+				/* fprintf(stderr, "Bad status message: %s\n",
+					strerror(-rc)); */
+				goto out;
+			}
+			if (error) {
+				/* fprintf(stderr,
+					"Error %d from daemon: %s\n",
+					error, error_msg); */
+				err = O2CB_ET_CONFIGURATION_ERROR;
+				goto out;
+			}
+			break;
+
+		default:
+			/* fprintf(stderr,
+				"Unexpected message %s from daemon\n",
+				message_to_string(message)); */
+			err = O2CB_ET_INTERNAL_FAILURE;
+			goto out;
+			break;
+	}
+
+	err = 0;
+
+out:
+	if (controld_fd != -1) {
+		close(controld_fd);
+		controld_fd = -1;
+	}
+
+	return err;
+}
+
 errcode_t o2cb_begin_group_join(const char *cluster_name,
 				struct o2cb_region_desc *desc)
 {
@@ -1207,7 +1496,7 @@ errcode_t o2cb_begin_group_join(const char *cluster_name,
 
 errcode_t o2cb_complete_group_join(const char *cluster_name,
 				   struct o2cb_region_desc *desc,
-				   int error)
+				   int result)
 {
 	errcode_t err;
 	char _fake_cluster_name[NAME_MAX];
@@ -1223,7 +1512,7 @@ errcode_t o2cb_complete_group_join(const char *cluster_name,
 	}
 
 	return current_stack->s_ops->complete_group_join(cluster_name,
-							 desc, error);
+							 desc, result);
 }
 
 errcode_t o2cb_group_leave(const char *cluster_name,
-- 
1.5.3.8




More information about the Ocfs2-tools-devel mailing list