[Ocfs2-tools-commits] jlbec commits r1368 - in branches/cman-based:
. o2cb_controld ocfs2_controld
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Tue Jul 17 17:21:29 PDT 2007
Author: jlbec
Date: 2007-07-17 17:21:27 -0700 (Tue, 17 Jul 2007)
New Revision: 1368
Added:
branches/cman-based/ocfs2_controld/
branches/cman-based/ocfs2_controld/Makefile
branches/cman-based/ocfs2_controld/group.c
branches/cman-based/ocfs2_controld/main.c
branches/cman-based/ocfs2_controld/member_cman.c
branches/cman-based/ocfs2_controld/ocfs2_controld.h
Modified:
branches/cman-based/Makefile
branches/cman-based/o2cb_controld/member_cman.c
Log:
Add the ocfs2_controld skeleton. It doesn't compile, but I want the
original code in source control so we can compare it later.
Modified: branches/cman-based/Makefile
===================================================================
--- branches/cman-based/Makefile 2007-07-16 23:28:31 UTC (rev 1367)
+++ branches/cman-based/Makefile 2007-07-18 00:21:27 UTC (rev 1368)
@@ -31,7 +31,7 @@
endif
ifdef BUILD_CMAN_SUPPORT
-SUBDIRS += o2cb_controld
+SUBDIRS += o2cb_controld # ocfs2_controld
endif
SUBDIRS += vendor
Modified: branches/cman-based/o2cb_controld/member_cman.c
===================================================================
--- branches/cman-based/o2cb_controld/member_cman.c 2007-07-16 23:28:31 UTC (rev 1367)
+++ branches/cman-based/o2cb_controld/member_cman.c 2007-07-18 00:21:27 UTC (rev 1368)
@@ -145,7 +145,7 @@
{
switch (reason) {
case CMAN_REASON_TRY_SHUTDOWN:
- /* XXX we need to check heartbeat here */
+ /* XXX do we need to check heartbeat here */
#if 0
if (list_empty(&lockspaces))
#endif
Added: branches/cman-based/ocfs2_controld/Makefile
===================================================================
--- branches/cman-based/ocfs2_controld/Makefile 2007-07-16 23:28:31 UTC (rev 1367)
+++ branches/cman-based/ocfs2_controld/Makefile 2007-07-18 00:21:27 UTC (rev 1368)
@@ -0,0 +1,42 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+SBIN_PROGRAMS = ocfs2_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 member_cman.c group.c
+
+
+HFILES = ocfs2_controld.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/ocfs2_controld/group.c
===================================================================
--- branches/cman-based/ocfs2_controld/group.c 2007-07-16 23:28:31 UTC (rev 1367)
+++ branches/cman-based/ocfs2_controld/group.c 2007-07-18 00:21:27 UTC (rev 1368)
@@ -0,0 +1,204 @@
+/* -*- 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 "ocfs2_controld.h"
+
+#define OCFS2_CONTROLD_GROUP_NAME "ocfs2"
+#define OCFS2_CONTROLD_GROUP_LEVEL 2 /* Because gfs_controld uses 2.
+ I think all that matters is that
+ we are a higher number than
+ fenced, which uses 0. */
+
+
+/* save all the params from callback functions here because we can't
+ do the processing within the callback function itself */
+
+group_handle_t gh;
+static int cb_action;
+static char cb_name[MAX_GROUP_NAME_LEN+1];
+static int cb_event_nr;
+static unsigned int cb_id;
+static int cb_type;
+static int cb_member_count;
+static int cb_members[MAX_GROUP_MEMBERS];
+
+int do_stop(struct mountgroup *mg);
+int do_finish(struct mountgroup *mg);
+int do_terminate(struct mountgroup *mg);
+int do_start(struct mountgroup *mg, int type, int count, int *nodeids);
+
+
+static void stop_cbfn(group_handle_t h, void *private, char *name)
+{
+ cb_action = DO_STOP;
+ strcpy(cb_name, name);
+}
+
+static void start_cbfn(group_handle_t h, void *private, char *name,
+ int event_nr, int type, int member_count, int *members)
+{
+ int i;
+
+ cb_action = DO_START;
+ strncpy(cb_name, name, MAX_GROUP_NAME_LEN);
+ cb_event_nr = event_nr;
+ cb_type = type;
+ cb_member_count = member_count;
+
+ for (i = 0; i < member_count; i++)
+ cb_members[i] = members[i];
+}
+
+static void finish_cbfn(group_handle_t h, void *private, char *name,
+ int event_nr)
+{
+ cb_action = DO_FINISH;
+ strncpy(cb_name, name, MAX_GROUP_NAME_LEN);
+ cb_event_nr = event_nr;
+}
+
+static void terminate_cbfn(group_handle_t h, void *private, char *name)
+{
+ cb_action = DO_TERMINATE;
+ strncpy(cb_name, name, MAX_GROUP_NAME_LEN);
+}
+
+static void setid_cbfn(group_handle_t h, void *private, char *name,
+ unsigned int id)
+{
+ cb_action = DO_SETID;
+ strncpy(cb_name, name, MAX_GROUP_NAME_LEN);
+ cb_id = id;
+}
+
+static void deliver_cbfn(group_handle_t h, void *private, char *name,
+ int nodeid, int len, char *buf)
+{
+}
+
+static group_callbacks_t callbacks = {
+ stop_cbfn,
+ start_cbfn,
+ finish_cbfn,
+ terminate_cbfn,
+ setid_cbfn,
+ deliver_cbfn
+};
+
+char *str_members(void)
+{
+ static char buf[MAXLINE];
+ int i, len = 0;
+
+ memset(buf, 0, MAXLINE);
+
+ for (i = 0; i < cb_member_count; i++)
+ len += sprintf(buf+len, "%d ", cb_members[i]);
+ return buf;
+}
+
+int process_groupd(void)
+{
+ struct mountgroup *mg;
+ int error = 0;
+
+ error = group_dispatch(gh);
+ if (error) {
+ log_error("groupd_dispatch error %d errno %d", error, errno);
+ goto out;
+ }
+
+ if (!cb_action)
+ goto out;
+
+ mg = find_mg(cb_name);
+ if (!mg) {
+ log_error("callback %d group %s not found", cb_action, cb_name);
+ error = -1;
+ goto out;
+ }
+
+ switch (cb_action) {
+ case DO_STOP:
+ log_debug("groupd cb: stop %s", cb_name);
+ mg->last_callback = DO_STOP;
+ mg->last_stop = mg->last_start;
+ do_stop(mg);
+ break;
+
+ case DO_START:
+ log_debug("groupd cb: start %s type %d count %d members %s",
+ cb_name, cb_type, cb_member_count, str_members());
+ mg->last_callback = DO_START;
+ mg->last_start = cb_event_nr;
+ do_start(mg, cb_type, cb_member_count, cb_members);
+ break;
+
+ case DO_FINISH:
+ log_debug("groupd cb: finish %s", cb_name);
+ mg->last_callback = DO_FINISH;
+ mg->last_finish = cb_event_nr;
+ do_finish(mg);
+ break;
+
+ case DO_TERMINATE:
+ log_debug("groupd cb: terminate %s", cb_name);
+ mg->last_callback = DO_TERMINATE;
+ do_terminate(mg);
+ break;
+
+ case DO_SETID:
+ log_debug("groupd cb: set_id %s %x", cb_name, cb_id);
+ mg->id = cb_id;
+ break;
+
+ default:
+ error = -EINVAL;
+ }
+
+ out:
+ cb_action = 0;
+ return error;
+}
+
+int setup_groupd(void)
+{
+ int rv;
+
+ gh = group_init(NULL, OCFS2_CONTROLD_GROUP_NAME,
+ OCFS2_CONTROLD_GROUP_LEVEL, &callbacks, 10);
+ if (!gh) {
+ log_error("group_init error %d %d", (int) gh, errno);
+ return -ENOTCONN;
+ }
+
+ rv = group_get_fd(gh);
+ if (rv < 0)
+ log_error("group_get_fd error %d %d", rv, errno);
+
+ log_debug("groupd %d", rv);
+
+ return rv;
+}
+
Added: branches/cman-based/ocfs2_controld/main.c
===================================================================
--- branches/cman-based/ocfs2_controld/main.c 2007-07-16 23:28:31 UTC (rev 1367)
+++ branches/cman-based/ocfs2_controld/main.c 2007-07-18 00:21:27 UTC (rev 1368)
@@ -0,0 +1,780 @@
+/* -*- 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 "ocfs2_controld.h"
+
+#define OPTION_STRING "DPhVwpl:"
+#define LOCKFILE_NAME "/var/run/gfs_controld.pid"
+
+#define DEFAULT_PLOCK_RATE_LIMIT 100
+
+struct client {
+ int fd;
+ char type[32];
+ struct mountgroup *mg;
+ int another_mount;
+};
+
+static int client_maxi;
+static int client_size = 0;
+static struct client *client = NULL;
+static struct pollfd *pollfd = NULL;
+
+static int cman_fd;
+static int cpg_fd;
+static int listen_fd;
+static int groupd_fd;
+static int uevent_fd;
+static int plocks_fd;
+static int plocks_ci;
+
+extern struct list_head mounts;
+extern struct list_head withdrawn_mounts;
+int no_withdraw;
+int no_plock;
+uint32_t plock_rate_limit = DEFAULT_PLOCK_RATE_LIMIT;
+int dmsetup_wait;
+
+int do_read(int fd, void *buf, size_t count)
+{
+ int rv, off = 0;
+
+ while (off < count) {
+ rv = read(fd, buf + off, count - off);
+ if (rv == 0)
+ return -1;
+ if (rv == -1 && errno == EINTR)
+ continue;
+ if (rv == -1)
+ return -1;
+ off += rv;
+ }
+ return 0;
+}
+
+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 void make_args(char *buf, int *argc, char **argv, char sep)
+{
+ char *p = buf;
+ int i;
+
+ argv[0] = p;
+
+ for (i = 1; i < MAXARGS; i++) {
+ p = strchr(buf, sep);
+ if (!p)
+ break;
+ *p = '\0';
+ argv[i] = p + 1;
+ buf = p + 1;
+ }
+ *argc = i;
+}
+#endif
+
+static char *get_args(char *buf, int *argc, char **argv, char sep, int want)
+{
+ char *p = buf, *rp = NULL;
+ int i;
+
+ argv[0] = p;
+
+ for (i = 1; i < MAXARGS; i++) {
+ p = strchr(buf, sep);
+ if (!p)
+ break;
+ *p = '\0';
+
+ if (want == i) {
+ rp = p + 1;
+ break;
+ }
+
+ argv[i] = p + 1;
+ buf = p + 1;
+ }
+ *argc = i;
+
+ /* we ended by hitting \0, return the point following that */
+ if (!rp)
+ rp = strchr(buf, '\0') + 1;
+
+ return rp;
+}
+
+static int client_add(int fd)
+{
+ int i;
+
+ while (1) {
+ /* This fails the first time with client_size of zero */
+ for (i = 0; i < client_size; i++) {
+ if (client[i].fd == -1) {
+ client[i].fd = fd;
+ pollfd[i].fd = fd;
+ pollfd[i].events = POLLIN;
+ if (i > client_maxi)
+ client_maxi = i;
+ return i;
+ }
+ }
+
+ /* We didn't find an empty slot, so allocate more. */
+ client_size += MAX_CLIENTS;
+
+ if (!client) {
+ client = malloc(client_size * sizeof(struct client));
+ pollfd = malloc(client_size * sizeof(struct pollfd));
+ } else {
+ client = realloc(client, client_size *
+ sizeof(struct client));
+ pollfd = realloc(pollfd, client_size *
+ sizeof(struct pollfd));
+ }
+ if (!client || !pollfd)
+ log_error("Can't allocate client memory.");
+
+ for (i = client_size - MAX_CLIENTS; i < client_size; i++) {
+ client[i].fd = -1;
+ pollfd[i].fd = -1;
+ }
+ }
+}
+
+static void client_dead(int ci)
+{
+ log_debug("client %d fd %d dead", ci, client[ci].fd);
+ close(client[ci].fd);
+ client[ci].fd = -1;
+ pollfd[ci].fd = -1;
+ client[ci].mg = NULL;
+}
+
+static void client_ignore(int ci, int fd)
+{
+ pollfd[ci].fd = -1;
+ pollfd[ci].events = 0;
+}
+
+static void client_back(int ci, int fd)
+{
+ pollfd[ci].fd = fd;
+ pollfd[ci].events = POLLIN;
+}
+
+int client_send(int ci, char *buf, int len)
+{
+ return do_write(client[ci].fd, buf, len);
+}
+
+static int dump_debug(int ci)
+{
+ int len = DUMP_SIZE;
+
+ if (dump_wrap) {
+ len = DUMP_SIZE - dump_point;
+ do_write(client[ci].fd, dump_buf + dump_point, len);
+ len = dump_point;
+ }
+
+ do_write(client[ci].fd, dump_buf, len);
+ return 0;
+}
+
+#if 0
+/* mount.gfs sends us a special fd that it will write an error message to
+ if mount(2) fails. We can monitor this fd for an error message while
+ waiting for the kernel mount outside our main poll loop */
+
+void setup_mount_error_fd(struct mountgroup *mg)
+{
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec vec;
+ char tmp[CMSG_SPACE(sizeof(int))];
+ int fd, socket = client[mg->mount_client].fd;
+ char ch;
+ ssize_t n;
+
+ memset(&msg, 0, sizeof(msg));
+
+ vec.iov_base = &ch;
+ vec.iov_len = 1;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+ msg.msg_control = tmp;
+ msg.msg_controllen = sizeof(tmp);
+
+ n = recvmsg(socket, &msg, 0);
+ if (n < 0) {
+ log_group(mg, "setup_mount_error_fd recvmsg err %d errno %d",
+ n, errno);
+ return;
+ }
+ if (n != 1) {
+ log_group(mg, "setup_mount_error_fd recvmsg got %ld", (long)n);
+ return;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+
+ if (cmsg->cmsg_type != SCM_RIGHTS) {
+ log_group(mg, "setup_mount_error_fd expected type %d got %d",
+ SCM_RIGHTS, cmsg->cmsg_type);
+ return;
+ }
+
+ fd = (*(int *)CMSG_DATA(cmsg));
+ mg->mount_error_fd = fd;
+
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
+
+ log_group(mg, "setup_mount_error_fd got fd %d", fd);
+}
+#endif
+
+static int process_client(int ci)
+{
+ struct mountgroup *mg;
+ char buf[MAXLINE], *argv[MAXARGS], out[MAXLINE];
+ char *cmd = NULL;
+ int argc = 0, rv, fd;
+
+ memset(buf, 0, MAXLINE);
+ memset(out, 0, MAXLINE);
+ memset(argv, 0, sizeof(char *) * MAXARGS);
+
+ rv = read(client[ci].fd, buf, MAXLINE);
+ if (!rv) {
+ client_dead(ci);
+ return 0;
+ }
+ if (rv < 0) {
+ log_debug("client %d fd %d read error %d %d", ci,
+ client[ci].fd, rv, errno);
+ return rv;
+ }
+
+ log_debug("client %d: %s", ci, buf);
+
+ get_args(buf, &argc, argv, ' ', 7);
+ cmd = argv[0];
+ rv = 0;
+
+ if (!strcmp(cmd, "join")) {
+ /* ci, dir (mountpoint), type (gfs/gfs2), proto (lock_dlm),
+ table (fsname:clustername), extra (rw), dev (/dev/sda1) */
+
+ rv = do_mount(ci, argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], &mg);
+ fd = client[ci].fd;
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
+ if (!rv || rv == -EALREADY) {
+ client[ci].another_mount = rv;
+ client[ci].mg = mg;
+ mg->mount_client_fd = fd;
+ }
+ goto reply;
+ } else if (!strcmp(cmd, "mount_result")) {
+ got_mount_result(client[ci].mg, atoi(argv[3]), ci,
+ client[ci].another_mount);
+ } else if (!strcmp(cmd, "leave")) {
+ rv = do_unmount(ci, argv[1], atoi(argv[3]));
+ goto reply;
+
+ } else if (!strcmp(cmd, "remount")) {
+ rv = do_remount(ci, argv[1], argv[3]);
+ goto reply;
+
+ } else if (!strcmp(cmd, "dump")) {
+ dump_debug(ci);
+
+ } else if (!strcmp(cmd, "plocks")) {
+ dump_plocks(argv[1], client[ci].fd);
+ client_dead(ci);
+
+ } else {
+ rv = -EINVAL;
+ goto reply;
+ }
+
+ return rv;
+
+ reply:
+ sprintf(out, "%d", rv);
+ rv = client_send(ci, out, MAXLINE);
+ return rv;
+}
+
+static int setup_listen(void)
+{
+ 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], OCFS2_CONTROLD_SOCK_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 process_uevent(void)
+{
+ char buf[MAXLINE];
+ char *argv[MAXARGS], *act;
+ int rv, argc = 0;
+
+ memset(buf, 0, sizeof(buf));
+ memset(argv, 0, sizeof(char *) * MAXARGS);
+
+ rv = recv(uevent_fd, &buf, sizeof(buf), 0);
+ if (rv < 0) {
+ log_error("uevent recv error %d errno %d", rv, errno);
+ return -1;
+ }
+
+ if (!strstr(buf, "gfs") || !strstr(buf, "lock_module"))
+ return 0;
+
+ get_args(buf, &argc, argv, '/', 4);
+ if (argc != 4)
+ log_error("uevent message has %d args", argc);
+ act = argv[0];
+
+ log_debug("kernel: %s %s", act, argv[3]);
+
+ if (!strcmp(act, "change@"))
+ kernel_recovery_done(argv[3]);
+ else if (!strcmp(act, "offline@"))
+ do_withdraw(argv[3]);
+ else
+ ping_kernel_mount(argv[3]);
+
+ return 0;
+}
+
+int setup_uevent(void)
+{
+ struct sockaddr_nl snl;
+ int s, rv;
+
+ s = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ if (s < 0) {
+ log_error("netlink socket error %d errno %d", s, errno);
+ return s;
+ }
+
+ memset(&snl, 0, sizeof(snl));
+ snl.nl_family = AF_NETLINK;
+ snl.nl_pid = getpid();
+ snl.nl_groups = 1;
+
+ rv = bind(s, (struct sockaddr *) &snl, sizeof(snl));
+ if (rv < 0) {
+ log_error("uevent bind error %d errno %d", rv, errno);
+ close(s);
+ return rv;
+ }
+
+ log_debug("uevent %d", s);
+
+ return s;
+}
+
+int loop(void)
+{
+ int rv, i, f, error, poll_timeout = -1, ignore_plocks_fd = 0;
+
+ rv = listen_fd = setup_listen();
+ if (rv < 0)
+ goto out;
+ client_add(listen_fd);
+
+ rv = cman_fd = setup_cman();
+ if (rv < 0)
+ goto out;
+ client_add(cman_fd);
+
+ rv = cpg_fd = setup_cpg();
+ if (rv < 0)
+ goto out;
+ client_add(cpg_fd);
+
+ rv = groupd_fd = setup_groupd();
+ if (rv < 0)
+ goto out;
+ client_add(groupd_fd);
+
+ rv = uevent_fd = setup_uevent();
+ if (rv < 0)
+ goto out;
+ client_add(uevent_fd);
+
+ rv = plocks_fd = setup_plocks();
+ if (rv < 0)
+ goto out;
+ plocks_ci = client_add(plocks_fd);
+
+ log_debug("setup done");
+
+ for (;;) {
+ rv = poll(pollfd, client_maxi + 1, poll_timeout);
+ if (rv < 0)
+ log_error("poll error %d errno %d", rv, errno);
+
+ /* client[0] is listening for new connections */
+
+ if (pollfd[0].revents & POLLIN) {
+ f = accept(client[0].fd, NULL, NULL);
+ if (f < 0)
+ log_debug("accept error %d %d", f, errno);
+ else
+ client_add(f);
+ }
+
+ for (i = 1; i <= client_maxi; i++) {
+ if (client[i].fd < 0)
+ continue;
+
+ if (pollfd[i].revents & POLLIN) {
+ if (pollfd[i].fd == groupd_fd)
+ process_groupd();
+ else if (pollfd[i].fd == cman_fd)
+ process_cman();
+ else if (pollfd[i].fd == cpg_fd)
+ process_cpg();
+ else if (pollfd[i].fd == uevent_fd)
+ process_uevent();
+ else if (pollfd[i].fd == plocks_fd) {
+ error = process_plocks();
+ if (error == -EBUSY) {
+ client_ignore(plocks_ci,
+ plocks_fd);
+ ignore_plocks_fd = 1;
+ poll_timeout = 100;
+ }
+ } else
+ process_client(i);
+ }
+
+ if (pollfd[i].revents & POLLHUP) {
+ if (pollfd[i].fd == cman_fd) {
+ log_error("cman connection died");
+ exit_cman();
+ } else if (pollfd[i].fd == groupd_fd) {
+ log_error("groupd connection died");
+ exit_cman();
+ } else if (pollfd[i].fd == cpg_fd) {
+ log_error("cpg connection died");
+ exit_cman();
+ }
+ client_dead(i);
+ }
+
+ /* check if our plock rate limit has expired so we
+ can start taking more local plock requests again */
+
+ if (ignore_plocks_fd) {
+ error = process_plocks();
+ if (error != -EBUSY) {
+ client_back(plocks_ci, plocks_fd);
+ ignore_plocks_fd = 0;
+ poll_timeout = -1;
+ }
+ }
+
+ if (dmsetup_wait) {
+ update_dmsetup_wait();
+ if (dmsetup_wait) {
+ if (poll_timeout == -1)
+ poll_timeout = 1000;
+ } else {
+ if (poll_timeout == 1000)
+ poll_timeout = -1;
+ }
+ }
+ }
+ }
+ rv = 0;
+ out:
+ 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, "gfs_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);
+ }
+}
+
+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("gfs_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(" -P Enable plock debugging\n");
+ printf(" -p Disable plocks\n");
+ printf(" -l <limit> Limit the rate of plock operations\n");
+ printf(" Default is %d, set to 0 for no limit\n", DEFAULT_PLOCK_RATE_LIMIT);
+ printf(" -w Disable withdraw\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 'w':
+ no_withdraw = 1;
+ break;
+
+ case 'D':
+ daemon_debug_opt = 1;
+ break;
+
+ case 'P':
+ plock_debug_opt = 1;
+ break;
+
+ case 'l':
+ plock_rate_limit = atoi(optarg);
+ break;
+
+ case 'p':
+ no_plock = 1;
+ break;
+
+ case 'h':
+ print_usage();
+ exit(EXIT_SUCCESS);
+ break;
+
+ case 'V':
+ printf("gfs_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;
+ };
+ }
+}
+
+void set_oom_adj(int val)
+{
+ FILE *fp;
+
+ fp = fopen("/proc/self/oom_adj", "w");
+ if (!fp)
+ return;
+
+ fprintf(fp, "%i", val);
+ fclose(fp);
+}
+
+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];
+ INIT_LIST_HEAD(&mounts);
+ INIT_LIST_HEAD(&withdrawn_mounts);
+
+ decode_arguments(argc, argv);
+
+ if (!daemon_debug_opt)
+ daemonize();
+
+ set_scheduler();
+ set_oom_adj(-16);
+
+ return loop();
+}
+
+void daemon_dump_save(void)
+{
+ int len, i;
+
+ len = strlen(daemon_debug_buf);
+
+ for (i = 0; i < len; i++) {
+ dump_buf[dump_point++] = daemon_debug_buf[i];
+
+ if (dump_point == DUMP_SIZE) {
+ dump_point = 0;
+ dump_wrap = 1;
+ }
+ }
+}
+
+char *prog_name;
+int plock_debug_opt;
+int daemon_debug_opt;
+char daemon_debug_buf[256];
+char dump_buf[DUMP_SIZE];
+int dump_point;
+int dump_wrap;
+
Added: branches/cman-based/ocfs2_controld/member_cman.c
===================================================================
--- branches/cman-based/ocfs2_controld/member_cman.c 2007-07-16 23:28:31 UTC (rev 1367)
+++ branches/cman-based/ocfs2_controld/member_cman.c 2007-07-18 00:21:27 UTC (rev 1368)
@@ -0,0 +1,118 @@
+/* -*- 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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <libcman.h>
+
+#include "ocfs2_controld.h"
+
+int our_nodeid;
+char * clustername;
+cman_cluster_t cluster;
+static cman_handle_t ch;
+extern struct list_head mounts;
+
+
+static void cman_callback(cman_handle_t h, void *private, int reason, int arg)
+{
+ if (reason == CMAN_REASON_TRY_SHUTDOWN) {
+ if (list_empty(&mounts))
+ cman_replyto_shutdown(ch, 1);
+ else {
+ log_debug("no to cman shutdown");
+ cman_replyto_shutdown(ch, 0);
+ }
+ }
+}
+
+void exit_cman(void)
+{
+ log_error("cluster is down, exiting");
+ exit(1);
+}
+
+int process_cman(void)
+{
+ int rv;
+
+ rv = cman_dispatch(ch, CMAN_DISPATCH_ALL);
+
+ if (rv == -1 && errno == EHOSTDOWN)
+ exit_cman();
+
+ return 0;
+}
+
+int setup_cman(void)
+{
+ cman_node_t node;
+ int rv, fd;
+
+ ch = cman_init(NULL);
+ if (!ch) {
+ log_error("cman_init error %d", errno);
+ return -ENOTCONN;
+ }
+
+ rv = cman_start_notification(ch, cman_callback);
+ if (rv < 0) {
+ log_error("cman_start_notification error %d %d", rv, errno);
+ goto fail_finish;
+ }
+
+ /* FIXME: wait here for us to be a member of the cluster */
+
+ memset(&cluster, 0, sizeof(cluster));
+ rv = cman_get_cluster(ch, &cluster);
+ if (rv < 0) {
+ log_error("cman_get_cluster error %d %d", rv, errno);
+ goto fail_stop;
+ }
+ clustername = cluster.ci_name;
+
+ memset(&node, 0, sizeof(node));
+ rv = cman_get_node(ch, CMAN_NODEID_US, &node);
+ if (rv < 0) {
+ log_error("cman_get_node error %d %d", rv, errno);
+ goto fail_stop;
+ }
+ our_nodeid = node.cn_nodeid;
+
+ fd = cman_get_fd(ch);
+ return fd;
+
+ fail_stop:
+ cman_stop_notification(ch);
+ fail_finish:
+ cman_finish(ch);
+ return rv;
+}
+
Added: branches/cman-based/ocfs2_controld/ocfs2_controld.h
===================================================================
--- branches/cman-based/ocfs2_controld/ocfs2_controld.h 2007-07-16 23:28:31 UTC (rev 1367)
+++ branches/cman-based/ocfs2_controld/ocfs2_controld.h 2007-07-18 00:21:27 UTC (rev 1368)
@@ -0,0 +1,313 @@
+/* -*- 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 __OCFS2_CONTROLD_H
+#define __OCFS2_CONTROLD_H
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <syslog.h>
+#include <sched.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/errno.h>
+#include <linux/netlink.h>
+
+#include "list.h"
+#include "linux_endian.h"
+#include "libgroup.h"
+
+#define MAXARGS 16
+#define MAXLINE 256
+#define MAXNAME 255
+#define MAX_CLIENTS 8
+#define MAX_MSGLEN 2048
+#define MAX_OPTIONS_LEN 1024
+#define DUMP_SIZE (1024 * 1024)
+
+#define OCFS2_CONTROLD_SOCK_PATH "ocfs2_controld_sock"
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+enum {
+ DO_STOP = 1,
+ DO_START,
+ DO_FINISH,
+ DO_TERMINATE,
+ DO_SETID,
+ DO_DELIVER,
+};
+
+extern char *prog_name;
+extern int daemon_debug_opt;
+extern char daemon_debug_buf[256];
+extern char dump_buf[DUMP_SIZE];
+extern int dump_point;
+extern int dump_wrap;
+
+extern void daemon_dump_save(void);
+
+#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); \
+ daemon_dump_save(); \
+} while (0)
+
+#define log_group(g, fmt, args...) \
+do { \
+ snprintf(daemon_debug_buf, 255, "%ld %s " fmt "\n", time(NULL), \
+ (g)->name, ##args); \
+ if (daemon_debug_opt) fprintf(stderr, "%s", daemon_debug_buf); \
+ daemon_dump_save(); \
+} while (0)
+
+#define log_plock(g, fmt, args...) \
+do { \
+ snprintf(daemon_debug_buf, 255, "%ld %s " fmt "\n", time(NULL), \
+ (g)->name, ##args); \
+ if (plock_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)
+
+#define ASSERT(x) \
+{ \
+ if (!(x)) { \
+ fprintf(stderr, "\nAssertion failed on line %d of file %s\n\n" \
+ "Assertion: \"%s\"\n", \
+ __LINE__, __FILE__, #x); \
+ } \
+}
+
+struct mountpoint {
+ struct list_head list;
+ char dir[PATH_MAX+1];
+ int client;
+};
+
+struct mountgroup {
+ struct list_head list;
+ uint32_t id;
+ struct list_head members;
+ struct list_head members_gone;
+ int memb_count;
+ struct list_head resources; /* for plocks */
+ struct list_head mountpoints;
+
+ char name[MAXNAME+1];
+ char table[MAXNAME+1];
+ char type[5];
+ char options[MAX_OPTIONS_LEN+1];
+ char dev[PATH_MAX+1];
+
+ int last_stop;
+ int last_start;
+ int last_finish;
+ int last_callback;
+ int start_event_nr;
+ int start_type;
+
+ char error_msg[128];
+ int mount_client;
+ int mount_client_fd;
+ int mount_client_notified;
+ int mount_client_delay;
+ int group_leave_on_finish;
+ int remount_client;
+ int init;
+ int got_our_options;
+ int got_our_journals;
+ int delay_send_journals;
+ int kernel_mount_error;
+ int kernel_mount_done;
+ int got_kernel_mount;
+ int first_mount_pending_stop;
+ int first_mounter;
+ int first_mounter_done;
+ int global_first_recover_done;
+ int emulate_first_mounter;
+ int wait_first_done;
+ int low_nodeid;
+ int master_nodeid;
+ int save_plocks;
+
+ uint64_t cp_handle;
+ time_t last_checkpoint_time;
+ time_t last_plock_time;
+
+ int needs_recovery;
+ int our_jid;
+ int spectator;
+ int readonly;
+ int rw;
+ int withdraw;
+ int dmsetup_wait;
+ pid_t dmsetup_pid;
+
+ struct list_head saved_messages;
+ void *start2_fn;
+};
+
+/* mg_member opts bit field */
+
+enum {
+ MEMB_OPT_RW = 1,
+ MEMB_OPT_RO = 2,
+ MEMB_OPT_SPECT = 4,
+ MEMB_OPT_RECOVER = 8,
+};
+
+/* these need to match the kernel defines of the same name in
+ linux/fs/gfs2/lm_interface.h */
+
+#define LM_RD_GAVEUP 308
+#define LM_RD_SUCCESS 309
+
+/* mg_member state: local_recovery_status, recovery_status */
+
+enum {
+ RS_NEED_RECOVERY = 1,
+ RS_SUCCESS,
+ RS_GAVEUP,
+ RS_NOFS,
+ RS_READONLY,
+};
+
+struct mg_member {
+ struct list_head list;
+ int nodeid;
+ int jid;
+
+ int spectator;
+ int readonly;
+ int rw;
+ uint32_t opts;
+
+ int tell_gfs_to_recover;
+ int wait_gfs_recover_done;
+ int gone_event;
+ int gone_type;
+ int finished;
+ int local_recovery_status;
+ int recovery_status;
+ int withdrawing;
+ int needs_journals;
+
+ int ms_kernel_mount_done;
+ int ms_first_mounter;
+ int ms_kernel_mount_error;
+};
+
+enum {
+ MSG_JOURNAL = 1,
+ MSG_OPTIONS,
+ MSG_REMOUNT,
+ MSG_PLOCK,
+ MSG_WITHDRAW,
+ MSG_MOUNT_STATUS,
+ MSG_RECOVERY_STATUS,
+ MSG_RECOVERY_DONE,
+};
+
+#define GDLM_VER_MAJOR 1
+#define GDLM_VER_MINOR 0
+#define GDLM_VER_PATCH 0
+
+struct gdlm_header {
+ uint16_t version[3];
+ uint16_t type; /* MSG_ */
+ uint32_t nodeid; /* sender */
+ uint32_t to_nodeid; /* 0 if to all */
+ char name[MAXNAME];
+};
+
+struct save_msg {
+ struct list_head list;
+ int nodeid;
+ int len;
+ int type;
+ char buf[0];
+};
+
+int do_read(int fd, void *buf, size_t count);
+int do_write(int fd, void *buf, size_t count);
+struct mountgroup *find_mg(char *name);
+struct mountgroup *find_mg_id(uint32_t id);
+
+int setup_cman(void);
+int process_cman(void);
+int setup_cpg(void);
+int process_cpg(void);
+int setup_groupd(void);
+int process_groupd(void);
+int setup_plocks(void);
+int process_plocks(void);
+void exit_cman(void);
+
+int do_mount(int ci, char *dir, char *type, char *proto, char *table,
+ char *options, char *dev, struct mountgroup **mg_ret);
+int do_unmount(int ci, char *dir, int mnterr);
+int do_remount(int ci, char *dir, char *mode);
+int do_withdraw(char *name);
+int kernel_recovery_done(char *name);
+void ping_kernel_mount(char *table);
+void save_message(struct mountgroup *mg, char *buf, int len, int from, int type);
+void got_mount_result(struct mountgroup *mg, int result, int ci, int another);
+
+int client_send(int ci, char *buf, int len);
+
+int send_group_message(struct mountgroup *mg, int len, char *buf);
+void update_flow_control_status(void);
+
+void store_plocks(struct mountgroup *mg, int nodeid);
+void retrieve_plocks(struct mountgroup *mg);
+int dump_plocks(char *name, int fd);
+void process_saved_plocks(struct mountgroup *mg);
+void purge_plocks(struct mountgroup *mg, int nodeid, int unmount);
+int unlink_checkpoint(struct mountgroup *mg);
+void update_dmsetup_wait(void);
+
+#endif
More information about the Ocfs2-tools-commits
mailing list