[Ocfs2-tools-commits] mfasheh commits r465 - in trunk: . clusterbo documentation documentation/samples libocfs2/include libocfs2cluster libocfs2cluster/include listuuid mkfs.ocfs2 mount.ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Mon Dec 6 15:50:04 CST 2004


Author: mfasheh
Date: 2004-12-06 15:50:03 -0600 (Mon, 06 Dec 2004)
New Revision: 465

Added:
   trunk/clusterbo/
   trunk/clusterbo/Makefile
   trunk/clusterbo/clusterbo.c
   trunk/documentation/
   trunk/documentation/samples/
   trunk/documentation/samples/cluster.conf
   trunk/libocfs2cluster/
   trunk/libocfs2cluster/README
   trunk/libocfs2cluster/TODO
   trunk/libocfs2cluster/include/
   trunk/libocfs2cluster/include/ocfs2_heartbeat.h
   trunk/libocfs2cluster/include/ocfs2_nodemanager.h
   trunk/libocfs2cluster/include/ocfs2_tcp.h
   trunk/listuuid/
   trunk/listuuid/Makefile
   trunk/listuuid/listuuid.c
   trunk/mount.ocfs2/
   trunk/mount.ocfs2/Makefile
   trunk/mount.ocfs2/mount.ocfs2.c
Removed:
   trunk/dlmtools/
Modified:
   trunk/Makefile
   trunk/libocfs2/include/ocfs2_fs.h
   trunk/mkfs.ocfs2/mkfs.c
Log:
* merge the dlm-glue tree back to trunk.



Modified: trunk/Makefile
===================================================================
--- trunk/Makefile	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/Makefile	2004-12-06 21:50:03 UTC (rev 465)
@@ -22,7 +22,7 @@
 $(error could not detect architecture for tools)
 endif
 
-SUBDIRS = libocfs2 fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 dlmtools extras load_ocfs ocfs_uid_gen patches
+SUBDIRS = libocfs2 fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 clusterbo mount.ocfs2 listuuid extras load_ocfs ocfs_uid_gen patches
 
 ifdef BUILD_OCFS2CDSL
 SUBDIRS += ocfs2cdsl

