[Ocfs2-tools-commits] jlbec commits r1363 - in branches/cman-based:
. o2cb_controld
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Mon Jul 16 00:31:50 PDT 2007
Author: jlbec
Date: 2007-07-16 00:31:49 -0700 (Mon, 16 Jul 2007)
New Revision: 1363
Added:
branches/cman-based/o2cb_controld/
branches/cman-based/o2cb_controld/Makefile
branches/cman-based/o2cb_controld/action.c
branches/cman-based/o2cb_controld/main.c
branches/cman-based/o2cb_controld/member_cman.c
branches/cman-based/o2cb_controld/o2cb_controld.h
Modified:
branches/cman-based/Makefile
Log:
Add a first cut at a compiling daemon. I don't know if nodeids are correct,
and I haven't tested it. But it's a good starting point.
I need to test. I need to teach configure to determine whether cman exists.
action.c should use libo2cb rather than doing the configfs work itself.
That sort of thing.
Modified: branches/cman-based/Makefile
===================================================================
--- branches/cman-based/Makefile 2007-07-16 07:30:23 UTC (rev 1362)
+++ branches/cman-based/Makefile 2007-07-16 07:31:49 UTC (rev 1363)
@@ -20,7 +20,7 @@
COMPILE_PY = 1
endif
-SUBDIRS = libo2dlm libo2cb libocfs2 fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 o2cb_ctl ocfs2_hb_ctl mount.ocfs2 listuuid sizetest extras patches
+SUBDIRS = libo2dlm libo2cb libocfs2 fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 o2cb_ctl ocfs2_hb_ctl mount.ocfs2 listuuid sizetest extras patches o2cb_controld
ifdef BUILD_OCFS2CDSL
SUBDIRS += ocfs2cdsl
Added: branches/cman-based/o2cb_controld/Makefile
===================================================================
--- branches/cman-based/o2cb_controld/Makefile 2007-07-16 07:30:23 UTC (rev 1362)
+++ branches/cman-based/o2cb_controld/Makefile 2007-07-16 07:31:49 UTC (rev 1363)
@@ -0,0 +1,42 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+SBIN_PROGRAMS = o2cb_controld
+
+#INCLUDES = -Iinclude -I$(TOPDIR)/libocfs2/include \
+# -I$(TOPDIR)/libo2cb/include -I$(TOPDIR)/libo2dlm/include
+#LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
+#LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
+#LIBO2DLM_LIBS = -L$(TOPDIR)/libo2dlm -lo2dlm
+#LIBO2DLM_DEPS = $(TOPDIR)/libo2dlm/libo2dlm.a
+
+INCLUDES = -I$(TOPDIR)/libo2dlm/include -I$(TOPDIR)/libo2cb/include
+LIBO2CB_LIBS = -L$(TOPDIR)/libo2cb -lo2cb
+LIBO2CB_DEPS = $(TOPDIR)/libo2cb/libo2cb.a
+
+ifdef OCFS2_DEBUG
+OPTS += -ggdb
+else
+OPTS += -O2
+endif
+
+CFLAGS := $(OPTS) -Wall -Wstrict-prototypes -Wmissing-prototypes \
+ -Wmissing-declarations
+
+DEFINES = -DO2CB_FLAT_INCLUDES -DVERSION=\"$(VERSION)\"
+
+CFILES = main.c action.c member_cman.c
+
+#HFILES = $(subst .c,.h,$(CFILES))
+#HFILES += mount_constants.h nls.h paths.h
+
+OBJS = $(subst .c,.o,$(CFILES))
+#MANS = ocfs2_dlm_controld
+
+DIST_FILES = $(CFILES) $(HFILES) $(addsuffix .in,$(MANS))
+
+o2cb_controld: $(OBJS) $(LIBO2CB_DEPS)
+ $(LINK) $(LIBO2CB_LIBS) $(COM_ERR_LIBS) -lcman
+
+include $(TOPDIR)/Postamble.make
Added: branches/cman-based/o2cb_controld/action.c
===================================================================
--- branches/cman-based/o2cb_controld/action.c 2007-07-16 07:30:23 UTC (rev 1362)
+++ branches/cman-based/o2cb_controld/action.c 2007-07-16 07:31:49 UTC (rev 1363)
@@ -0,0 +1,933 @@
+/* -*- 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.
+ */
+
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <limits.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include "o2cb_controld.h"
+#include "ccs.h"
+
+#if 0
+static int dir_members[MAX_GROUP_MEMBERS];
+static int dir_members_count;
+#endif
+
+static char cluster_dir[PATH_MAX] = "";
+static char nodes_dir[PATH_MAX] = "";
+
+#define CLUSTER_BASE "/sys/kernel/config/cluster"
+#define CLUSTER_FORMAT CLUSTER_BASE "/%s"
+#define NODES_FORMAT CLUSTER_FORMAT "/nodes"
+
+
+static int do_write(int fd, void *buf, size_t count)
+{
+ int rv, off = 0;
+
+ retry:
+ rv = write(fd, buf + off, count);
+ if (rv == -1 && errno == EINTR)
+ goto retry;
+ if (rv < 0) {
+ log_error("write errno %d", errno);
+ return rv;
+ }
+
+ if (rv != count) {
+ count -= rv;
+ off += rv;
+ goto retry;
+ }
+ return 0;
+}
+
+#if 0
+static int do_sysfs(char *name, char *file, char *val)
+{
+ char fname[512];
+ int rv, fd;
+
+ sprintf(fname, "%s/%s/%s", DLM_SYSFS_DIR, name, file);
+
+ fd = open(fname, O_WRONLY);
+ if (fd < 0) {
+ log_error("open \"%s\" error %d %d", fname, fd, errno);
+ return -1;
+ }
+
+ log_debug("write \"%s\" to \"%s\"", val, fname);
+
+ rv = do_write(fd, val, strlen(val) + 1);
+ close(fd);
+ return rv;
+}
+
+int set_control(char *name, int val)
+{
+ char buf[32];
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, 32, "%d", val);
+
+ return do_sysfs(name, "control", buf);
+}
+
+int set_event_done(char *name, int val)
+{
+ char buf[32];
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, 32, "%d", val);
+
+ return do_sysfs(name, "event_done", buf);
+}
+
+int set_id(char *name, uint32_t id)
+{
+ char buf[32];
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, 32, "%u", id);
+
+ return do_sysfs(name, "id", buf);
+}
+#endif
+
+#if 0
+static int update_dir_members(char *name)
+{
+ char path[PATH_MAX];
+ DIR *d;
+ struct dirent *de;
+ int i = 0;
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s/nodes", SPACES_DIR, name);
+
+ d = opendir(path);
+ if (!d) {
+ log_debug("%s: opendir failed: %d", path, errno);
+ return -1;
+ }
+
+ memset(dir_members, 0, sizeof(dir_members));
+ dir_members_count = 0;
+
+ /* FIXME: we should probably read the nodeid in each dir instead */
+
+ while ((de = readdir(d))) {
+ if (de->d_name[0] == '.')
+ continue;
+ dir_members[i++] = atoi(de->d_name);
+ log_debug("dir_member %d", dir_members[i-1]);
+ }
+ closedir(d);
+
+ dir_members_count = i;
+ return 0;
+}
+
+static int id_exists(int id, int count, int *array)
+{
+ int i;
+ for (i = 0; i < count; i++) {
+ if (array[i] == id)
+ return 1;
+ }
+ return 0;
+}
+#endif
+
+static int create_path(char *path)
+{
+ mode_t old_umask;
+ int rv;
+
+ old_umask = umask(0022);
+ rv = mkdir(path, 0777);
+ umask(old_umask);
+
+ if (rv < 0) {
+ log_error("%s: mkdir failed: %d", path, errno);
+ if (errno == EEXIST)
+ rv = 0;
+ }
+ return rv;
+}
+
+static int path_exists(const char *path)
+{
+ struct stat buf;
+
+ if (stat(path, &buf) < 0) {
+ if (errno != ENOENT)
+ log_error("%s: stat failed: %d", path, errno);
+ return 0;
+ }
+ return 1;
+}
+
+#if 0
+static int open_ccs(void)
+{
+ int i, cd;
+
+ while ((cd = ccs_connect()) < 0) {
+ sleep(1);
+ if (++i > 9 && !(i % 10))
+ log_error("connect to ccs error %d, "
+ "check ccsd or cluster status", cd);
+ }
+ return cd;
+}
+
+/* when not set in cluster.conf, a node's default weight is 1 */
+
+#define WEIGHT_PATH "/cluster/clusternodes/clusternode[@name=\"%s\"]/@weight"
+
+static int get_weight(int cd, int nodeid)
+{
+ char path[PATH_MAX], *str, *name;
+ int error, w;
+
+ name = nodeid2name(nodeid);
+ if (!name) {
+ log_error("no name for nodeid %d", nodeid);
+ return 1;
+ }
+
+ memset(path, 0, PATH_MAX);
+ sprintf(path, WEIGHT_PATH, name);
+
+ error = ccs_get(cd, path, &str);
+ if (error || !str)
+ return 1;
+
+ w = atoi(str);
+ free(str);
+ return w;
+}
+
+int set_members(char *name, int new_count, int *new_members)
+{
+ char path[PATH_MAX];
+ char buf[32];
+ int i, w, fd, rv, id, cd = 0, old_count, *old_members;
+
+ /*
+ * create lockspace dir if it doesn't exist yet
+ */
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s", SPACES_DIR, name);
+
+ if (!path_exists(path)) {
+ if (create_path(path))
+ return -1;
+ }
+
+ /*
+ * remove/add lockspace members
+ */
+
+ rv = update_dir_members(name);
+ if (rv)
+ return rv;
+
+ old_members = dir_members;
+ old_count = dir_members_count;
+
+ for (i = 0; i < old_count; i++) {
+ id = old_members[i];
+ if (id_exists(id, new_count, new_members))
+ continue;
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s/nodes/%d",
+ SPACES_DIR, name, id);
+
+ log_debug("set_members rmdir \"%s\"", path);
+
+ rv = rmdir(path);
+ if (rv) {
+ log_error("%s: rmdir failed: %d", path, errno);
+ goto out;
+ }
+ }
+
+ /*
+ * remove lockspace dir after we've removed all the nodes
+ * (when we're shutting down and adding no new nodes)
+ */
+
+ if (!new_count) {
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s", SPACES_DIR, name);
+
+ log_debug("set_members lockspace rmdir \"%s\"", path);
+
+ rv = rmdir(path);
+ if (rv)
+ log_error("%s: rmdir failed: %d", path, errno);
+ }
+
+ for (i = 0; i < new_count; i++) {
+ id = new_members[i];
+ if (id_exists(id, old_count, old_members))
+ continue;
+
+ if (!is_cman_member(id))
+ cman_statechange();
+ /*
+ * create node's dir
+ */
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s/nodes/%d",
+ SPACES_DIR, name, id);
+
+ log_debug("set_members mkdir \"%s\"", path);
+
+ rv = create_path(path);
+ if (rv)
+ goto out;
+
+ /*
+ * set node's nodeid
+ */
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s/nodes/%d/nodeid",
+ SPACES_DIR, name, id);
+
+ rv = fd = open(path, O_WRONLY);
+ if (rv < 0) {
+ log_error("%s: open failed: %d", path, errno);
+ goto out;
+ }
+
+ memset(buf, 0, 32);
+ snprintf(buf, 32, "%d", id);
+
+ rv = do_write(fd, buf, strlen(buf));
+ if (rv < 0) {
+ log_error("%s: write failed: %d, %s", path, errno, buf);
+ close(fd);
+ goto out;
+ }
+ close(fd);
+
+ /*
+ * set node's weight
+ */
+
+ if (!cd)
+ cd = open_ccs();
+
+ w = get_weight(cd, id);
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s/nodes/%d/weight",
+ SPACES_DIR, name, id);
+
+ rv = fd = open(path, O_WRONLY);
+ if (rv < 0) {
+ log_error("%s: open failed: %d", path, errno);
+ goto out;
+ }
+
+ memset(buf, 0, 32);
+ snprintf(buf, 32, "%d", w);
+
+ rv = do_write(fd, buf, strlen(buf));
+ if (rv < 0) {
+ log_error("%s: write failed: %d, %s", path, errno, buf);
+ close(fd);
+ goto out;
+ }
+ close(fd);
+ }
+
+ rv = 0;
+ out:
+ if (cd)
+ ccs_disconnect(cd);
+ return rv;
+}
+#endif
+
+#if 0
+char *str_ip(char *addr)
+{
+ static char ip[256];
+ struct sockaddr_in *sin = (struct sockaddr_in *) addr;
+ memset(ip, 0, sizeof(ip));
+ inet_ntop(AF_INET, &sin->sin_addr, ip, 256);
+ return ip;
+}
+#endif
+
+static char *str_ip(char *addr)
+{
+ static char str_ip_buf[INET6_ADDRSTRLEN];
+ struct sockaddr_storage *ss = (struct sockaddr_storage *)addr;
+ struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
+ void *saddr;
+
+ if (ss->ss_family == AF_INET6)
+ saddr = &sin6->sin6_addr;
+ else
+ saddr = &sin->sin_addr;
+
+ inet_ntop(ss->ss_family, saddr, str_ip_buf, sizeof(str_ip_buf));
+ return str_ip_buf;
+}
+
+static char *str_port(char *addr)
+{
+ static char str_port_buf[32];
+ struct sockaddr_storage *ss = (struct sockaddr_storage *)addr;
+ struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
+ int port;
+
+ if (ss->ss_family == AF_INET6)
+ port = ntohs(sin6->sin6_port);
+ else
+ port = ntohs(sin->sin_port);
+
+ snprintf(str_port_buf, sizeof(str_port_buf), "%d", port);
+ return str_port_buf;
+}
+
+/* clear out everything under nodes_dir */
+static int clear_configfs_nodes(void)
+{
+ char path[PATH_MAX];
+ DIR *d;
+ struct dirent *de;
+ int rv, failcount = 0;
+
+ d = opendir(nodes_dir);
+ if (!d) {
+ log_debug("%s: opendir failed: %d", nodes_dir, errno);
+ return -1;
+ }
+
+ while ((de = readdir(d))) {
+ if (de->d_name[0] == '.')
+ continue;
+ snprintf(path, PATH_MAX, "%s/%s", nodes_dir, de->d_name);
+
+ log_debug("clear_configfs_nodes rmdir \"%s\"", path);
+
+ rv = rmdir(path);
+ if (rv) {
+ log_error("%s: rmdir failed: %d", path, errno);
+ failcount++;
+ }
+ }
+ closedir(d);
+
+ return failcount;
+}
+
+
+
+#if 0
+static void clear_configfs_space_nodes(char *name)
+{
+ char path[PATH_MAX];
+ int i, rv;
+
+ rv = update_dir_members(name);
+ if (rv < 0)
+ return;
+
+ for (i = 0; i < dir_members_count; i++) {
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s/nodes/%d",
+ SPACES_DIR, name, dir_members[i]);
+
+ log_debug("clear_configfs_space_nodes rmdir \"%s\"", path);
+
+ rv = rmdir(path);
+ if (rv)
+ log_error("%s: rmdir failed: %d", path, errno);
+ }
+}
+
+/* clear out everything under config/dlm/cluster/spaces/ */
+
+void clear_configfs_spaces(void)
+{
+ char path[PATH_MAX];
+ DIR *d;
+ struct dirent *de;
+ int rv;
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s", SPACES_DIR);
+
+ d = opendir(path);
+ if (!d) {
+ log_debug("%s: opendir failed: %d", path, errno);
+ return;
+ }
+
+ while ((de = readdir(d))) {
+ if (de->d_name[0] == '.')
+ continue;
+
+ clear_configfs_space_nodes(de->d_name);
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s", SPACES_DIR, de->d_name);
+
+ log_debug("clear_configfs_spaces rmdir \"%s\"", path);
+
+ rv = rmdir(path);
+ if (rv)
+ log_error("%s: rmdir failed: %d", path, errno);
+ }
+ closedir(d);
+}
+#endif
+
+void clear_configfs(void)
+{
+ if (!cluster_dir[0] || !nodes_dir[0])
+ return;
+
+ if (!path_exists(cluster_dir) || !path_exists(nodes_dir))
+ return;
+
+ clear_configfs_nodes();
+#if 0
+ clear_configfs_spaces();
+#endif
+ rmdir(cluster_dir);
+}
+
+static int add_configfs_base(void)
+{
+ int rv = -1;
+ char *cluster_name;
+
+ if (!path_exists("/sys/kernel/config")) {
+ log_error("No /sys/kernel/config, is configfs loaded?");
+ goto out;
+ }
+
+ if (!path_exists("/sys/kernel/config/cluster")) {
+ log_error("No /sys/kernel/config/cluster, is ocfs2_nodemanager loaded?");
+ goto out;
+ }
+
+ if (!nodes_dir[0] || !cluster_dir[0]) {
+ cluster_name = get_cluster_name();
+ if (!cluster_name)
+ goto out;
+
+ snprintf(cluster_dir, PATH_MAX, CLUSTER_FORMAT,
+ cluster_name);
+ snprintf(nodes_dir, PATH_MAX, NODES_FORMAT, cluster_name);
+ }
+
+ if (!path_exists(cluster_dir)) {
+ rv = create_path(cluster_dir);
+ if (rv)
+ goto out;
+ }
+
+ if (!path_exists(nodes_dir)) {
+ log_error("Path %s exists, but %s does not. Is this really ocfs2_nodemanager?",
+ cluster_dir, nodes_dir);
+ rv = -1;
+ }
+
+out:
+ return rv;
+}
+
+static int do_set(const char *name, const char *attr, const char *val)
+{
+ char path[PATH_MAX];
+ int fd, rv;
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s/num", nodes_dir, name);
+
+ fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ log_error("%s: open failed: %d", path, errno);
+ return -1;
+ }
+
+ rv = do_write(fd, (char *)val, strlen(val));
+ if (rv < 0) {
+ log_error("%s: write failed: %d, %s", path, errno, val);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+
+ return 0;
+}
+
+int add_configfs_node(const char *name, int nodeid, char *addr, int addrlen,
+ int local)
+{
+ char path[PATH_MAX];
+ char buf[32];
+ int rv;
+
+ log_debug("add_configfs_node %s %d %s local %d",
+ name, nodeid, str_ip(addr), local);
+
+ rv = add_configfs_base();
+ if (rv < 0)
+ return rv;
+
+ /*
+ * create comm dir for this node
+ */
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s", nodes_dir, name);
+
+ rv = create_path(path);
+ if (rv)
+ return -1;
+
+ /*
+ * set the nodeid
+ */
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, 32, "%d", nodeid);
+ rv = do_set(name, "num", buf);
+ if (rv < 0)
+ return -1;
+
+ /*
+ * set the address
+ */
+
+ rv = do_set(name, "ipv4_addr", str_ip(addr));
+ if (rv < 0)
+ return -1;
+
+ /*
+ * set the port
+ */
+
+ rv = do_set(name, "ipv4_port", str_port(addr));
+ if (rv < 0)
+ return -1;
+
+ /*
+ * set local
+ */
+
+ if (local) {
+ rv = do_set(name, "local", "1");
+ if (rv < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+void del_configfs_node(const char *name)
+{
+ char path[PATH_MAX];
+ int rv;
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s", nodes_dir, name);
+
+ log_debug("del_configfs_node rmdir \"%s\"", path);
+
+ rv = rmdir(path);
+ if (rv)
+ log_error("%s: rmdir failed: %d", path, errno);
+}
+
+#if 0
+#define PROTOCOL_PATH "/cluster/dlm/@protocol"
+#define PROTO_TCP 1
+#define PROTO_SCTP 2
+
+static int get_ccs_protocol(int cd)
+{
+ char path[PATH_MAX], *str;
+ int error, rv;
+
+ memset(path, 0, PATH_MAX);
+ sprintf(path, PROTOCOL_PATH);
+
+ error = ccs_get(cd, path, &str);
+ if (error || !str)
+ return -1;
+
+ if (!strncasecmp(str, "tcp", 3))
+ rv = PROTO_TCP;
+ else if (!strncasecmp(str, "sctp", 4))
+ rv = PROTO_SCTP;
+ else {
+ log_error("read invalid dlm protocol from ccs");
+ rv = 0;
+ }
+
+ free(str);
+ log_debug("got ccs protocol %d", rv);
+ return rv;
+}
+
+#define TIMEWARN_PATH "/cluster/dlm/@timewarn"
+
+static int get_ccs_timewarn(int cd)
+{
+ char path[PATH_MAX], *str;
+ int error, rv;
+
+ memset(path, 0, PATH_MAX);
+ sprintf(path, TIMEWARN_PATH);
+
+ error = ccs_get(cd, path, &str);
+ if (error || !str)
+ return -1;
+
+ rv = atoi(str);
+
+ if (rv <= 0) {
+ log_error("read invalid dlm timewarn from ccs");
+ rv = -1;
+ }
+
+ free(str);
+ log_debug("got ccs timewarn %d", rv);
+ return rv;
+}
+
+#define DEBUG_PATH "/cluster/dlm/@log_debug"
+
+static int get_ccs_debug(int cd)
+{
+ char path[PATH_MAX], *str;
+ int error, rv;
+
+ memset(path, 0, PATH_MAX);
+ sprintf(path, DEBUG_PATH);
+
+ error = ccs_get(cd, path, &str);
+ if (error || !str)
+ return -1;
+
+ rv = atoi(str);
+
+ if (rv < 0) {
+ log_error("read invalid dlm log_debug from ccs");
+ rv = -1;
+ }
+
+ free(str);
+ log_debug("got ccs log_debug %d", rv);
+ return rv;
+}
+
+static int set_configfs_protocol(int proto)
+{
+ char path[PATH_MAX];
+ char buf[32];
+ int fd, rv;
+
+ rv = add_configfs_base();
+ if (rv < 0)
+ return rv;
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/protocol", CLUSTER_DIR);
+
+ fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ log_error("%s: open failed: %d", path, errno);
+ return fd;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, 32, "%d", proto);
+
+ rv = do_write(fd, buf, strlen(buf));
+ if (rv < 0) {
+ log_error("%s: write failed: %d", path, errno);
+ return rv;
+ }
+ close(fd);
+ log_debug("set protocol %d", proto);
+ return 0;
+}
+
+static int set_configfs_timewarn(int cs)
+{
+ char path[PATH_MAX];
+ char buf[32];
+ int fd, rv;
+
+ rv = add_configfs_base();
+ if (rv < 0)
+ return rv;
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/timewarn_cs", CLUSTER_DIR);
+
+ fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ log_error("%s: open failed: %d", path, errno);
+ return fd;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, 32, "%d", cs);
+
+ rv = do_write(fd, buf, strlen(buf));
+ if (rv < 0) {
+ log_error("%s: write failed: %d", path, errno);
+ return rv;
+ }
+ close(fd);
+ log_debug("set timewarn_cs %d", cs);
+ return 0;
+}
+
+static int set_configfs_debug(int val)
+{
+ char path[PATH_MAX];
+ char buf[32];
+ int fd, rv;
+
+ rv = add_configfs_base();
+ if (rv < 0)
+ return rv;
+
+ memset(path, 0, PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/log_debug", CLUSTER_DIR);
+
+ fd = open(path, O_WRONLY);
+ if (fd < 0) {
+ log_error("%s: open failed: %d", path, errno);
+ return fd;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, 32, "%d", val);
+
+ rv = do_write(fd, buf, strlen(buf));
+ if (rv < 0) {
+ log_error("%s: write failed: %d", path, errno);
+ return rv;
+ }
+ close(fd);
+ log_debug("set log_debug %d", val);
+ return 0;
+}
+
+static void set_protocol(int cd)
+{
+ int rv, proto;
+
+ rv = get_ccs_protocol(cd);
+ if (!rv || rv < 0)
+ return;
+
+ /* for dlm kernel, TCP=0 and SCTP=1 */
+ if (rv == PROTO_TCP)
+ proto = 0;
+ else if (rv == PROTO_SCTP)
+ proto = 1;
+ else
+ return;
+
+ set_configfs_protocol(proto);
+}
+
+static void set_timewarn(int cd)
+{
+ int rv;
+
+ rv = get_ccs_timewarn(cd);
+ if (rv < 0)
+ return;
+
+ set_configfs_timewarn(rv);
+}
+
+static void set_debug(int cd)
+{
+ int rv;
+
+ rv = get_ccs_debug(cd);
+ if (rv < 0)
+ return;
+
+ set_configfs_debug(rv);
+}
+
+void set_ccs_options(void)
+{
+ int cd;
+
+ cd = open_ccs();
+
+ log_debug("set_ccs_options %d", cd);
+
+ set_protocol(cd);
+ set_timewarn(cd);
+ set_debug(cd);
+
+ ccs_disconnect(cd);
+}
+#endif
Added: branches/cman-based/o2cb_controld/main.c
===================================================================
--- branches/cman-based/o2cb_controld/main.c 2007-07-16 07:30:23 UTC (rev 1362)
+++ branches/cman-based/o2cb_controld/main.c 2007-07-16 07:31:49 UTC (rev 1363)
@@ -0,0 +1,262 @@
+/******************************************************************************
+*******************************************************************************
+**
+** 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.
+ */
+
+#include "o2cb_controld.h"
+
+#define OPTION_STRING "DhV"
+#define LOCKFILE_NAME "/var/run/o2cb_controld.pid"
+
+#if 0
+static int uevent_fd;
+#endif
+static int member_fd;
+
+static void sigterm_handler(int sig)
+{
+ clear_configfs();
+}
+
+static int loop(void)
+{
+ struct pollfd *pollfd;
+ int rv, i, maxi;
+
+ pollfd = malloc(MAXCON * sizeof(struct pollfd));
+ if (!pollfd)
+ return -1;
+
+ rv = member_fd = setup_member();
+ if (rv < 0)
+ goto out;
+ pollfd[0].fd = member_fd;
+ pollfd[0].events = POLLIN;
+
+ maxi = 0;
+
+ for (;;) {
+ rv = poll(pollfd, maxi + 1, -1);
+ if (rv == -1 && errno == EINTR)
+ continue;
+ if (rv < 0) {
+ log_error("poll errno %d", errno);
+ goto out;
+ }
+
+ for (i = 0; i <= maxi; i++) {
+ if (pollfd[i].revents & POLLIN) {
+ if (pollfd[i].fd == member_fd)
+ process_member();
+ }
+
+ if (pollfd[i].revents & POLLHUP) {
+ if (pollfd[i].fd == member_fd) {
+ log_error("cluster is down, exiting");
+ clear_configfs();
+ exit(1);
+ }
+ log_debug("closing fd %d", pollfd[i].fd);
+ close(pollfd[i].fd);
+ }
+ }
+ }
+ rv = 0;
+ out:
+ free(pollfd);
+ return rv;
+}
+
+static void lockfile(void)
+{
+ int fd, error;
+ struct flock lock;
+ char buf[33];
+
+ memset(buf, 0, 33);
+
+ fd = open(LOCKFILE_NAME, O_CREAT|O_WRONLY,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (fd < 0) {
+ fprintf(stderr, "cannot open/create lock file %s\n",
+ LOCKFILE_NAME);
+ exit(EXIT_FAILURE);
+ }
+
+ lock.l_type = F_WRLCK;
+ lock.l_start = 0;
+ lock.l_whence = SEEK_SET;
+ lock.l_len = 0;
+
+ error = fcntl(fd, F_SETLK, &lock);
+ if (error) {
+ fprintf(stderr, "o2cb_controld is already running\n");
+ exit(EXIT_FAILURE);
+ }
+
+ error = ftruncate(fd, 0);
+ if (error) {
+ fprintf(stderr, "cannot clear lock file %s\n", LOCKFILE_NAME);
+ exit(EXIT_FAILURE);
+ }
+
+ sprintf(buf, "%d\n", getpid());
+
+ error = write(fd, buf, strlen(buf));
+ if (error <= 0) {
+ fprintf(stderr, "cannot write lock file %s\n", LOCKFILE_NAME);
+ exit(EXIT_FAILURE);
+ }
+}
+
+static void daemonize(void)
+{
+ pid_t pid = fork();
+ if (pid < 0) {
+ perror("main: cannot fork");
+ exit(EXIT_FAILURE);
+ }
+ if (pid)
+ exit(EXIT_SUCCESS);
+ setsid();
+ chdir("/");
+ umask(0);
+ close(0);
+ close(1);
+ close(2);
+ openlog("o2cb_controld", LOG_PID, LOG_DAEMON);
+
+ lockfile();
+}
+
+static void print_usage(void)
+{
+ printf("Usage:\n");
+ printf("\n");
+ printf("%s [options]\n", prog_name);
+ printf("\n");
+ printf("Options:\n");
+ printf("\n");
+ printf(" -D Enable debugging code and don't fork\n");
+ printf(" -h Print this help, then exit\n");
+ printf(" -V Print program version information, then exit\n");
+}
+
+static void decode_arguments(int argc, char **argv)
+{
+ int cont = 1;
+ int optchar;
+
+ while (cont) {
+ optchar = getopt(argc, argv, OPTION_STRING);
+
+ switch (optchar) {
+
+ case 'D':
+ daemon_debug_opt = 1;
+ break;
+
+ case 'h':
+ print_usage();
+ exit(EXIT_SUCCESS);
+ break;
+
+ case 'V':
+ printf("o2cb_controld (built %s %s)\n", __DATE__, __TIME__);
+ /* printf("%s\n", REDHAT_COPYRIGHT); */
+ exit(EXIT_SUCCESS);
+ break;
+
+ case ':':
+ case '?':
+ fprintf(stderr, "Please use '-h' for usage.\n");
+ exit(EXIT_FAILURE);
+ break;
+
+ case EOF:
+ cont = 0;
+ break;
+
+ default:
+ fprintf(stderr, "unknown option: %c\n", optchar);
+ exit(EXIT_FAILURE);
+ break;
+ };
+ }
+}
+
+static void set_oom_adj(int val)
+{
+ FILE *fp;
+
+ fp = fopen("/proc/self/oom_adj", "w");
+ if (!fp)
+ return;
+
+ fprintf(fp, "%i", val);
+ fclose(fp);
+}
+
+static void set_scheduler(void)
+{
+ struct sched_param sched_param;
+ int rv;
+
+ rv = sched_get_priority_max(SCHED_RR);
+ if (rv != -1) {
+ sched_param.sched_priority = rv;
+ rv = sched_setscheduler(0, SCHED_RR, &sched_param);
+ if (rv == -1)
+ log_error("could not set SCHED_RR priority %d err %d",
+ sched_param.sched_priority, errno);
+ } else {
+ log_error("could not get maximum scheduler priority err %d",
+ errno);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ prog_name = argv[0];
+
+ decode_arguments(argc, argv);
+
+ if (!daemon_debug_opt)
+ daemonize();
+
+ signal(SIGTERM, sigterm_handler);
+
+ set_scheduler();
+ set_oom_adj(-16);
+
+ /* if this daemon was killed and the cluster shut down, and
+ then the cluster brought back up and this daemon restarted,
+ there will be old configfs entries we need to clear out */
+ clear_configfs();
+
+#if 0
+ set_ccs_options();
+#endif
+
+ return loop();
+}
+
+char *prog_name;
+int daemon_debug_opt;
+char daemon_debug_buf[256];
+
Added: branches/cman-based/o2cb_controld/member_cman.c
===================================================================
--- branches/cman-based/o2cb_controld/member_cman.c 2007-07-16 07:30:23 UTC (rev 1362)
+++ branches/cman-based/o2cb_controld/member_cman.c 2007-07-16 07:31:49 UTC (rev 1363)
@@ -0,0 +1,219 @@
+/******************************************************************************
+*******************************************************************************
+**
+** 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.
+ */
+
+#include <inttypes.h>
+#include <libcman.h>
+#include "o2cb_controld.h"
+
+static cman_handle_t ch;
+static cman_node_t old_nodes[MAX_NODES];
+static int old_node_count;
+static cman_node_t cman_nodes[MAX_NODES];
+static int cman_node_count;
+static int local_nodeid;
+extern struct list_head lockspaces;
+
+
+static int is_member(cman_node_t *node_list, int count, int nodeid)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (node_list[i].cn_nodeid == nodeid)
+ return node_list[i].cn_member;
+ }
+ return 0;
+}
+
+static int is_old_member(int nodeid)
+{
+ return is_member(old_nodes, old_node_count, nodeid);
+}
+
+int is_cman_member(int nodeid)
+{
+ return is_member(cman_nodes, cman_node_count, nodeid);
+}
+
+static cman_node_t *find_cman_node(int nodeid)
+{
+ int i;
+
+ for (i = 0; i < cman_node_count; i++) {
+ if (cman_nodes[i].cn_nodeid == nodeid)
+ return &cman_nodes[i];
+ }
+ return NULL;
+}
+
+char *nodeid2name(int nodeid)
+{
+ cman_node_t *cn;
+
+ cn = find_cman_node(nodeid);
+ if (!cn)
+ return NULL;
+ return cn->cn_name;
+}
+
+/* add a configfs dir for cluster members that don't have one,
+ del the configfs dir for cluster members that are now gone */
+
+static void statechange(void)
+{
+ int i, rv;
+
+ old_node_count = cman_node_count;
+ memcpy(&old_nodes, &cman_nodes, sizeof(old_nodes));
+
+ cman_node_count = 0;
+ memset(&cman_nodes, 0, sizeof(cman_nodes));
+ rv = cman_get_nodes(ch, MAX_NODES, &cman_node_count, cman_nodes);
+ if (rv < 0) {
+ log_debug("cman_get_nodes error %d %d", rv, errno);
+ return;
+ }
+
+ for (i = 0; i < old_node_count; i++) {
+ if (old_nodes[i].cn_member &&
+ !is_cman_member(old_nodes[i].cn_nodeid)) {
+
+ log_debug("cman: node %d removed",
+ old_nodes[i].cn_nodeid);
+
+ del_configfs_node(old_nodes[i].cn_name);
+ }
+ }
+
+ for (i = 0; i < cman_node_count; i++) {
+ if (cman_nodes[i].cn_member &&
+ !is_old_member(cman_nodes[i].cn_nodeid)) {
+
+ log_debug("cman: node %d added",
+ cman_nodes[i].cn_nodeid);
+
+ add_configfs_node(cman_nodes[i].cn_name,
+ cman_nodes[i].cn_nodeid,
+ cman_nodes[i].cn_address.cna_address,
+ cman_nodes[i].cn_address.cna_addrlen,
+ (cman_nodes[i].cn_nodeid ==
+ local_nodeid));
+ }
+ }
+}
+
+char *get_cluster_name(void)
+{
+ int rv;
+ static cman_cluster_t cluster;
+
+ rv = cman_get_cluster(ch, &cluster);
+ if (rv < 0 ) {
+ log_error("cman_get_cluster error %d, %d", rv, errno);
+ return NULL;
+ }
+
+ return cluster.ci_name;
+}
+
+static void member_callback(cman_handle_t h, void *private, int reason, int arg)
+{
+ switch (reason) {
+ case CMAN_REASON_TRY_SHUTDOWN:
+#if 0
+ if (list_empty(&lockspaces))
+#endif
+ cman_replyto_shutdown(ch, 1);
+#if 0
+ else {
+ log_debug("no to cman shutdown");
+ cman_replyto_shutdown(ch, 0);
+ }
+#endif
+ break;
+ case CMAN_REASON_STATECHANGE:
+ statechange();
+ break;
+ }
+}
+
+int process_member(void)
+{
+ int rv;
+
+ rv = cman_dispatch(ch, CMAN_DISPATCH_ALL);
+ if (rv == -1 && errno == EHOSTDOWN) {
+ /* do we want to try to forcibly clean some stuff up
+ in the kernel here? */
+ log_error("cluster is down, exiting");
+ clear_configfs();
+ exit(1);
+ }
+ return 0;
+}
+
+int setup_member(void)
+{
+ cman_node_t node;
+ int rv, fd;
+
+ ch = cman_init(NULL);
+ if (!ch) {
+ log_error("cman_init error %d %d", (int) ch, errno);
+ return -ENOTCONN;
+ }
+
+ rv = cman_start_notification(ch, member_callback);
+ if (rv < 0) {
+ log_error("cman_start_notification error %d %d", rv, errno);
+ cman_finish(ch);
+ return rv;
+ }
+
+ fd = cman_get_fd(ch);
+
+ /* FIXME: wait here for us to be a member of the cluster */
+ memset(&node, 0, sizeof(node));
+ rv = cman_get_node(ch, CMAN_NODEID_US, &node);
+ if (rv < 0) {
+ log_error("cman_get_node us error %d %d", rv, errno);
+ cman_stop_notification(ch);
+ cman_finish(ch);
+ fd = rv;
+ goto out;
+ }
+ local_nodeid = node.cn_nodeid;
+
+ old_node_count = 0;
+ memset(&old_nodes, 0, sizeof(old_nodes));
+ cman_node_count = 0;
+ memset(&cman_nodes, 0, sizeof(cman_nodes));
+
+ /* add configfs entries for existing nodes */
+ statechange();
+ out:
+ return fd;
+}
+
+/* Force re-read of cman nodes */
+void cman_statechange()
+{
+ statechange();
+}
Added: branches/cman-based/o2cb_controld/o2cb_controld.h
===================================================================
--- branches/cman-based/o2cb_controld/o2cb_controld.h 2007-07-16 07:30:23 UTC (rev 1362)
+++ branches/cman-based/o2cb_controld/o2cb_controld.h 2007-07-16 07:31:49 UTC (rev 1363)
@@ -0,0 +1,92 @@
+/******************************************************************************
+*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************
+******************************************************************************/
+
+#ifndef __O2CB_CONTROLD_H__
+#define __O2CB_CONTROLD_H__
+
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <limits.h>
+#include <unistd.h>
+#include <time.h>
+#include <syslog.h>
+#include <sched.h>
+#include <signal.h>
+#include <linux/netlink.h>
+
+
+#define MAXARGS 8
+#define MAXLINE 256
+#define MAXCON 4
+#define MAXNAME 255
+#define MAX_NODES 256 /* should be same as MAX_GROUP_MEMBERS */
+
+extern char *prog_name;
+extern int daemon_debug_opt;
+extern int kernel_debug_opt;
+extern char daemon_debug_buf[256];
+
+#define log_debug(fmt, args...) \
+do { \
+ snprintf(daemon_debug_buf, 255, "%ld " fmt "\n", time(NULL), ##args); \
+ if (daemon_debug_opt) fprintf(stderr, "%s", daemon_debug_buf); \
+} while (0)
+
+#define log_error(fmt, args...) \
+do { \
+ log_debug(fmt, ##args); \
+ syslog(LOG_ERR, fmt, ##args); \
+} while (0)
+
+
+/* action.c */
+int set_control(char *name, int val);
+int set_event_done(char *name, int val);
+int add_configfs_node(const char *name, int nodeid, char *addr, int addrlen,
+ int local);
+void del_configfs_node(const char *name);
+void clear_configfs(void);
+int set_members(char *name, int new_count, int *new_members);
+int set_id(char *name, uint32_t id);
+void set_ccs_options(void);
+
+/* member_xxx.c */
+int setup_member(void);
+int process_member(void);
+char *nodeid2name(int nodeid);
+char *get_cluster_name(void);
+
+/* member_cman.c */
+int is_cman_member(int nodeid);
+void cman_statechange(void);
+
+#endif
+
More information about the Ocfs2-tools-commits
mailing list