[Ocfs2-tools-devel] [PATCH 11/39] ocfs2_controld: Add the test
client
Joel Becker
joel.becker at oracle.com
Fri Mar 14 16:52:34 PDT 2008
The test_client allows us to poke ocfs2_controld without trying to
actually run mount(1).
Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
Makefile | 2 +-
ocfs2_controld/.gitignore | 3 +
ocfs2_controld/Makefile | 39 +++++
ocfs2_controld/test_client.c | 332 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 375 insertions(+), 1 deletions(-)
create mode 100644 ocfs2_controld/.gitignore
create mode 100644 ocfs2_controld/Makefile
create mode 100644 ocfs2_controld/test_client.c
diff --git a/Makefile b/Makefile
index d5c56fa..29e45cf 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ CHKCONFIG_DEP = chkconfig
COMPILE_PY = 1
endif
-SUBDIRS = include libo2dlm libo2cb libocfs2 fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 o2cb_ctl ocfs2_hb_ctl mount.ocfs2 ocfs2cdsl listuuid sizetest extras patches
+SUBDIRS = include libo2dlm libo2cb libocfs2 fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 o2cb_ctl ocfs2_hb_ctl mount.ocfs2 ocfs2_controld ocfs2cdsl listuuid sizetest extras patches
ifdef BUILD_OCFS2CONSOLE
SUBDIRS += ocfs2console
diff --git a/ocfs2_controld/.gitignore b/ocfs2_controld/.gitignore
new file mode 100644
index 0000000..8ee7107
--- /dev/null
+++ b/ocfs2_controld/.gitignore
@@ -0,0 +1,3 @@
+.*.sw?
+*.d
+test_client
diff --git a/ocfs2_controld/Makefile b/ocfs2_controld/Makefile
new file mode 100644
index 0000000..f8ade09
--- /dev/null
+++ b/ocfs2_controld/Makefile
@@ -0,0 +1,39 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+ifneq ($(BUILD_CMAN_SUPPORT),)
+UNINST_PROGRAMS = test_client
+endif
+
+INCLUDES = -I$(TOPDIR)/include
+LIBO2CB_LIBS = -L$(TOPDIR)/libo2cb -lo2cb
+LIBO2CB_DEPS = $(TOPDIR)/libo2cb/libo2cb.a
+LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
+LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
+
+ifdef OCFS2_DEBUG
+OPTS += -ggdb
+else
+OPTS += -O2
+endif
+
+CFLAGS := $(OPTS) -Wall -Wstrict-prototypes -Wmissing-prototypes \
+ -Wmissing-declarations
+
+DEFINES = -DOCFS2_FLAT_INCLUDES -DO2DLM_FLAT_INCLUDES \
+ -DO2CB_FLAT_INCLUDES -DHAVE_CMAN -DVERSION=\"$(VERSION)\"
+
+TEST_CFILES = test_client.c
+
+TEST_OBJS = $(subst .c,.o,$(TEST_CFILES) $(PROTO_CFILES))
+MANS =
+
+DIST_FILES = \
+ $(TEST_CFILES) \
+ $(addsuffix .in,$(MANS))
+
+test_client: $(TEST_OBJS) $(LIBO2CB_DEPS) $(LIBOCFS2_DEPS)
+ $(LINK) $(LIBOCFS2_LIBS) $(LIBO2CB_LIBS) $(COM_ERR_LIBS)
+
+include $(TOPDIR)/Postamble.make
diff --git a/ocfs2_controld/test_client.c b/ocfs2_controld/test_client.c
new file mode 100644
index 0000000..33147a9
--- /dev/null
+++ b/ocfs2_controld/test_client.c
@@ -0,0 +1,332 @@
+/* -*- 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 <stdlib.h>
+#include <stddef.h>
+#include <mntent.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "ocfs2/ocfs2.h"
+#include "o2cb/o2cb_client_proto.h"
+
+
+
+static int parse_status(char **args, int *error, char **error_msg)
+{
+ int rc = 0;
+ long err;
+ char *ptr = NULL;
+
+ err = strtol(args[0], &ptr, 10);
+ if (ptr && *ptr != '\0') {
+ fprintf(stderr, "Invalid error code string: %s", args[0]);
+ rc = -EINVAL;
+ } else if ((err == LONG_MIN) || (err == LONG_MAX) ||
+ (err < INT_MIN) || (err > INT_MAX)) {
+ fprintf(stderr, "Error code %ld out of range", err);
+ rc = -ERANGE;
+ } else {
+ *error_msg = args[1];
+ *error = err;
+ }
+
+ return rc;
+}
+
+static errcode_t fill_uuid(const char *device, char *uuid)
+{
+ errcode_t err;
+ ocfs2_filesys *fs;
+ struct o2cb_region_desc desc;
+
+ err = ocfs2_open(device, OCFS2_FLAG_RO, 0, 0, &fs);
+ if (err)
+ goto out;
+
+ err = ocfs2_fill_heartbeat_desc(fs, &desc);
+ ocfs2_close(fs);
+
+ if (!err)
+ strncpy(uuid, desc.r_name, OCFS2_VOL_UUID_LEN + 1);
+out:
+ return err;
+}
+
+static int call_mount(int fd, const char *uuid, const char *cluster,
+ const char *device, const char *mountpoint)
+{
+ int rc;
+ int error;
+ char *error_msg;
+ client_message message;
+ char *argv[OCFS2_CONTROLD_MAXARGS + 1];
+ char buf[OCFS2_CONTROLD_MAXLINE];
+
+ rc = send_message(fd, CM_MOUNT, OCFS2_FS_NAME, uuid, cluster,
+ device, mountpoint);
+ if (rc) {
+ fprintf(stderr, "Unable to send MOUNT message: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+
+ rc = receive_message(fd, buf, &message, argv);
+ if (rc < 0) {
+ fprintf(stderr, "Error reading from daemon: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+
+ switch (message) {
+ case CM_STATUS:
+ rc = parse_status(argv, &error, &error_msg);
+ if (rc) {
+ fprintf(stderr, "Bad status message: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+ if (error && (error != EALREADY)) {
+ rc = -error;
+ fprintf(stderr,
+ "Error %d from daemon: %s\n",
+ error, error_msg);
+ goto out;
+ }
+ break;
+
+ default:
+ rc = -EINVAL;
+ fprintf(stderr,
+ "Unexpected message %s from daemon\n",
+ message_to_string(message));
+ goto out;
+ break;
+ }
+
+ /* XXX Here we fake mount */
+ /* rc = mount(...); */
+ rc = 0;
+
+ rc = send_message(fd, CM_MRESULT, OCFS2_FS_NAME, uuid, rc,
+ mountpoint);
+ if (rc) {
+ fprintf(stderr, "Unable to send MRESULT message: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+
+ rc = receive_message(fd, buf, &message, argv);
+ if (rc < 0) {
+ fprintf(stderr, "Error reading from daemon: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+
+ switch (message) {
+ case CM_STATUS:
+ rc = parse_status(argv, &error, &error_msg);
+ if (rc) {
+ fprintf(stderr, "Bad status message: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+ if (error) {
+ rc = -error;
+ fprintf(stderr,
+ "Error %d from daemon: %s\n",
+ error, error_msg);
+ }
+ break;
+
+ default:
+ rc = -EINVAL;
+ fprintf(stderr,
+ "Unexpected message %s from daemon\n",
+ message_to_string(message));
+ break;
+ }
+
+out:
+ return rc;
+}
+
+static int call_unmount(int fd, const char *uuid, const char *mountpoint)
+{
+ int rc = 0;
+ int error;
+ char *error_msg;
+ client_message message;
+ char *argv[OCFS2_CONTROLD_MAXARGS + 1];
+ char buf[OCFS2_CONTROLD_MAXLINE];
+#if 0
+ errcode_t err;
+ FILE *mntfile;
+ struct mntent *entp;
+ char device[PATH_MAX + 1];
+ char uuid[OCFS2_VOL_UUID_LEN + 1];
+
+ device[0] = '\0';
+
+ mntfile = setmntent("/tmp/fakemtab", "r");
+ if (!mntfile) {
+ rc = -errno;
+ fprintf(stderr, "Unable to open mtab: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+
+ while ((entp = getmntent(mntfile)) != NULL) {
+ if (strcmp(entp->mnt_type, OCFS2_FSTYPE))
+ continue;
+ if (strcmp(entp->mnt_type, mountpoint))
+ continue;
+ strncpy(device, entp->mnt_fsname, PATH_MAX);
+ }
+ endmntent(mntfile);
+
+ if (!*device) {
+ rc = -ENOENT;
+ fprintf(stderr, "Unable to find filesystem %s\n",
+ mountpoint);
+ goto out;
+ }
+
+ err = fill_uuid(device, uuid);
+ if (err) {
+ com_err("test_client", err,
+ "while trying to read uuid from %s", device);
+ rc = -EIO;
+ goto out;
+ }
+#endif
+
+ rc = send_message(fd, CM_UNMOUNT, OCFS2_FS_NAME, uuid, mountpoint);
+ if (rc) {
+ fprintf(stderr, "Unable to send UNMOUNT message: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+
+ rc = receive_message(fd, buf, &message, argv);
+ if (rc < 0) {
+ fprintf(stderr, "Error reading from daemon: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+
+ switch (message) {
+ case CM_STATUS:
+ rc = parse_status(argv, &error, &error_msg);
+ if (rc) {
+ fprintf(stderr, "Bad status message: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+ if (error) {
+ rc = -error;
+ fprintf(stderr,
+ "Error %d from daemon: %s\n",
+ error, error_msg);
+ goto out;
+ }
+ break;
+
+ default:
+ rc = -EINVAL;
+ fprintf(stderr,
+ "Unexpected message %s from daemon\n",
+ message_to_string(message));
+ goto out;
+ break;
+ }
+
+out:
+ return rc;
+}
+
+enum {
+ OP_MOUNT,
+ OP_UMOUNT,
+};
+static int parse_options(int argc, char **argv, int *op, char ***args)
+{
+ int rc = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, "Operation required\n");
+ return -EINVAL;
+ }
+
+ if (!strcmp(argv[1], "mount")) {
+ if (argc == 6) {
+ *op = OP_MOUNT;
+ *args = argv + 2;
+ } else {
+ fprintf(stderr, "Invalid number of arguments\n");
+ rc = -EINVAL;
+ }
+ } else if (!strcmp(argv[1], "umount")) {
+ if (argc == 4) {
+ *op = OP_UMOUNT;
+ *args = argv + 2;
+ } else {
+ fprintf(stderr, "Invalid number of arguments\n");
+ rc = -EINVAL;
+ }
+ } else {
+ fprintf(stderr, "Invalid operation: %s\n", argv[1]);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+int main(int argc, char **argv)
+{
+ int rc, fd, op;
+ char **args;
+
+ rc = parse_options(argc, argv, &op, &args);
+ if (rc)
+ goto out;
+
+ rc = ocfs2_client_connect();
+ if (rc < 0) {
+ fprintf(stderr, "Unable to connect to ocfs2_controld: %s\n",
+ strerror(-rc));
+ goto out;
+ }
+ fd = rc;
+
+ switch (op) {
+ case OP_MOUNT:
+ rc = call_mount(fd, args[0], args[1], args[2],
+ args[3]);
+ break;
+
+ case OP_UMOUNT:
+ rc = call_unmount(fd, args[0], args[1]);
+ break;
+
+ default:
+ fprintf(stderr, "Can't get here!\n");
+ rc = -ENOTSUP;
+ break;
+ }
+
+ close(fd);
+
+out:
+ return rc;
+}
--
1.5.3.8
More information about the Ocfs2-tools-devel
mailing list