Added: trunk/clusterbo/Makefile
===================================================================
--- trunk/clusterbo/Makefile	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/clusterbo/Makefile	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,36 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+SBIN_PROGRAMS = clusterbo
+
+INCLUDES = -Iinclude -I$(TOPDIR)/libocfs2/include \
+	    -I$(TOPDIR)/libocfs2cluster/include
+LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
+LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
+
+ifdef OCFS_DEBUG
+OPTS += -ggdb
+else
+OPTS += -O2
+endif
+
+CFLAGS := $(OPTS) -Wall -Wstrict-prototypes -Wmissing-prototypes \
+           -Wmissing-declarations
+
+DEFINES = -DOCFS2_FLAT_INCLUDES
+
+CFILES =	clusterbo.c
+
+OBJS = $(subst .c,.o,$(CFILES))
+
+DIST_FILES = $(CFILES) 
+DIST_RULES = dist-subdircreate
+
+dist-subdircreate:
+	$(TOPDIR)/mkinstalldirs $(DIST_DIR)/include
+
+clusterbo: $(OBJS) $(LIBOCFS2_DEPS)
+	$(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
+
+include $(TOPDIR)/Postamble.make

Added: trunk/clusterbo/clusterbo.c
===================================================================
--- trunk/clusterbo/clusterbo.c	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/clusterbo/clusterbo.c	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,375 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/mount.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#define __u8 unsigned char 
+#define u8 unsigned char 
+#define u16 unsigned short int
+#define u32 unsigned int       
+#define u64 unsigned long long
+#define atomic_t int
+#define spinlock_t unsigned long
+typedef unsigned short kdev_t;
+
+typedef struct list_head {
+        struct list_head *next, *prev;
+} list_t;
+
+#include "ocfs2_nodemanager.h"
+
+#define NIPQUAD(addr) \
+        ((unsigned char *)&addr)[0], \
+        ((unsigned char *)&addr)[1], \
+        ((unsigned char *)&addr)[2], \
+        ((unsigned char *)&addr)[3]
+
+
+#define CLUSTER_FILE   "/proc/cluster/nm/.cluster"
+#define GROUP_FILE     "/proc/cluster/nm/.group"
+#define NODE_FILE      "/proc/cluster/nm/.node"
+
+#define CONF_FILE   "/etc/cluster.conf"
+
+/* are these right ? */
+#define MIN_PORT_NUM   1024
+#define MAX_PORT_NUM   65535
+
+#define  NET_IOC_MAGIC          'O'
+#define  NET_IOC_ACTIVATE       _IOR(NET_IOC_MAGIC, 1, net_ioc)
+#define  NET_IOC_GETSTATE       _IOR(NET_IOC_MAGIC, 2, net_ioc)
+
+
+typedef struct _net_ioc
+{
+	unsigned int status;
+} net_ioc;
+
+#define OCFS2_NM_MODULE  "ocfs2_nodemanager"
+#define OCFS2_HB_MODULE  "ocfs2_heartbeat"
+#define OCFS2_TCP_MODULE "ocfs2_tcp"
+
+
+int activate_cluster(void);
+int add_node(nm_node_info *newnode);
+int set_cluster_name(char *cluster_name);
+int activate_net(void);
+int load_module(char *module, char *mountpoint, char *fstype);
+
+
+nm_node_info *nodes;
+int total_nodes = 0;
+
+int main(int argc, char **argv)
+{
+	int ret, i;
+	FILE *conf;
+	char *cluster_name = NULL;
+
+	ret = load_module(OCFS2_NM_MODULE, "/proc/cluster/nm", "nm");
+	if (ret) {
+		fprintf(stderr, "failed to load and/or mount nm: %d\n", ret);
+		exit(1);
+	}
+	ret = load_module(OCFS2_HB_MODULE, "/proc/cluster/heartbeat", "hb");
+	if (ret) {
+		fprintf(stderr, "failed to load and/or mount hb: %d\n", ret);
+		exit(1);
+	}
+	ret = load_module(OCFS2_TCP_MODULE, NULL, NULL);
+	if (ret) {
+		fprintf(stderr, "failed to load tcp: %d\n", ret);
+		exit(1);
+	}
+
+	nodes = malloc(NM_MAX_NODES * sizeof(nm_node_info));
+	if (!nodes) {
+		fprintf(stderr, "failed to malloc node array\n");
+		exit(1);
+	}
+	memset(nodes, 0, NM_MAX_NODES * sizeof(nm_node_info));
+	
+	conf = fopen(CONF_FILE, "r");
+	if (!conf) {
+		fprintf(stderr, "failed to open %s: %s\n", CONF_FILE, strerror(errno));
+		exit(1);
+	}
+
+	ret = fscanf(conf, "cluster_name=%64as\n", &cluster_name);
+	if (ret != 1) {
+		fprintf(stderr, "bad file format: expected cluster_name=XXX\n");
+		exit(1);
+	}
+	printf("found cluster named %s\n", cluster_name);
+
+	while (1) {
+		int node_num, port;
+		char *node_name = NULL;
+		char *ip = NULL;
+		u32 real_ip;
+
+		ret = fscanf(conf, "%d,%64a[^,],%15a[0-9.],%d\n", &node_num, &node_name, &ip, &port);
+		if (ret == 0 || ret == -1) {
+			printf("done.  found %d nodes\n", total_nodes);
+			break;
+		}
+		if (ret != 4) {
+			fprintf(stderr, "bad file format: node_num,node_name,ipaddr,ipport\n");
+			exit(1);
+		}
+
+		if (node_num < 0 || node_num >= NM_MAX_NODES) {
+			fprintf(stderr, "bad node number: got %d, range is 0 - %d\n", node_num, NM_MAX_NODES-1);
+			exit(1);
+		}
+		if (nodes[node_num].node_name[0]) {
+			fprintf(stderr, "already have a node in slot %d: orig=%s, this=%s\n", 
+				node_num, nodes[node_num].node_name, node_name);
+			exit(1);
+		}
+		if (port < MIN_PORT_NUM || port > MAX_PORT_NUM) {
+			fprintf(stderr, "bad port number: got %d, range is %d - %d\n", port, MIN_PORT_NUM, MAX_PORT_NUM);
+			exit(1);
+		}
+		if (!inet_aton(ip, (struct in_addr*)&real_ip)) {
+			fprintf(stderr, "bad ipv4 address: %s\n", ip);
+			exit(1);
+		}
+
+
+		total_nodes++;
+		nodes[node_num].node_num = node_num;
+		memcpy(nodes[node_num].node_name, node_name, NM_MAX_NAME_LEN);
+		nodes[node_num].node_name[NM_MAX_NAME_LEN]=0;
+		nodes[node_num].ifaces[0].ip_port = htons(port);
+		nodes[node_num].ifaces[0].addr_u.ip_addr4 = real_ip;
+		free(ip);
+		free(node_name);
+	}
+	fclose(conf);
+	
+	set_cluster_name(cluster_name);
+	i=0;
+	while (1) {
+		if (!total_nodes--)
+			break;
+		if (!nodes[i].node_name[0]) {
+			i++;
+			continue;
+		}
+		add_node(&nodes[i]);
+		i++;
+	}
+	printf("done.  activating cluster now...\n");
+	activate_cluster();
+	printf("done.  nm ready!\n");
+	activate_net();
+	printf("done.  net ready!\n");
+	free(nodes);
+	return 0;
+}
+
+int set_cluster_name(char *cluster_name)
+{
+	int fd;
+	nm_op *op;
+	int ret;
+	char *buf;
+	
+	buf = malloc(4096);
+	op = (nm_op *)buf;
+	memset(buf, 0, 4096);
+	op->magic = NM_OP_MAGIC;
+
+	printf("setting cluster name...\n");
+	fd = open(CLUSTER_FILE, O_RDWR);
+	if (fd == -1) {
+		printf("failed to open %s\n", CLUSTER_FILE);
+		exit(1);
+	}
+	op->opcode = NM_OP_NAME_CLUSTER;
+	strcpy(&op->arg_u.name[0], cluster_name);
+
+	ret = write(fd, op, sizeof(nm_op));
+	printf("write called returned %d\n", ret);
+	if (ret < 0) {
+		printf("error is: %s\n", strerror(errno));
+		exit(1);
+	}
+	memset(buf, 0, 4096);
+	ret = read(fd, buf, 4096);
+	printf("read returned %d\n", ret);
+	if (ret < 0)
+		exit(1);
+	printf("<<<<%*s>>>>\n", ret, buf);
+	close(fd);
+	free(buf);
+	return 0;
+
+}
+
+int add_node(nm_node_info *newnode)
+{
+	int fd;
+	nm_op *op;
+	int ret;
+	char *buf;
+	nm_node_info *node;
+	
+	buf = malloc(4096);
+	op = (nm_op *)buf;
+	memset(buf, 0, 4096);
+	op->magic = NM_OP_MAGIC;
+
+
+	printf("adding cluster node....\n");
+	fd = open(CLUSTER_FILE, O_RDWR);
+	if (fd == -1) {
+		printf("failed to open %s\n", CLUSTER_FILE);
+		exit(1);
+	}
+	op->opcode = NM_OP_ADD_CLUSTER_NODE;
+	node = &(op->arg_u.node);
+	memcpy(node, newnode, sizeof(nm_node_info));
+	printf("passing port=%u, vers=%u, addr=%d.%d.%d.%d\n",
+	       node->ifaces[0].ip_port,
+	       node->ifaces[0].ip_version,
+	       NIPQUAD(node->ifaces[0].addr_u.ip_addr4));
+
+	ret = write(fd, op, sizeof(nm_op));
+	printf("write called returned %d\n", ret);
+	if (ret < 0) {
+		printf("error is: %s\n", strerror(errno));
+		exit(1);
+	}
+	memset(buf, 0, 4096);
+	ret = read(fd, buf, 4096);
+	printf("read returned %d\n", ret);
+	if (ret < 0)
+		exit(1);
+	printf("<<<<%*s>>>>\n", ret, buf);
+	close(fd);
+
+	free(buf);
+	return 0;
+
+}
+
+int activate_cluster(void)
+{
+	int fd;
+	nm_op *op;
+	int ret;
+	char *buf;
+	
+	buf = malloc(4096);
+	op = (nm_op *)buf;
+	memset(buf, 0, 4096);
+	op->magic = NM_OP_MAGIC;
+
+	printf("activating cluster....\n");
+	fd = open(CLUSTER_FILE, O_RDWR);
+	if (fd == -1) {
+		printf("failed to open %s\n", CLUSTER_FILE);
+		exit(1);
+	}
+	op->opcode = NM_OP_CREATE_CLUSTER;
+
+	ret = write(fd, op, sizeof(nm_op));
+	printf("write called returned %d\n", ret);
+	if (ret < 0) {
+		printf("error is: %s\n", strerror(errno));
+		exit(1);
+	}
+	memset(buf, 0, 4096);
+	ret = read(fd, buf, 4096);
+	printf("read returned %d\n", ret);
+	if (ret < 0)
+		exit(1);
+	printf("<<<<%*s>>>>\n", ret, buf);
+	close(fd);
+
+	free(buf);
+	return 0;
+
+}
+
+
+int activate_net(void)
+{
+	int fd;
+	net_ioc net;
+
+	memset(&net, 0, sizeof(net_ioc));
+	fd = open("/proc/cluster/net", O_RDONLY);
+	if (fd == -1) {
+		printf("eeek.  failed to open\n");
+		exit(1);
+	}
+	
+	if (ioctl(fd, NET_IOC_ACTIVATE, &net) == -1) {
+		printf("eeek.  ioctl failed\n");
+		close(fd);
+		exit(1);
+	}
+	close(fd);
+	printf("ioctl returned: %u\n", net.status);
+	return 0;
+}
+
+
+int load_module(char *module, char *mountpoint, char *fstype)
+{
+	int ret;
+	int pid;
+	int status;
+	struct stat st;
+
+	pid = fork();
+	switch (pid) {
+		case 0:
+			ret = execl("/sbin/modprobe", "/sbin/modprobe", module, (char *)NULL);
+			fprintf(stderr, "eeek! exec returned %d: %s\n", ret, strerror(errno));
+			exit(1);
+			break;
+		case -1:
+			fprintf(stderr, "fork failed: %s\n", strerror(errno));
+			return -errno;
+
+		default:
+			ret = wait(&status);
+			if (WIFEXITED(status)) {
+				if (WEXITSTATUS(status) != 0) {
+					fprintf(stderr, "modprobe returned %d!\n", WEXITSTATUS(status));
+					return -WEXITSTATUS(status);
+				}
+			} else {
+				fprintf(stderr, "modprobe has not exited!\n");
+				return -EINVAL;
+			}
+			break;
+	}
+	if (!mountpoint)
+		return 0;
+
+	if (stat("/proc/cluster", &st) != 0 ||
+	    stat(mountpoint, &st) != 0) {
+		fprintf(stderr, "mountpoint %s does not exist!\n", mountpoint);
+		return -EINVAL;
+	}
+
+	ret = mount("none", mountpoint, fstype, 0, "");
+	return ret;
+}

Added: trunk/documentation/samples/cluster.conf
===================================================================
--- trunk/documentation/samples/cluster.conf	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/documentation/samples/cluster.conf	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,4 @@
+cluster_name=foofers
+0,ca-test31,139.185.118.131,8765
+1,ca-test32,139.185.118.132,7654
+2,ca-test33,139.185.118.133,9977

Modified: trunk/libocfs2/include/ocfs2_fs.h
===================================================================
--- trunk/libocfs2/include/ocfs2_fs.h	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/libocfs2/include/ocfs2_fs.h	2004-12-06 21:50:03 UTC (rev 465)
@@ -97,6 +97,11 @@
 #define OCFS2_CHAIN_FL		(0x00000400)	/* Chain allocator */
 
 /*
+ * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
+ */
+#define OCFS2_JOURNAL_DIRTY_FL	(0x00000001)	/* Journal needs recovery */
+
+/*
  * superblock s_state flags
  */
 #define OCFS2_ERROR_FS		(0x00000001)	/* FS saw errors */
@@ -126,8 +131,9 @@
 enum {
 	BAD_BLOCK_SYSTEM_INODE = 0,
 	GLOBAL_INODE_ALLOC_SYSTEM_INODE,
+	SLOT_MAP_SYSTEM_INODE,
+#define OCFS2_FIRST_ONLINE_SYSTEM_INODE SLOT_MAP_SYSTEM_INODE
 	DLM_SYSTEM_INODE,
-#define OCFS2_FIRST_ONLINE_SYSTEM_INODE DLM_SYSTEM_INODE
 	GLOBAL_BITMAP_SYSTEM_INODE,
 	ORPHAN_DIR_SYSTEM_INODE,
 #define OCFS2_LAST_GLOBAL_SYSTEM_INODE ORPHAN_DIR_SYSTEM_INODE
@@ -145,6 +151,7 @@
 	[GLOBAL_INODE_ALLOC_SYSTEM_INODE] 	{ "global_inode_alloc", OCFS2_BITMAP_FL | OCFS2_CHAIN_FL, 0 },
 
 	/* These are used by the running filesystem */
+	[SLOT_MAP_SYSTEM_INODE]			{ "slot_map", 0, 0 },
 	[DLM_SYSTEM_INODE]			{ "dlm", OCFS2_DLM_FL, 0 },
 	[GLOBAL_BITMAP_SYSTEM_INODE]		{ "global_bitmap", 0, 0 },
 	[ORPHAN_DIR_SYSTEM_INODE]		{ "orphan_dir", 0, 1 },

Added: trunk/libocfs2cluster/README
===================================================================
--- trunk/libocfs2cluster/README	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/libocfs2cluster/README	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,16 @@
+Here's how to get the basics working:
+  * plunk down otcp.o, onm.o, ohb.o and odlm.o somewhere in your
+      module path and run depmod (or better yet, symlink each to
+      your build tree and run depmod -ar)
+  * make an /etc/cluster.conf.  example:
+	cluster_name=foofers
+	0,ca-test31,139.185.118.131,8765
+	1,ca-test32,139.185.118.132,7654
+	2,ca-test33,139.185.118.133,9977
+    the node format is <nodenum>,<nodename>,<ip>,<port>
+  * run clusterbo as root
+  * run "mount -t ocfs2 /dev/device /mount/point"
+    -o options: hbdev=different-device -or-
+                hbuuid=different-uuid
+                to heartbeat on a different device than
+                the one you are mounting

Added: trunk/libocfs2cluster/TODO
===================================================================
--- trunk/libocfs2cluster/TODO	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/libocfs2cluster/TODO	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,7 @@
+* change the name and/or path of /etc/cluster.conf to something friendlier
+  maybe /etc/sysconfig/cluster/xxxx or similar
+* change the cluster.conf format to jlbec's stanza style
+* harden the tools for setuid-ness
+* fix mount.ocfs2 to handle other normal mount options appropriately (at least
+  handle rw, which is passed magically by /sbin/mount)
+

Added: trunk/libocfs2cluster/include/ocfs2_heartbeat.h
===================================================================
--- trunk/libocfs2cluster/include/ocfs2_heartbeat.h	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/libocfs2cluster/include/ocfs2_heartbeat.h	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,94 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmhb.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Mark Fasheh, Sunil Mushran, Wim Coekaerts,
+ *	    Manish Singh, Neeraj Goyal, Suchit Kaura
+ */
+
+#ifndef DLMHB_H
+#define DLMHB_H
+
+#define CLUSTER_DISK_UUID_LEN      32      // 16 byte binary == 32 char hex string
+
+enum {
+	HB_NODE_STATE_INIT = 0,
+	HB_NODE_STATE_DOWN,
+	HB_NODE_STATE_UP
+};
+
+
+#define HB_OP_MAGIC      0xf00d
+enum {
+	HB_OP_START_DISK_HEARTBEAT=371,
+	HB_OP_GET_NODE_MAP
+};
+
+typedef struct _hb_op
+{
+	u16 magic;
+	u16 opcode;
+	unsigned int fd;
+	char disk_uuid[CLUSTER_DISK_UUID_LEN+1];
+	u16 group_num;
+	u32 bits;
+	u32 blocks;
+	u64 start;
+} hb_op;
+
+enum {
+	HB_TYPE_DISK = 0,
+	HB_TYPE_NET
+};
+
+
+/* callback stuff */
+
+enum {
+	HB_NODE_DOWN_CB = 0,
+	HB_NODE_UP_CB,
+	HB_NODE_RESPONDED_CB,    // this one is very chatty
+	HB_NUM_CB
+};
+
+enum {
+	HB_Root = 1,
+	HB_Disk,
+	HB_WriteOpArraySize
+};
+
+typedef struct _hb_disk_heartbeat_block
+{
+	u64 time;
+} hb_disk_heartbeat_block;
+
+
+// number of initial allowed misses 
+#define HB_INITIAL_DISK_MARGIN     60
+#define HB_INITIAL_NET_MARGIN      60
+
+// number of allowed misses in steady state
+#define HB_DISK_MARGIN             30
+#define HB_NET_MARGIN              30
+
+#endif /* DLMHB_H */

Added: trunk/libocfs2cluster/include/ocfs2_nodemanager.h
===================================================================
--- trunk/libocfs2cluster/include/ocfs2_nodemanager.h	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/libocfs2cluster/include/ocfs2_nodemanager.h	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,119 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmnm.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Mark Fasheh, Sunil Mushran, Wim Coekaerts,
+ *	    Manish Singh, Neeraj Goyal, Suchit Kaura
+ */
+
+#ifndef DLMNM_H
+#define DLMNM_H
+
+#include "ocfs2_heartbeat.h"
+
+#define NM_MAX_IFACES            2
+#define NM_MAX_NODES             255
+#define NM_INVALID_SLOT_NUM      255
+
+/* host name, group name, cluster name all 64 bytes */
+#define NM_MAX_NAME_LEN          64    // __NEW_UTS_LEN
+
+
+#define NM_GROUP_INODE_START    200000
+#define NM_NODE_INODE_START     100000
+
+enum {
+	NM_CLUSTER_DOWN=0,
+	NM_CLUSTER_UP
+};
+
+enum {
+	NM_GROUP_NOT_READY=0,
+	NM_GROUP_READY
+};
+
+enum {
+	NM_Root = 1,
+	NM_Cluster,
+	NM_Node,
+	NM_Group,
+};
+
+
+
+
+typedef struct _nm_network_iface
+{
+	u16 ip_port;			/* for simplicity, just define exactly one port for this if */
+	u16 ip_version;
+	union {
+		u32 ip_addr4;		/* IPv4 address in NBO */
+		u32 ip_addr6[4];	/* IPv6 address in NBO */
+	} addr_u;
+} nm_network_iface;
+
+typedef struct _nm_node_info 
+{
+	u16 node_num;
+	char node_name[NM_MAX_NAME_LEN+1];
+	nm_network_iface ifaces[NM_MAX_IFACES];
+} nm_node_info;
+
+/* transaction file nm_op stuff */
+
+#define NM_OP_MAGIC      0xbeaf
+enum {
+	NM_OP_CREATE_CLUSTER=123,
+	NM_OP_DESTROY_CLUSTER,
+	NM_OP_NAME_CLUSTER,
+	NM_OP_ADD_CLUSTER_NODE,
+	NM_OP_GET_CLUSTER_NUM_NODES,
+	NM_OP_GET_NODE_INFO,
+	NM_OP_CREATE_GROUP,
+	NM_OP_GET_GROUP_INFO,
+	NM_OP_ADD_GROUP_NODE,
+	NM_OP_GET_GLOBAL_NODE_NUM
+};
+
+typedef struct _nm_group_change
+{
+	u16 group_num;
+	u16 node_num;
+	u16 slot_num;
+	char disk_uuid[CLUSTER_DISK_UUID_LEN+1];
+	char name[NM_MAX_NAME_LEN+1];
+} nm_group_change;
+
+typedef struct _nm_op
+{
+	u16 magic;
+	u16 opcode;
+	union {
+		u16 index;
+		char name[NM_MAX_NAME_LEN+1];
+		nm_node_info node;
+		nm_group_change gc;
+	} arg_u;
+} nm_op;
+
+#endif /* DLMNM_H */

Added: trunk/libocfs2cluster/include/ocfs2_tcp.h
===================================================================
--- trunk/libocfs2cluster/include/ocfs2_tcp.h	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/libocfs2cluster/include/ocfs2_tcp.h	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,61 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmtcp.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Mark Fasheh, Sunil Mushran, Wim Coekaerts,
+ *	    Manish Singh, Neeraj Goyal, Suchit Kaura
+ */
+
+#ifndef DLMNET_H
+#define DLMNET_H
+#include <linux/socket.h>
+#include <sys/socket.h>
+#include <linux/inet.h>
+#include <linux/in.h>
+
+typedef struct _gsd_ioc
+{
+	int fd;
+	int namelen;
+	char name[NM_MAX_NAME_LEN+1];
+	int status;
+} gsd_ioc;
+
+#define  NET_IOC_MAGIC          'O'
+#define  NET_IOC_ACTIVATE       _IOR(NET_IOC_MAGIC, 1, net_ioc)
+#define  NET_IOC_GETSTATE       _IOR(NET_IOC_MAGIC, 2, net_ioc)
+#define  GSD_IOC_CREATE_GROUP   _IOR(NET_IOC_MAGIC, 3, gsd_ioc)
+#define  GSD_IOC_ADD_GROUP_NODE _IOR(NET_IOC_MAGIC, 4, gsd_ioc)
+
+#define GSD_MESSAGE   130
+#define GSD_ACTION_ADD_GROUP        (0x01)
+#define GSD_ACTION_ADD_GROUP_NODE   (0x02)
+typedef struct _gsd_message
+{
+	u16 from;
+	u8 action;
+	u8 namelen;
+	u8 name[NM_MAX_NAME_LEN];
+} gsd_message;
+
+#endif /* DLMNET_H */

Added: trunk/listuuid/Makefile
===================================================================
--- trunk/listuuid/Makefile	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/listuuid/Makefile	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,36 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+SBIN_PROGRAMS = listuuid
+
+INCLUDES = -Iinclude -I$(TOPDIR)/libocfs2/include \
+	    -I$(TOPDIR)/libocfs2cluster/include
+LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
+LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
+
+ifdef OCFS_DEBUG
+OPTS += -ggdb
+else
+OPTS += -O2
+endif
+
+CFLAGS := $(OPTS) -Wall -Wstrict-prototypes -Wmissing-prototypes \
+           -Wmissing-declarations
+
+DEFINES = -DOCFS2_FLAT_INCLUDES
+
+CFILES =	listuuid.c
+
+OBJS = $(subst .c,.o,$(CFILES))
+
+DIST_FILES = $(CFILES) 
+DIST_RULES = dist-subdircreate
+
+dist-subdircreate:
+	$(TOPDIR)/mkinstalldirs $(DIST_DIR)/include
+
+listuuid: $(OBJS) $(LIBOCFS2_DEPS)
+	$(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
+
+include $(TOPDIR)/Postamble.make

Added: trunk/listuuid/listuuid.c
===================================================================
--- trunk/listuuid/listuuid.c	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/listuuid/listuuid.c	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,258 @@
+/*
+ * listuuid.c
+ *
+ * Lists UUIDs of all the devices
+ *
+ * Copyright (C) 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Authors: Sunil Mushran
+ */
+
+#define _LARGEFILE64_SOURCE
+#define _GNU_SOURCE /* Because libc really doesn't want us using O_DIRECT? */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/fd.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#define  OCFS2_FLAT_INCLUDES	1
+#include <ocfs2.h>
+#include <ocfs2_fs.h>
+#include <ocfs2_disk_dlm.h>
+#include <ocfs1_fs_compat.h>
+#include <kernel-list.h>
+
+char *device = NULL;
+char *progname = NULL;
+int all_devices = 0;
+
+char *usage_string =
+"usage: %s [-a] [device]\n";
+
+/*
+ * ocfs2_partition_list()
+ *
+ */
+static errcode_t ocfs2_partition_list (struct list_head *dev_list)
+{
+	errcode_t ret = 0;
+	FILE *proc;
+	char line[256];
+	char name[256];
+	char major[256];
+	char minor[256];
+	ocfs2_devices *dev;
+
+	proc = fopen ("/proc/partitions", "r");
+	if (proc == NULL) {
+		ret = OCFS2_ET_IO;
+		goto bail;
+	}
+
+	while (fgets (line, sizeof(line), proc) != NULL) {
+		*major = *minor = *name = '\0';
+		if (sscanf(line, "%*[ ]%[0-9]%*[ ]%[0-9] %*d %99[^ \t\n]",
+			   major, minor, name) != 3)
+			continue;
+
+		ret = ocfs2_malloc0(sizeof(ocfs2_devices), &dev);
+		if (ret)
+			goto bail;
+
+		snprintf(dev->dev_name, sizeof(dev->dev_name), "/dev/%s", name);
+		dev->maj_num = strtoul(major, NULL, 0);
+		dev->min_num = strtoul(minor, NULL, 0);
+		list_add_tail(&(dev->list), dev_list);
+	}
+
+bail:
+	if (proc)
+		fclose(proc);
+
+	return ret;
+}
+
+/*
+ * ocfs2_print_uuids()
+ *
+ */
+static void ocfs2_print_uuids(struct list_head *dev_list)
+{
+	ocfs2_devices *dev;
+	struct list_head *pos;
+	char uuid[40];
+	char devstr[10];
+	char *p;
+	int i;
+
+	printf("%-20s  %7s  %-32s\n", "Device", "maj,min", "UUID");
+	list_for_each(pos, dev_list) {
+		dev = list_entry(pos, ocfs2_devices, list);
+		if (dev->fs_type == 0)
+			continue;
+
+		memset(uuid, 0, sizeof(uuid));
+		for (i = 0, p = uuid; i < 16; i++, p += 2)
+			sprintf(p, "%02X", dev->uuid[i]);
+
+		sprintf(devstr, "%3d,%-d", dev->maj_num, dev->min_num);
+		printf("%-20s  %-7s  %-32s\n", dev->dev_name, devstr, uuid);
+	}
+
+	return ;
+}
+
+/*
+ * ocfs2_detect()
+ *
+ */
+static errcode_t ocfs2_detect(char *device)
+{
+	errcode_t ret = 0;
+	struct list_head dev_list;
+	struct list_head *pos1, *pos2;
+	ocfs2_devices *dev;
+	ocfs2_filesys *fs = NULL;
+	char *dev_name;
+
+	INIT_LIST_HEAD(&(dev_list));
+
+	if (device) {
+		ret = ocfs2_malloc0(sizeof(ocfs2_devices), &dev);
+		if (ret)
+			goto bail;
+		strncpy(dev->dev_name, device, sizeof(dev->dev_name));
+		list_add(&(dev->list), &dev_list);
+	} else {
+		ret = ocfs2_partition_list(&dev_list);
+		if (ret) {
+			com_err(progname, ret, "while reading /proc/partitions");
+			goto bail;
+		}
+	}
+
+	list_for_each(pos1, &dev_list) {
+		dev = list_entry(pos1, ocfs2_devices, list);
+		dev_name = dev->dev_name;
+
+		/* open	fs */
+		fs = NULL;
+		ret = ocfs2_open(dev_name, OCFS2_FLAG_RO, 0, 0, &fs);
+		if (ret) {
+			dev->fs_type = 0;
+			ret = 0;
+			continue;
+		} else
+			dev->fs_type = 2;
+
+		/* get uuid for ocfs2 */
+		if (dev->fs_type == 2) {
+			memcpy(dev->uuid, OCFS2_RAW_SB(fs->fs_super)->s_uuid,
+			       sizeof(dev->uuid));
+		}
+
+		/* close fs */
+		ocfs2_close(fs);
+	}
+
+	ocfs2_print_uuids(&dev_list);
+
+bail:
+
+	list_for_each_safe(pos1, pos2, &(dev_list)) {
+		dev = list_entry(pos1, ocfs2_devices, list);
+		list_del(&(dev->list));
+		ocfs2_free(&dev);
+	}
+
+	return ret;
+}
+
+/*
+ * usage()
+ *
+ */
+static void usage(char *progname)
+{
+	printf(usage_string, progname);
+	return ;
+}
+
+/*
+ * read_options()
+ *
+ */
+static int read_options(int argc, char **argv)
+{
+	int ret = 0;
+	int c;
+
+	progname = basename(argv[0]);
+
+	if (argc < 2) {
+		usage(progname);
+		ret = 1;
+		goto bail;
+	}
+
+	while(1) {
+		c = getopt(argc, argv, "a");
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'a':	/* all devices */
+			all_devices = 1;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	if (!ret && optind < argc && argv[optind])
+		device = argv[optind];
+
+bail:
+	return ret;
+}
+
+/*
+ * main()
+ *
+ */
+int main(int argc, char **argv)
+{
+	errcode_t ret = 0;
+
+	initialize_ocfs_error_table();
+
+	ret = read_options (argc, argv);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_detect(device);
+
+bail:
+	return ret;
+}

Modified: trunk/mkfs.ocfs2/mkfs.c
===================================================================
--- trunk/mkfs.ocfs2/mkfs.c	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/mkfs.ocfs2/mkfs.c	2004-12-06 21:50:03 UTC (rev 465)
@@ -267,6 +267,7 @@
 static void write_metadata(State *s, SystemFileDiskRecord *rec, void *src);
 static void write_bitmap_data(State *s, AllocBitmap *bitmap);
 static void write_directory_data(State *s, DirData *dir);
+static void write_slot_map_data(State *s, SystemFileDiskRecord *slot_map_rec);
 static void write_group_data(State *s, AllocGroup *group);
 static void format_leading_space(State *s);
 static void replacement_journal_create(State *s, uint64_t journal_off);
@@ -292,6 +293,7 @@
 SystemFileInfo system_files[] = {
 	{ "bad_blocks", SFI_OTHER, 1, 0 },
 	{ "global_inode_alloc", SFI_CHAIN, 1, 0 },
+	{ "slot_map", SFI_OTHER, 1, 0 },
 	{ "dlm", SFI_DLM, 1, 0 },
 	{ "global_bitmap", SFI_CLUSTER, 1, 0 },
 	{ "orphan_dir", SFI_OTHER, 1, 1 },
@@ -443,9 +445,8 @@
 		cpu_to_le64(tmprec->fe_off >> s->blocksize_bits);
 
 	tmprec = &(record[DLM_SYSTEM_INODE][0]);
-	need = (AUTOCONF_BLOCKS(s->initial_nodes, 32) +
-		PUBLISH_BLOCKS(s->initial_nodes, 32) +
-		VOTE_BLOCKS(s->initial_nodes, 32)) << s->blocksize_bits;
+	need = (OCFS2_MAX_NODES + 1) << s->blocksize_bits;
+
 	alloc_bytes_from_bitmap(s, need, s->global_bm, &tmprec->extent_off, &tmprec->extent_len);
 	tmprec->file_size = need;
 
@@ -455,6 +456,10 @@
 	add_entry_to_directory(s, orphan_dir, ".", tmprec->fe_off, OCFS2_FT_DIR);
 	add_entry_to_directory(s, orphan_dir, "..", system_dir_rec.fe_off, OCFS2_FT_DIR);
 
+	tmprec = &(record[SLOT_MAP_SYSTEM_INODE][0]);
+	alloc_from_bitmap(s, 1, s->global_bm, &tmprec->extent_off, &tmprec->extent_len);
+	tmprec->file_size = s->cluster_size;
+
 	format_leading_space(s);
 	format_superblock(s, &superblock_rec, &root_dir_rec, &system_dir_rec);
 
@@ -494,6 +499,9 @@
 
 	write_group_data(s, s->system_group);
 
+	tmprec = &(record[SLOT_MAP_SYSTEM_INODE][0]);
+	write_slot_map_data(s, tmprec);
+
 	write_directory_data(s, root_dir);
 	write_directory_data(s, system_dir);
 	write_directory_data(s, orphan_dir);
@@ -1689,6 +1697,28 @@
 }
 
 static void
+write_slot_map_data(State *s, SystemFileDiskRecord *slot_map_rec)
+{
+	int i, num;
+	int16_t *slot_map;
+
+	/* we only use the 1st block of this file, the rest is zero'd
+	 * out. */
+	num = s->blocksize / sizeof(int16_t);
+
+	slot_map = do_malloc(s, slot_map_rec->extent_len);
+	memset(slot_map, 0, slot_map_rec->extent_len);
+
+	for(i = 0; i < num; i++)
+		slot_map[i] = cpu_to_le16(-1);
+
+	do_pwrite(s, slot_map, slot_map_rec->extent_len,
+		  slot_map_rec->extent_off);
+
+	free(slot_map);
+}
+
+static void
 format_leading_space(State *s)
 {
 	int num_blocks = 2, size;

Added: trunk/mount.ocfs2/Makefile
===================================================================
--- trunk/mount.ocfs2/Makefile	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/mount.ocfs2/Makefile	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,36 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+SBIN_PROGRAMS = mount.ocfs2
+
+INCLUDES = -Iinclude -I$(TOPDIR)/libocfs2/include \
+	    -I$(TOPDIR)/libocfs2cluster/include
+LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
+LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
+
+ifdef OCFS_DEBUG
+OPTS += -ggdb
+else
+OPTS += -O2
+endif
+
+CFLAGS := $(OPTS) -Wall -Wstrict-prototypes -Wmissing-prototypes \
+           -Wmissing-declarations
+
+DEFINES = -DOCFS2_FLAT_INCLUDES
+
+CFILES =	mount.ocfs2.c
+
+OBJS = $(subst .c,.o,$(CFILES))
+
+DIST_FILES = $(CFILES) 
+DIST_RULES = dist-subdircreate
+
+dist-subdircreate:
+	$(TOPDIR)/mkinstalldirs $(DIST_DIR)/include
+
+mount.ocfs2: $(OBJS) $(LIBOCFS2_DEPS)
+	$(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
+
+include $(TOPDIR)/Postamble.make

Added: trunk/mount.ocfs2/mount.ocfs2.c
===================================================================
--- trunk/mount.ocfs2/mount.ocfs2.c	2004-12-06 00:35:04 UTC (rev 464)
+++ trunk/mount.ocfs2/mount.ocfs2.c	2004-12-06 21:50:03 UTC (rev 465)
@@ -0,0 +1,967 @@
+/*
+ * listuuid.c
+ *
+ * Lists UUIDs of all the devices
+ *
+ * Copyright (C) 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Authors: Sunil Mushran
+ */
+
+
+#define _LARGEFILE64_SOURCE
+#define _GNU_SOURCE /* Because libc really doesn't want us using O_DIRECT? */
+
+#include <sys/types.h>
+#include <asm/types.h>
+
+#define u8   __u8
+#define s8   __s8
+#define u16  __u16
+#define s16  __s16
+#define u32  __u32
+#define s32  __s32
+#define u64  __u64
+#define s64  __s64
+#define atomic_t int
+#define spinlock_t unsigned long
+typedef unsigned short kdev_t;
+
+
+
+
+#include <asm/page.h>
+#include <sys/mount.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/fd.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#define  OCFS2_FLAT_INCLUDES	1
+#include <ocfs2.h>
+#include <ocfs2_fs.h>
+#include <ocfs2_disk_dlm.h>
+#include <ocfs1_fs_compat.h>
+#include <kernel-list.h>
+
+#include "bitops.h"
+
+#include "ocfs2_nodemanager.h"
+#include "ocfs2_heartbeat.h"
+#include "ocfs2_tcp.h"
+
+#define CLUSTER_FILE   "/proc/cluster/nm/.cluster"
+#define GROUP_FILE     "/proc/cluster/nm/.group"
+#define NODE_FILE      "/proc/cluster/nm/.node"
+#define HEARTBEAT_DISK_FILE "/proc/cluster/heartbeat/.disk"
+
+
+int create_remote_group(char *group_name, __u16 node);
+int get_node_map(__u16 group_num, char *bitmap);
+int get_raw_node_map(__u16 groupnum, char *groupdev, __u32 block_bits, __u32 num_blocks, __u64 start_block, char *bitmap);
+int get_ocfs2_disk_hb_params(char *group_dev, __u32 *block_bits, __u32 *cluster_bits,
+			     __u64 *start_block, __u32 *num_clusters);
+int activate_group(char *group_name, char *group_dev, __u16 group_num, 
+		   __u32 block_bits, __u64 num_blocks, __u64 start_block);
+int add_to_local_group(char *uuid, __u16 group_num, __u16 node_num);
+int create_group(char *uuid, __u16 *group_num);
+int get_my_nodenum(__u16 *nodenum);
+int add_me_to_group(char *groupname, char *groupdev);
+static errcode_t ocfs2_partition_list (struct list_head *dev_list);
+static void ocfs2_partition_list_destroy (struct list_head *dev_list);
+static errcode_t ocfs2_detect_all(struct list_head *dev_list);
+static int read_options(int argc, char **argv, char **hbuuid, char **hbdev, char **device, char **mp);
+
+char *op_buf = NULL;
+
+
+
+/*
+ * ocfs2_partition_list()
+ *
+ */
+static errcode_t ocfs2_partition_list (struct list_head *dev_list)
+{
+	errcode_t ret = 0;
+	FILE *proc;
+	char line[256];
+	char name[256];
+	ocfs2_devices *dev;
+
+	proc = fopen ("/proc/partitions", "r");
+	if (proc == NULL) {
+		ret = OCFS2_ET_IO;
+		goto bail;
+	}
+
+	while (fgets (line, sizeof(line), proc) != NULL) {
+		if (sscanf(line, "%*d %*d %*d %99[^ \t\n]", name) != 1)
+			continue;
+
+		ret = ocfs2_malloc0(sizeof(ocfs2_devices), &dev);
+		if (ret)
+			goto bail;
+
+		snprintf(dev->dev_name, sizeof(dev->dev_name), "/dev/%s", name);
+		list_add_tail(&(dev->list), dev_list);
+	}
+
+bail:
+	if (proc)
+		fclose(proc);
+
+	return ret;
+}
+
+
+/*
+ * ocfs2_partition_list_destroy()
+ *
+ */
+static void ocfs2_partition_list_destroy (struct list_head *dev_list)
+{
+	struct list_head *iter, *tmpiter;
+	ocfs2_devices *dev;
+
+	list_for_each_safe(iter, tmpiter, dev_list) {
+		dev = list_entry(iter, ocfs2_devices, list);
+		list_del(&dev->list);
+		free(dev);
+	}
+}
+
+
+/*
+ * ocfs2_detect_all()
+ *
+ */
+static errcode_t ocfs2_detect_all(struct list_head *dev_list)
+{
+	errcode_t ret = 0;
+	struct list_head *pos1;
+	ocfs2_devices *dev;
+	ocfs2_filesys *fs = NULL;
+	char *dev_name;
+
+	ret = ocfs2_partition_list(dev_list);
+	if (ret) {
+		com_err("mount.ocfs2", ret, "while reading /proc/partitions");
+		return ret;
+	}
+
+	list_for_each(pos1, dev_list) {
+		dev = list_entry(pos1, ocfs2_devices, list);
+		dev_name = dev->dev_name;
+
+		/* open	fs */
+		fs = NULL;
+		ret = ocfs2_open(dev_name, OCFS2_FLAG_RO, 0, 0, &fs);
+		if (ret) {
+			dev->fs_type = 0;
+			ret = 0;
+			continue;
+		} else
+			dev->fs_type = 2;
+
+		/* get uuid for ocfs2 */
+		if (dev->fs_type == 2) {
+			memcpy(dev->uuid, OCFS2_RAW_SB(fs->fs_super)->s_uuid,
+			       sizeof(dev->uuid));
+		}
+
+		/* close fs */
+		ocfs2_close(fs);
+	}
+	return ret;
+}
+
+
+/*
+ * read_options()
+ *
+ */
+static int read_options(int argc, char **argv, char **hbuuid, char **hbdev, char **device, char **mp)
+{
+	int ret = 0;
+	int c;
+	char *tmp, *tmp2;
+
+	if (argc < 2) {
+		ret = 1;
+		goto bail;
+	}
+
+	while(1) {
+		c = getopt(argc, argv, "o:");
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'o':	/* options */
+			ret = 1;
+			tmp = optarg;
+			while (*tmp) {
+				if (strncasecmp(tmp, "hbuuid=", strlen("hbuuid="))==0) {
+					tmp += strlen("hbuuid=");
+					tmp2 = strchr(tmp, ',');
+					
+					/* uuid should be exactly 32 hex chars */
+					if (tmp2) {
+						if (tmp2-tmp != 32)
+							goto bail;
+					} else {
+						if (strlen(tmp) != 32)
+							goto bail;
+					}
+					*hbuuid = strndup(tmp, 32);
+				} else if (strncasecmp(tmp, "hbdev=", strlen("hbdev="))==0) {
+					tmp += strlen("hbdev=");
+					tmp2 = strchr(tmp, ',');
+					if (!tmp2)
+						tmp2 = tmp + strlen(tmp);
+					if (tmp2-tmp <= 0)
+						goto bail;
+					*hbdev = strndup(tmp, tmp2-tmp);
+				} else {
+					/* unknown option, ignore
+					 * these for now, but we need
+					 * to eventually handle
+					 * them. */
+					tmp2 = strchr(tmp, ',');
+				}
+				tmp = tmp2;
+				if (!tmp || !*tmp)
+					break;
+				tmp++;
+			}
+			ret = 0;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	if (!ret) {
+		ret = 1;
+		/* need device and mountpoint */
+		if (optind+1 < argc && argv[optind] && argv[optind+1]) {
+			*device = strdup(argv[optind]);
+			*mp = strdup(argv[optind+1]);
+			ret = 0;
+		}
+	}
+
+bail:
+	return ret;
+}
+
+
+/*
+ * main()
+ *
+ */
+int main(int argc, char **argv)
+{
+	char *device = NULL, *mountpoint = NULL;
+	char *hbdev = NULL, *hbuuid = NULL;
+	errcode_t ret = 0;
+	struct list_head dev_list;
+	char uuid[40];
+	ocfs2_devices *dev;
+	struct list_head *iter;
+	char *p;
+	int i, found = 0;
+	unsigned long flags = 0;
+	char *args = NULL;
+
+	INIT_LIST_HEAD(&dev_list);
+
+	op_buf = malloc(PAGE_SIZE);
+	if (!op_buf) {
+		ret = 1;
+		goto bail;
+	}
+
+	ret = read_options (argc, argv, &hbuuid, &hbdev, &device, &mountpoint);
+	if (ret)
+		goto bail;
+	
+	ret = 1;
+	if (!device)
+		goto bail;
+
+	/* provide nothing or one, not both */
+	if (hbuuid && hbdev)
+		goto bail;
+
+	ret = ocfs2_detect_all(&dev_list);
+	if (ret)
+		goto bail;
+
+	found = 0;
+	/* sort out which device is to be used for heartbeat */
+	if (hbuuid) {
+		list_for_each(iter, &dev_list) {
+			dev = list_entry(iter, ocfs2_devices, list);
+			if (dev->fs_type != 2)
+				continue;
+
+			memset(uuid, 0, sizeof(uuid));
+			for (i = 0, p = uuid; i < 16; i++, p += 2)
+				sprintf(p, "%02X", dev->uuid[i]);
+			if (strncasecmp(uuid, hbuuid, 32)==0) {
+				/* found it */
+				strncpy(hbuuid, uuid, 32);  // normalized uuid
+				hbdev = strdup(dev->dev_name);
+				found = 1;
+				break;
+			}
+		}
+	} else {
+		char *look_for = (hbdev ? hbdev : device);
+		
+		/* broken for now.  have to give exact dev name in /proc/partitions */
+		list_for_each(iter, &dev_list) {
+			dev = list_entry(iter, ocfs2_devices, list);
+			if (dev->fs_type != 2)
+				continue;
+
+			if (strcasecmp(dev->dev_name, look_for)==0) {
+				/* found it */
+				if (!hbdev)
+					hbdev = strdup(dev->dev_name);
+				else
+					strcpy(hbdev, dev->dev_name);
+				hbuuid = malloc(33);
+				memset(hbuuid, 0, 33);
+				for (i = 0, p = hbuuid; i < 16; i++, p += 2)
+					sprintf(p, "%02X", dev->uuid[i]);
+				found = 1;
+				break;
+			}
+		}
+	}
+	if (!found) {
+		ret = 1;
+		goto bail;
+	}
+
+	/* all three should now have valid values */
+	printf("device=%s hbuuid=%s hbdev=%s\n", device, hbuuid, hbdev);
+
+	ret = add_me_to_group(hbuuid, hbdev);
+	if (ret < 0) {
+		printf("eeek! something bad happened in add_me_to_group: ret=%d\n", (int)ret);
+		goto bail;
+	}
+
+	args = malloc(strlen(hbuuid) + strlen("group=") + 1);
+	if (!args)
+		goto bail;
+	sprintf(args, "group=%s", hbuuid);
+	flags = 0;
+	ret = mount(device, mountpoint, "ocfs2", flags, args);
+
+bail:
+	if (args)
+		free(args);
+	if (device)
+		free(device);
+	if (mountpoint)
+		free(mountpoint);
+	if (hbdev)
+		free(hbdev);
+	if (hbuuid)
+		free(hbuuid);
+
+	ocfs2_partition_list_destroy (&dev_list);
+
+	if (op_buf)
+		free(op_buf);
+
+	return ret;
+}
+
+
+
+/*
+ * this will try to add the group (and the node to the group)
+ * for every mount.  luckily, there are many shortcut paths
+ * along the way, so checking for -EEXIST will save time.
+ */
+int add_me_to_group(char *groupname, char *groupdev)
+{
+	int ret;
+	__u16 my_nodenum, groupnum;
+	__u32 pre_nodemap[] = {0, 0, 0, 0, 0, 0, 0, 0};
+	__u32 post_nodemap[] = {0, 0, 0, 0, 0, 0, 0, 0};
+	int start, next, i;
+	__u32 block_bits, cluster_bits, num_clusters;
+	__u64 start_block, num_blocks;
+
+	/* either create the group or find that it already exists */
+	ret = get_my_nodenum(&my_nodenum);
+	if (ret < 0)
+		return ret;
+
+	ret = get_ocfs2_disk_hb_params(groupdev, &block_bits, &cluster_bits, 
+				       &start_block, &num_clusters);
+	if (ret < 0)
+		return ret;
+
+	num_blocks = num_clusters << cluster_bits;
+	num_blocks >>= block_bits;
+	
+	ret = create_group(groupname, &groupnum);
+	if (ret != -EEXIST && ret != 0)
+		return ret;
+
+	ret = activate_group(groupname, groupdev, groupnum, block_bits, num_blocks, start_block);
+	if (ret < 0)
+		return ret;
+
+	ret = add_to_local_group(groupname, groupnum, my_nodenum);
+	if (ret != -EEXIST && ret != 0)
+		return ret;
+
+	/* at this point my node is heartbeating, so any other nodes 
+	 * joining right now must communicate with me */
+
+	while (1) {
+		ret = get_node_map(groupnum, (char *)pre_nodemap);
+		if (ret < 0)
+			return ret;
+		if (ocfs2_test_bit(my_nodenum, (char *)pre_nodemap)) {
+			printf("found myself (%u) in nodemap! continuing...\n", my_nodenum);
+			break;
+		} else {
+			printf("have not yet found myself (%u) in nodemap...\n", my_nodenum);
+		}
+		/* TODO: set this to the default hb interval. 2 seconds right now */
+		sleep(2);
+	}
+
+	/* now that we see ourself heartbeating, take a look
+	 * at ALL of the nodes that seem to be heartbeating 
+	 * on this device.  add them here and have them add
+	 * me there... */
+	ret = get_raw_node_map(groupnum, groupdev, block_bits, num_blocks, start_block, (char *)pre_nodemap);
+	if (ret < 0)
+		return ret;
+
+again:
+	/* go create this group and add this node on every other node I see */	
+	start = 0;
+	while (1) {
+		next = ocfs2_find_next_bit_set((unsigned long *)pre_nodemap, NM_MAX_NODES, start);
+		if (next >= NM_MAX_NODES) {
+			break;
+		}
+		if (next != my_nodenum) {
+			/* add remote node here... */
+			ret = add_to_local_group(groupname, groupnum, next);
+			if (ret != -EEXIST && ret != 0)
+				return ret;
+
+			/* ...and add this node there */
+			ret = create_remote_group(groupname, next);
+			if (ret != 0 && ret != -EEXIST) {
+				printf("create_remote_group: node=%u returned %d!\n",
+				       next, ret);
+				break;
+			}
+		}
+		start = next + 1;
+	}
+	if (ret != 0 && ret != -EEXIST)
+		return ret;
+
+	printf("done creating remote groups\n");
+
+	/* grab the nodemap again and look for changes */
+	ret = get_raw_node_map(groupnum, groupdev, block_bits, num_blocks, start_block, (char *)post_nodemap);
+	if (ret < 0)
+		return ret;
+	
+	printf("checking raw node map again.....\n");
+
+	if (memcmp(pre_nodemap, post_nodemap, sizeof(pre_nodemap)) == 0) {
+		/* nothing changed.  we are DONE! */
+		printf("woot. nothing changed. all done\n");
+		return 0;
+	}
+		
+	printf("something changed\n");
+		
+	/* something changed */
+	for (i=0; i<8; i++) {
+		post_nodemap[i] &= ~pre_nodemap[i];
+		pre_nodemap[i] = post_nodemap[i];
+		post_nodemap[i] = 0;
+	}
+
+	/* keep going while there are still nodes to contact */
+	if (ocfs2_find_next_bit_set((unsigned long *)pre_nodemap, NM_MAX_NODES, 0) < NM_MAX_NODES)
+		goto again;
+	
+	printf("ah nothing left to care about ... leaving\n");
+
+	return 0;
+}
+
+int get_my_nodenum(__u16 *nodenum)
+{
+	FILE *file;
+	int ret = -EINVAL;
+	int retval=-EINVAL, num;
+	nm_op *op = (nm_op *)op_buf;
+
+	memset(op_buf, 0, PAGE_SIZE);
+	op->magic = NM_OP_MAGIC;
+	op->opcode = NM_OP_GET_GLOBAL_NODE_NUM;
+	
+	*nodenum = 255;
+
+	file = fopen(CLUSTER_FILE, "r+");
+	if (!file)
+		return -errno;
+	if (fwrite((char *)op, sizeof(nm_op), 1, file) != 1)
+		goto done;
+	if (fscanf(file, "%d: %d", &retval, &num) != 2 ||
+	    retval != 0 || num < 0 || num > 255) {
+		ret = -EINVAL;
+		goto done;
+	}
+	*nodenum = num;
+	ret = 0;	
+done:	
+	fclose(file);
+	return ret;
+}
+
+int create_group(char *uuid, __u16 *group_num)
+{
+	FILE *file;
+	int ret = -EINVAL, retval;
+	int groupnum = NM_INVALID_SLOT_NUM;
+	nm_op *op = (nm_op *)op_buf;
+	struct stat st;
+	char fname[100];
+
+	if (strlen(uuid) != CLUSTER_DISK_UUID_LEN)
+		return -EINVAL;
+
+	sprintf(fname, "/proc/cluster/nm/%s", uuid);
+	if (stat(fname, &st) == 0) {
+		*group_num = st.st_ino - NM_GROUP_INODE_START;
+		return -EEXIST;
+	}
+	
+	*group_num = NM_INVALID_SLOT_NUM;
+
+	memset(op_buf, 0, PAGE_SIZE);
+	op->magic = NM_OP_MAGIC;
+	op->opcode = NM_OP_CREATE_GROUP;
+
+	op->arg_u.gc.group_num = NM_INVALID_SLOT_NUM;
+	strcpy(op->arg_u.gc.name, uuid);
+	strcpy(op->arg_u.gc.disk_uuid, uuid);
+
+	file = fopen(CLUSTER_FILE, "r+");
+	if (!file)
+		return -errno;
+	
+	if (fwrite((char *)op, sizeof(nm_op), 1, file) != 1)
+		goto done;
+
+	if (fscanf(file, "%d: group %d", &retval, &groupnum) != 2) {
+		ret = -EINVAL;
+		goto done;
+	}
+	ret = retval;
+	if ((ret == 0 || ret == -EEXIST) &&
+	    groupnum >= 0 && groupnum < NM_INVALID_SLOT_NUM)
+		*group_num = groupnum;
+		
+done:	
+	fclose(file);
+	return ret;
+}
+
+
+int add_to_local_group(char *uuid, __u16 group_num, __u16 node_num)
+{
+	FILE *file;
+	int ret = -EINVAL, retval;
+	nm_op *op = (nm_op *)op_buf;
+	char fname[100];
+	DIR *dir;
+	struct dirent *de;
+	
+	if (strlen(uuid) != CLUSTER_DISK_UUID_LEN)
+		return -EINVAL;
+
+	sprintf(fname, "/proc/cluster/nm/%s", uuid);
+	dir = opendir(fname);
+	if (dir) {
+		while ((de = readdir(dir)) != NULL) {
+			if (de->d_ino - NM_NODE_INODE_START == node_num) {
+				closedir(dir);
+				return -EEXIST;
+			}
+		}
+		closedir(dir);
+	}
+
+	memset(op_buf, 0, PAGE_SIZE);
+	op->magic = NM_OP_MAGIC;
+	op->opcode = NM_OP_ADD_GROUP_NODE;
+	op->arg_u.gc.group_num = group_num;
+	op->arg_u.gc.node_num = node_num;
+	op->arg_u.gc.slot_num = node_num;
+
+	file = fopen(GROUP_FILE, "r+");
+	if (!file)
+		return -errno;
+	
+	if (fwrite((char *)op, sizeof(nm_op), 1, file) != 1)
+		goto done;
+
+	if (fscanf(file, "%d: node", &retval) != 1) {
+		ret = -EINVAL;
+		goto done;
+	}
+	ret = retval;
+		
+done:	
+	fclose(file);
+	return ret;
+}
+
+int activate_group(char *group_name, char *group_dev, __u16 group_num, 
+		   __u32 block_bits, __u64 num_blocks, __u64 start_block)
+{
+	int dev_fd = -1;
+	int ret = -EINVAL, retval;
+	FILE *file;
+	hb_op *op;
+
+	printf("starting disk heartbeat...\n");
+	
+	memset(op_buf, 0, PAGE_SIZE);
+	op = (hb_op *)op_buf;
+	op->magic = HB_OP_MAGIC;
+	op->opcode = HB_OP_START_DISK_HEARTBEAT;
+	op->group_num = group_num;
+	strcpy(op->disk_uuid, group_name);
+	op->bits = block_bits;
+	op->blocks = num_blocks;
+	op->start = start_block;
+	
+	dev_fd = open(group_dev, O_RDWR);
+	if (dev_fd == -1)
+		return -errno;
+	op->fd = dev_fd;
+
+	file = fopen(HEARTBEAT_DISK_FILE, "r+");
+	if (!file)
+		return -errno;
+	
+	if (fwrite((char *)op, sizeof(hb_op), 1, file) != 1)
+		goto done;
+
+	if (fscanf(file, "%d: ", &retval) != 1) {
+		ret = -EINVAL;
+		goto done;
+	}
+	ret = 0;
+done:
+	/* hb will keep its own ref */
+	if (dev_fd != -1)
+		close(dev_fd);
+
+	fclose(file);
+	return 0;
+}
+
+
+int get_ocfs2_disk_hb_params(char *group_dev, __u32 *block_bits, __u32 *cluster_bits,
+			     __u64 *start_block, __u32 *num_clusters)
+{
+	int status = -EINVAL;
+	errcode_t ret = 0;
+	uint64_t blkno;
+	char *buf = NULL;
+	char *heartbeat_filename;
+	ocfs2_dinode *di;
+	ocfs2_extent_rec *rec;
+	ocfs2_filesys *fs = NULL;
+
+	ret = ocfs2_open(group_dev, OCFS2_FLAG_RO, 0, 0, &fs);
+	if (ret)
+		return status;
+
+	heartbeat_filename = sysfile_info[DLM_SYSTEM_INODE].name;
+	ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, heartbeat_filename,
+			   strlen(heartbeat_filename),  NULL, &blkno);
+	if (ret)
+		goto leave;
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	if (ret)
+		goto leave;
+	
+	ret = ocfs2_read_inode(fs, blkno, buf);
+	if (ret)
+		goto leave;
+
+	di = (ocfs2_dinode *)buf;
+	if (di->id2.i_list.l_tree_depth || 
+	    di->id2.i_list.l_next_free_rec != 1) {
+		goto leave;
+	}
+	rec = &(di->id2.i_list.l_recs[0]);
+	
+	*block_bits = OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
+	*cluster_bits = OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
+	*start_block = rec->e_blkno;
+	*num_clusters = rec->e_clusters;
+	status = 0;
+
+leave:
+	if (buf)
+		ocfs2_free(&buf);
+	if (fs)
+		ocfs2_close(fs);
+	return status;
+}
+
+int get_node_map(__u16 group_num, char *bitmap)
+{
+	FILE *file = NULL;
+	hb_op *op;
+	int ret = -EINVAL;
+	int retval;
+	
+	printf("getting node map...\n");
+	
+	memset(op_buf, 0, PAGE_SIZE);
+	op = (hb_op *)op_buf;
+	op->magic = HB_OP_MAGIC;
+	op->opcode = HB_OP_GET_NODE_MAP;
+	op->group_num = group_num;
+	
+	file = fopen(HEARTBEAT_DISK_FILE, "r+");
+	if (!file)
+		return -errno;
+	
+	if (fwrite((char *)op, sizeof(hb_op), 1, file) != 1)
+		goto done;
+
+	if (fscanf(file, "%d: ", &retval) != 1) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if (retval != 0) {
+		ret = retval;
+		goto done;
+	}
+	if (fread(bitmap, 1, (NM_MAX_NODES+7)/8, file) < (NM_MAX_NODES+7)/8) {
+		ret = -EINVAL;
+		goto done;
+	}
+	ret = 0;
+done:
+	fclose(file);
+	return ret;
+}
+
+
+int get_raw_node_map(__u16 groupnum, char *groupdev, __u32 block_bits, __u32 num_blocks, __u64 start_block, char *bitmap)
+{
+	int i;
+	int ret = -EINVAL;
+	char *buf = NULL, *tmpbuf;
+	hb_disk_heartbeat_block *times = NULL;
+
+	errcode_t err;
+	io_channel *channel;
+
+	
+	printf("getting raw node map...\n");
+
+	times = malloc(sizeof(hb_disk_heartbeat_block) * NM_MAX_NODES);
+	if (!times) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	err = io_open(groupdev, OCFS2_FLAG_RO, &channel);
+	if (err) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	err = io_set_blksize(channel, 1 << block_bits);
+	if (err) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	err = ocfs2_malloc_blocks(channel, (int)NM_MAX_NODES, &buf);
+	if (err) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	
+	err = io_read_block(channel, start_block, (int)NM_MAX_NODES, buf);
+	if (err) {
+		ret = -EIO;
+		if (err == OCFS2_ET_SHORT_READ)
+			ret = -EINVAL;
+		goto done;
+	}
+	
+	tmpbuf = buf;
+	for (i=0; i<NM_MAX_NODES; i++) {
+		times[i].time = ((hb_disk_heartbeat_block *)tmpbuf)->time;
+		tmpbuf += (1 << block_bits);
+	}
+
+	/* TODO: how long? */
+	sleep(4);
+
+	err = io_read_block(channel, start_block, (int)NM_MAX_NODES, buf);
+	if (err) {
+		ret = -EIO;
+		if (err == OCFS2_ET_SHORT_READ)
+			ret = -EINVAL;
+		goto done;
+	}
+
+	tmpbuf = buf;
+	for (i=0; i<NM_MAX_NODES; i++) {
+		printf("node: %d: before=%llu, after=%llu\n", i, times[i].time, ((hb_disk_heartbeat_block *)tmpbuf)->time);
+		if (times[i].time != ((hb_disk_heartbeat_block *)tmpbuf)->time) {
+			printf(" >>>>>  aha node %d seems to be up!\n", i);
+			ocfs2_set_bit(i, bitmap);
+		}
+		tmpbuf += (1 << block_bits);
+	}
+
+	ret = 0;
+done:
+
+	if (buf)
+		ocfs2_free(&buf);
+	io_close(channel);
+	if (times)
+		free(times);
+	return ret;
+}
+
+int create_remote_group(char *group_name, __u16 node)
+{
+	int ret, fd = -1, remote_node = -1;
+	gsd_ioc ioc;
+	char fname[100];
+	DIR *dir = NULL;
+	struct dirent *de = NULL;
+
+	printf("create_remote_group: name=%s, remote node=%u\n", group_name, node);
+
+	/* NOTE: this is a bit of a hack.  we actually normally would not
+	 * know which "global" node corresponds to this "group relative" node.
+	 * but for now, they directly match up. */
+	// sprintf(fname, "/proc/cluster/nm/%s/%03u", group_name, node);
+	
+	dir = opendir("/proc/cluster/nm");
+	if (!dir) {
+		ret = -EINVAL;
+		goto leave;
+	}
+
+	fname[0]=0;
+	while ((de = readdir(dir)) != NULL) {
+		if (de->d_ino - NM_NODE_INODE_START == node) {
+			sprintf(fname, "/proc/cluster/nm/%s", de->d_name);
+			break;
+		}
+	}
+	closedir(dir);
+	if (!fname[0]) {
+		ret = -EINVAL;
+		goto leave;
+	}
+	printf("found file %s corresponding to node %u\n", fname, node);
+
+	/* open a file descriptor to the node we want to talk to */
+	remote_node = open(fname, O_RDONLY);
+	if (remote_node == -1) {
+		ret = -errno;
+		goto leave;
+	}
+	printf("fd for remote node=%d\n", remote_node);
+
+	/* TODO: move this over to a transaction file on the inode, eliminate the ioctl */
+	fd = open("/proc/cluster/net", O_RDONLY);
+	if (fd == -1) {
+		ret = -errno;
+		goto leave;
+	}
+
+	printf("fd for net ioctl file=%d\n", fd);
+
+	/* call an ioctl to create the group over there */
+	memset(&ioc, 0, sizeof(gsd_ioc));
+	ioc.fd = remote_node;
+	ioc.namelen = strlen(group_name);
+	memcpy(ioc.name, group_name, ioc.namelen);
+	if (ioctl(fd, GSD_IOC_CREATE_GROUP, &ioc) < 0) {
+		ret = -errno;
+		goto leave;
+	}
+	ret = ioc.status;
+	printf("create group ioctl returned ret=%d\n", ret);
+
+	if (ret != 0 && ret != -EEXIST)
+		goto leave;
+	
+	/* call an ioctl to add this node to the group over there */
+	memset(&ioc, 0, sizeof(gsd_ioc));
+	ioc.fd = remote_node;
+	ioc.namelen = strlen(group_name);
+	memcpy(ioc.name, group_name, ioc.namelen);
+	if (ioctl(fd, GSD_IOC_ADD_GROUP_NODE, &ioc) < 0) {
+		ret = -errno;
+		goto leave;
+	}
+	ret = ioc.status;
+	printf("add node ioctl returned ret=%d\n", ret);
+
+leave:
+	if (fd != -1)
+		close(fd);
+	if (remote_node != -1)
+		close(remote_node);
+	return ret;
+}



More information about the Ocfs2-tools-commits mailing list