[Ocfs2-tools-devel] [PATCH 10/39] libo2cb: Add the client protocol
files.
Joel Becker
joel.becker at oracle.com
Fri Mar 14 16:52:33 PDT 2008
The control daemon protocol is added to libo2cb. It is only built when
libcman is detected.
Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
include/o2cb/Makefile | 2 +-
include/o2cb/o2cb_client_proto.h | 66 ++++++++++
libo2cb/Makefile | 9 +-
libo2cb/client_proto.c | 265 ++++++++++++++++++++++++++++++++++++++
4 files changed, 340 insertions(+), 2 deletions(-)
create mode 100644 include/o2cb/o2cb_client_proto.h
create mode 100644 libo2cb/client_proto.c
diff --git a/include/o2cb/Makefile b/include/o2cb/Makefile
index 59bfd7c..4fc0542 100644
--- a/include/o2cb/Makefile
+++ b/include/o2cb/Makefile
@@ -6,7 +6,7 @@ HFILES_GEN = o2cb_err.h
all: $(HFILES_GEN)
-HFILES = o2cb.h ocfs2_nodemanager.h ocfs2_heartbeat.h
+HFILES = o2cb.h ocfs2_nodemanager.h ocfs2_heartbeat.h o2cb_client_proto.h
HEADERS_SUBDIR = o2cb
HEADERS = $(HFILES) $(HFILES_GEN)
diff --git a/include/o2cb/o2cb_client_proto.h b/include/o2cb/o2cb_client_proto.h
new file mode 100644
index 0000000..61df7c3
--- /dev/null
+++ b/include/o2cb/o2cb_client_proto.h
@@ -0,0 +1,66 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ */
+
+/******************************************************************************
+*******************************************************************************
+**
+** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+**
+** This copyrighted material is made available to anyone wishing to use,
+** modify, copy, or redistribute it subject to the terms and conditions
+** of the GNU General Public License v.2.
+**
+*******************************************************************************
+******************************************************************************/
+
+/*
+ * Copyright (C) 2007 Oracle. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#ifndef __O2CB_CLIENT_PROTO_H
+#define __O2CB_CLIENT_PROTO_H
+
+#ifdef HAVE_CMAN
+
+/* Basic communication properties */
+#define OCFS2_CONTROLD_MAXLINE 256
+#define OCFS2_CONTROLD_MAXARGS 16
+#define OCFS2_CONTROLD_SOCK_PATH "ocfs2_controld_sock"
+#define O2CB_CONTROLD_SOCK_PATH "o2cb_controld_sock"
+
+/* Client messages */
+typedef enum {
+ CM_MOUNT,
+ CM_MRESULT,
+ CM_UNMOUNT,
+ CM_STATUS,
+} client_message;
+
+int client_listen(const char *path);
+int client_connect(const char *path);
+
+static inline int ocfs2_client_listen(void)
+{
+ return client_listen(OCFS2_CONTROLD_SOCK_PATH);
+}
+
+static inline int ocfs2_client_connect(void)
+{
+ return client_connect(OCFS2_CONTROLD_SOCK_PATH);
+}
+
+const char *message_to_string(client_message message);
+int send_message(int fd, client_message message, ...);
+int receive_message(int fd, char *buf, client_message *message,
+ char **argv);
+int receive_message_full(int fd, char *buf, client_message *message,
+ char **argv, char **rest);
+
+#endif /* HAVE_CMAN */
+
+#endif /* __O2CB_CLIENT_PROTO_H */
diff --git a/libo2cb/Makefile b/libo2cb/Makefile
index 6d36ad2..9aa27c2 100644
--- a/libo2cb/Makefile
+++ b/libo2cb/Makefile
@@ -33,6 +33,8 @@ CFILES = \
o2cb_abi.c \
o2cb_crc32.c
+PROTO_CFILES = client_proto.c
+
HFILES = \
o2cb_abi.h \
o2cb_crc32.h
@@ -42,6 +44,11 @@ HFILES_GEN = o2cb_err.h
OBJS = $(subst .c,.o,$(CFILES)) \
o2cb_err.o
+ifneq ($(BUILD_CMAN_SUPPORT),)
+DEFINES += -DHAVE_CMAN
+OBJS += $(subst .c,.o,$(PROTO_CFILES))
+endif
+
$(OBJS): $(HFILES_GEN)
o2cb_err.c o2cb_err.h: o2cb_err.et
@@ -52,7 +59,7 @@ libo2cb.a: $(OBJS)
$(AR) r $@ $^
$(RANLIB) $@
-DIST_FILES = $(CFILES) $(HFILES) o2cb_err.et
+DIST_FILES = $(CFILES) $(PROTO_CFILES) $(HFILES) o2cb_err.et
CLEAN_RULES = clean-err
diff --git a/libo2cb/client_proto.c b/libo2cb/client_proto.c
new file mode 100644
index 0000000..a152cfa
--- /dev/null
+++ b/libo2cb/client_proto.c
@@ -0,0 +1,265 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2007 Oracle. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "o2cb/o2cb_client_proto.h"
+
+struct client_message {
+ char *cm_command;
+ int cm_argcount;
+ char *cm_format;
+};
+
+#define BEGIN_MESSAGES(_list) struct client_message _list[] = {
+#define END_MESSAGES(_list) }; \
+ int _list##_len = sizeof(_list) / sizeof(_list[0]);
+#define DEFINE_MESSAGE(_name, _argcount, _format) [CM_##_name] = { \
+ .cm_command = #_name, \
+ .cm_argcount = _argcount, \
+ .cm_format = #_name " " _format, \
+},
+
+BEGIN_MESSAGES(message_list)
+DEFINE_MESSAGE(MOUNT, 5, "%s %s %s %s %s")
+DEFINE_MESSAGE(MRESULT, 4, "%s %s %d %s")
+DEFINE_MESSAGE(UNMOUNT, 3, "%s %s %s")
+DEFINE_MESSAGE(STATUS, 2, "%d %s")
+END_MESSAGES(message_list)
+
+const char *message_to_string(client_message message)
+{
+ return message_list[message].cm_command;
+}
+
+/* No short reads allowed */
+static int full_read(int fd, void *buf, size_t count)
+{
+ size_t off = 0;
+ ssize_t rc = 0;
+
+ while (off < count) {
+ rc = read(fd, buf + off, count - off);
+ if (rc == 0)
+ return -EPIPE;
+ if (rc == -1) {
+ rc = -errno;
+ if (rc == -EINTR)
+ continue;
+ break;
+ }
+ off += rc;
+ rc = 0;
+ }
+ return rc;
+}
+
+/* No short writes allowed */
+static int full_write(int fd, void *buf, size_t count)
+{
+ size_t off = 0;
+ ssize_t rc = 0;
+
+ while (off < count) {
+ rc = write(fd, buf + off, count - off);
+ if (rc == 0)
+ return -EPIPE;
+ if (rc == -1) {
+ rc = -errno;
+ if (rc == -EINTR)
+ continue;
+ break;
+ }
+ off += rc;
+ rc = 0;
+ }
+ return rc;
+}
+
+int send_message(int fd, client_message message, ...)
+{
+ int rc;
+ va_list args;
+ char mbuf[OCFS2_CONTROLD_MAXLINE];
+
+ memset(mbuf, 0, OCFS2_CONTROLD_MAXLINE);
+ va_start(args, message);
+ rc = vsnprintf(mbuf, OCFS2_CONTROLD_MAXLINE,
+ message_list[message].cm_format, args);
+ va_end(args);
+ if (rc >= OCFS2_CONTROLD_MAXLINE)
+ rc = -E2BIG;
+ else
+ rc = full_write(fd, mbuf, OCFS2_CONTROLD_MAXLINE);
+
+ return rc;
+}
+
+static char *get_args(char *buf, int *argc, char **argv, char sep, int want)
+{
+ char *p = buf, *rp = NULL;
+ int i = 0;
+
+ /* Skip the first word, which is the command */
+ p = strchr(buf, sep);
+ if (!p)
+ goto out;
+ p += 1;
+ argv[0] = p;
+
+ for (i = 1; i < OCFS2_CONTROLD_MAXARGS; i++) {
+ p = strchr(p, sep);
+ if (!p) {
+ rp = p + 1;
+ break;
+ }
+
+ if (want == i)
+ break;
+
+ *p = '\0';
+ p += 1;
+ argv[i] = p;
+ }
+
+out:
+ if (argc)
+ *argc = i;
+
+ /* Terminate the list, the caller expects us to */
+ argv[i] = NULL;
+
+ /* we ended by hitting \0, return the point following that */
+ if (!rp)
+ rp = strchr(buf, '\0') + 1;
+
+ return rp;
+}
+
+int receive_message_full(int fd, char *buf, client_message *message,
+ char **argv, char **rest)
+{
+ int i, rc, len, count;
+ client_message msg;
+ char *r;
+
+ rc = full_read(fd, buf, OCFS2_CONTROLD_MAXLINE);
+ if (rc)
+ goto out;
+
+ /* Safety first */
+ buf[OCFS2_CONTROLD_MAXLINE - 1] = '\0';
+ /* fprintf(stderr, "Got messsage \"%s\"\n", buf); */
+
+
+ for (i = 0; i < message_list_len; i++) {
+ len = strlen(message_list[i].cm_command);
+ if (!strncmp(buf, message_list[i].cm_command, len) &&
+ (buf[len] == ' '))
+ break;
+ }
+ if (i >= message_list_len) {
+ rc = -EBADMSG;
+ goto out;
+ }
+ msg = i;
+
+ r = get_args(buf, &count, argv, ' ',
+ message_list[msg].cm_argcount);
+ if (count != message_list[msg].cm_argcount) {
+ rc = -EBADMSG;
+ } else {
+ /* for (i = 0; i < count; i++)
+ fprintf(stderr, "Arg %d: \"%s\"\n", i, argv[i]); */
+ if (message)
+ *message = msg;
+ if (rest)
+ *rest = r;
+ }
+
+out:
+ return rc;
+}
+
+int receive_message(int fd, char *buf, client_message *message, char **argv)
+{
+ return receive_message_full(fd, buf, message, argv, NULL);
+}
+
+int client_listen(const char *path)
+{
+ struct sockaddr_un addr;
+ socklen_t addrlen;
+ int rv, s;
+
+ /* we listen for new client connections on socket s */
+
+ s = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (s < 0) {
+ /* log_error("socket error %d %d", s, errno); */
+ return s;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ strcpy(&addr.sun_path[1], path);
+ addrlen = sizeof(sa_family_t) + strlen(addr.sun_path+1) + 1;
+
+ rv = bind(s, (struct sockaddr *) &addr, addrlen);
+ if (rv < 0) {
+ /* log_error("bind error %d %d", rv, errno); */
+ close(s);
+ return rv;
+ }
+
+ rv = listen(s, 5);
+ if (rv < 0) {
+ /* log_error("listen error %d %d", rv, errno); */
+ close(s);
+ return rv;
+ }
+
+ /* log_debug("listen %d", s); */
+
+ return s;
+}
+
+int client_connect(const char *path)
+{
+ struct sockaddr_un sun;
+ socklen_t addrlen;
+ int rv, fd;
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ fd = -errno;
+ goto out;
+ }
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strcpy(&sun.sun_path[1], path);
+ addrlen = sizeof(sa_family_t) + strlen(sun.sun_path+1) + 1;
+
+ rv = connect(fd, (struct sockaddr *) &sun, addrlen);
+ if (rv < 0) {
+ close(fd);
+ fd = -errno;
+ }
+ out:
+ return fd;
+}
--
1.5.3.8
More information about the Ocfs2-tools-devel
mailing list