[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