[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