dlm: master - dlm_tool: move files

David Teigland teigland at fedoraproject.org
Fri Sep 30 21:57:38 UTC 2011


Gitweb:        http://git.fedorahosted.org/git/dlm.git?p=dlm.git;a=commitdiff;h=8d03f2e225d3a2109def78ddf9c7bed13575ea2e
Commit:        8d03f2e225d3a2109def78ddf9c7bed13575ea2e
Parent:        2a1ff7ea5b9c86e3e6ade2ea8da1bd22e2b61749
Author:        David Teigland <teigland at redhat.com>
AuthorDate:    Fri Sep 30 14:56:23 2011 -0500
Committer:     David Teigland <teigland at redhat.com>
CommitterDate: Fri Sep 30 14:56:23 2011 -0500

dlm_tool: move files

Signed-off-by: David Teigland <teigland at redhat.com>
---
 dlm/man/dlm_tool.8          |   98 ----
 dlm/tool/main.c             | 1334 -------------------------------------------
 dlm_controld/dlm_daemon.h   |    2 +-
 dlm_controld/endian.h       |   68 ---
 dlm_controld/linux_endian.h |   68 +++
 dlm_tool/Makefile           |   54 ++
 dlm_tool/dlm_tool.8         |   98 ++++
 dlm_tool/main.c             | 1334 +++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 1555 insertions(+), 1501 deletions(-)

diff --git a/dlm/man/dlm_tool.8 b/dlm/man/dlm_tool.8
deleted file mode 100644
index df9aa64..0000000
--- a/dlm/man/dlm_tool.8
+++ /dev/null
@@ -1,98 +0,0 @@
-.TH DLM_TOOL 8 2009-01-20 cluster cluster
-
-.SH NAME
-dlm_tool \- a utility for the dlm and dlm_controld daemon
-
-.SH SYNOPSIS
-.B dlm_tool
-[COMMAND] [OPTIONS]
-[
-.I name
-]
-
-.SH DESCRIPTION
-.TP
-.B ls
-Display internal dlm_controld state about lockspaces.
-
-.TP
-.B dump
-Dump dlm_controld debug buffer.
-
-.TP
-.B log_plock
-Dump dlm_controld plock debug buffer.
-
-.TP
-.BI plocks " name"
-Dump posix locks from dlm_controld for the lockspace.
-
-.TP
-.BI lockdump " name"
-Minimal display of locks from the lockspace.
-
-.TP
-.BI lockdebug " name"
-Extended display of locks from the lockspace.
-
-.TP
-.BI join " name"
-Join a lockspace.
-
-.TP
-.BI leave " name"
-Leave a lockspace.
-
-.TP
-.BI deadlock_check " name"
-Start a deadlock detection cycle for the lockspace.
-
-.SH OPTIONS
-.TP
-.B \-n
-Show all node information in ls.
-
-.TP
-.BI \-d " num"
-Resource directory enabled (1) or disabled (0) during join. Default 0.
-
-.TP
-.BI \-e " num"
-Exclusive create off/on (0/1) in join. Default 0.
-
-.TP
-.BI \-f " num"
-FS memory allocation off/on (0/1) in join. Default 0.
-
-.TP
-.BI \-m " mode"
-The permission mode (in octal) of the lockspace device created by join.
-Default 0600.
-
-.TP
-.B \-M
-Dump MSTCPY locks in addition to locks held by local processes.
-
-.TP
-.B \-s
-Summary following lockdebug output (experimental, format may change).
-
-.TP
-.B \-v
-Verbose lockdebug output.
-
-.TP
-.B \-w
-Wide lockdebug output.
-
-.TP
-.B \-h
-Print a help message describing available options, then exit.
-
-.TP
-.B \-V
-Print program version information, then exit.
-
-.SH SEE ALSO
-.BR dlm_controld (8)
-
diff --git a/dlm/tool/main.c b/dlm/tool/main.c
deleted file mode 100644
index 236463f..0000000
--- a/dlm/tool/main.c
+++ /dev/null
@@ -1,1334 +0,0 @@
-#include "clusterautoconfig.h"
-
-#include <sys/types.h>
-#include <sys/un.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stddef.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-#include <netinet/in.h>
-
-#include <linux/dlmconstants.h>
-#include "libdlm.h"
-#include "libdlmcontrol.h"
-#include "copyright.cf"
-
-#define LKM_IVMODE -1
-
-#define OP_JOIN				1
-#define OP_LEAVE			2
-#define OP_JOINLEAVE			3
-#define OP_LIST				4
-#define OP_DEADLOCK_CHECK		5
-#define OP_DUMP				6
-#define OP_PLOCKS			7
-#define OP_LOCKDUMP			8
-#define OP_LOCKDEBUG			9
-#define OP_LOG_PLOCK			10
-
-static char *prog_name;
-static char *lsname;
-static int operation;
-static int opt_ind;
-static int ls_all_nodes = 0;
-static int opt_dir = 0;
-static int opt_excl = 0;
-static int opt_fs = 0;
-static int dump_mstcpy = 0;
-static mode_t create_mode = 0600;
-static int verbose;
-static int wide;
-static int summarize;
-
-#define MAX_LS 128
-#define MAX_NODES 128
-
-/* from linux/fs/dlm/dlm_internal.h */
-#define DLM_LKSTS_WAITING       1
-#define DLM_LKSTS_GRANTED       2
-#define DLM_LKSTS_CONVERT       3
-
-#define DLM_MSG_REQUEST         1
-#define DLM_MSG_CONVERT         2
-#define DLM_MSG_UNLOCK          3
-#define DLM_MSG_CANCEL          4
-#define DLM_MSG_REQUEST_REPLY   5
-#define DLM_MSG_CONVERT_REPLY   6
-#define DLM_MSG_UNLOCK_REPLY    7
-#define DLM_MSG_CANCEL_REPLY    8
-#define DLM_MSG_GRANT           9
-#define DLM_MSG_BAST            10
-#define DLM_MSG_LOOKUP          11
-#define DLM_MSG_REMOVE          12
-#define DLM_MSG_LOOKUP_REPLY    13
-#define DLM_MSG_PURGE           14
-
-
-struct dlmc_lockspace lss[MAX_LS];
-struct dlmc_node nodes[MAX_NODES];
-
-struct rinfo {
-	int print_granted;
-	int print_convert;
-	int print_waiting;
-	int print_lookup;
-	int namelen;
-	int nodeid;
-	int lvb;
-	unsigned int lkb_count;
-	unsigned int lkb_granted;
-	unsigned int lkb_convert;
-	unsigned int lkb_waiting;
-	unsigned int lkb_lookup;
-	unsigned int lkb_wait_msg;
-	unsigned int lkb_master_copy;
-	unsigned int lkb_local_copy;
-	unsigned int lkb_process_copy;
-};
-
-struct summary {
-	unsigned int rsb_total;
-	unsigned int rsb_with_lvb;
-	unsigned int rsb_no_locks;
-	unsigned int rsb_lookup;
-	unsigned int rsb_master;
-	unsigned int rsb_local;
-	unsigned int rsb_nodeid_error;
-	unsigned int lkb_count;
-	unsigned int lkb_granted;
-	unsigned int lkb_convert;
-	unsigned int lkb_waiting;
-	unsigned int lkb_lookup;
-	unsigned int lkb_wait_msg;
-	unsigned int lkb_master_copy;
-	unsigned int lkb_local_copy;
-	unsigned int lkb_process_copy;
-	unsigned int expect_replies;
-};
-
-static const char *mode_str(int mode)
-{
-	switch (mode) {
-	case -1:
-		return "IV";
-	case LKM_NLMODE:
-		return "NL";
-	case LKM_CRMODE:
-		return "CR";
-	case LKM_CWMODE:
-		return "CW";
-	case LKM_PRMODE:
-		return "PR";
-	case LKM_PWMODE:
-		return "PW";
-	case LKM_EXMODE:
-		return "EX";
-	}
-	return "??";
-}
-
-static const char *msg_str(int type)
-{
-	switch (type) {
-	case DLM_MSG_REQUEST:
-		return "request";
-	case DLM_MSG_CONVERT:
-		return "convert";
-	case DLM_MSG_UNLOCK:
-		return "unlock ";
-	case DLM_MSG_CANCEL:
-		return "cancel ";
-	case DLM_MSG_REQUEST_REPLY:
-		return "r_reply";
-	case DLM_MSG_CONVERT_REPLY:
-		return "c_reply";
-	case DLM_MSG_UNLOCK_REPLY:
-		return "u_reply";
-	case DLM_MSG_CANCEL_REPLY:
-		return "c_reply";
-	case DLM_MSG_GRANT:
-		return "grant  ";
-	case DLM_MSG_BAST:
-		return "bast   ";
-	case DLM_MSG_LOOKUP:
-		return "lookup ";
-	case DLM_MSG_REMOVE:
-		return "remove ";
-	case DLM_MSG_LOOKUP_REPLY:
-		return "l_reply";
-	case DLM_MSG_PURGE:
-		return "purge  ";
-	default:
-		return "unknown";
-	}
-}
-
-static void print_usage(void)
-{
-	printf("Usage:\n");
-	printf("\n");
-	printf("dlm_tool [options] [join | leave | lockdump | lockdebug |\n"
-	       "                    ls | dump | log_plock | plocks |\n"
-	       "                    deadlock_check]\n");
-	printf("\n");
-	printf("Options:\n");
-	printf("  -n               Show all node information in ls\n");
-	printf("  -d <n>           Resource directory off/on (0/1) in join, default 0\n");
-	printf("  -e <n>           Exclusive create off/on (0/1) in join, default 0\n");
-	printf("  -f <n>           FS memory allocation off/on (0/1) in join, default 0\n");
-	printf("  -m <mode>        Permission mode for lockspace device (octal), default 0600\n");
-	printf("  -M               Print MSTCPY locks in lockdump\n"
-	       "                   (remote locks that are locally mastered)\n");
-	printf("  -s               Summary following lockdebug output\n");
-	printf("                   (experimental, format not fixed)\n");
-	printf("  -v               Verbose lockdebug output\n");
-	printf("  -w               Wide lockdebug output\n");
-	printf("  -h               Print this help, then exit\n");
-	printf("  -V               Print program version information, then exit\n");
-	printf("\n");
-}
-
-#define OPTION_STRING "MhVnd:m:e:f:vws"
-
-static void decode_arguments(int argc, char **argv)
-{
-	int cont = 1;
-	int optchar;
-	int need_lsname;
-	char modebuf[8];
-
-	while (cont) {
-		optchar = getopt(argc, argv, OPTION_STRING);
-
-		switch (optchar) {
-		case 'd':
-			opt_dir = atoi(optarg);
-			break;
-
-		case 'e':
-			opt_excl = atoi(optarg);
-			break;
-
-		case 'f':
-			opt_fs = atoi(optarg);
-			break;
-
-		case 'm':
-			memset(modebuf, 0, sizeof(modebuf));
-			snprintf(modebuf, 8, "%s", optarg);
-			sscanf(modebuf, "%o", &create_mode);
-			break;
-
-		case 'M':
-			dump_mstcpy = 1;
-			break;
-
-		case 'n':
-			ls_all_nodes = 1;
-			break;
-
-		case 's':
-			summarize = 1;
-			break;
-
-		case 'v':
-			verbose = 1;
-			break;
-
-		case 'w':
-			wide = 1;
-			break;
-
-		case 'h':
-			print_usage();
-			exit(EXIT_SUCCESS);
-			break;
-
-		case 'V':
-			printf("%s %s (built %s %s)\n",
-				prog_name, VERSION, __DATE__, __TIME__);
-			printf("%s\n", REDHAT_COPYRIGHT);
-			exit(EXIT_SUCCESS);
-			break;
-
-		case ':':
-		case '?':
-			fprintf(stderr, "Please use '-h' for usage.\n");
-			exit(EXIT_FAILURE);
-			break;
-
-		case EOF:
-			cont = 0;
-			break;
-
-		default:
-			fprintf(stderr, "unknown option: %c\n", optchar);
-			exit(EXIT_FAILURE);
-			break;
-		};
-	}
-
-	need_lsname = 1;
-
-	while (optind < argc) {
-
-		/*
-		 * libdlm
-		 */
-
-		if (!strncmp(argv[optind], "join", 4) &&
-		    (strlen(argv[optind]) == 4)) {
-			operation = OP_JOIN;
-			opt_ind = optind + 1;
-			break;
-		} else if (!strncmp(argv[optind], "leave", 5) &&
-			   (strlen(argv[optind]) == 5)) {
-			operation = OP_LEAVE;
-			opt_ind = optind + 1;
-			break;
-		} else if (!strncmp(argv[optind], "joinleave", 9) &&
-			   (strlen(argv[optind]) == 9)) {
-			operation = OP_JOINLEAVE;
-			opt_ind = optind + 1;
-			break;
-		}
-
-		/*
-		 * libdlmcontrol
-		 */
-
-		else if (!strncmp(argv[optind], "ls", 2) &&
-			   (strlen(argv[optind]) == 2)) {
-			operation = OP_LIST;
-			opt_ind = optind + 1;
-			need_lsname = 0;
-			break;
-		} else if (!strncmp(argv[optind], "deadlock_check", 14) &&
-			   (strlen(argv[optind]) == 14)) {
-			operation = OP_DEADLOCK_CHECK;
-			opt_ind = optind + 1;
-			break;
-		} else if (!strncmp(argv[optind], "dump", 4) &&
-			   (strlen(argv[optind]) == 4)) {
-			operation = OP_DUMP;
-			opt_ind = optind + 1;
-			need_lsname = 0;
-			break;
-		} else if (!strncmp(argv[optind], "plocks", 6) &&
-			   (strlen(argv[optind]) == 6)) {
-			operation = OP_PLOCKS;
-			opt_ind = optind + 1;
-			break;
-		} else if (!strncmp(argv[optind], "log_plock", 9) &&
-			   (strlen(argv[optind]) == 9)) {
-			operation = OP_LOG_PLOCK;
-			opt_ind = optind + 1;
-			need_lsname = 0;
-			break;
-		}
-
-		/*
-		 * debugfs
-		 */
-
-		else if (!strncmp(argv[optind], "lockdump", 8) &&
-			   (strlen(argv[optind]) == 8)) {
-			operation = OP_LOCKDUMP;
-			opt_ind = optind + 1;
-			break;
-		} else if (!strncmp(argv[optind], "lockdebug", 9) &&
-			   (strlen(argv[optind]) == 9)) {
-			operation = OP_LOCKDEBUG;
-			opt_ind = optind + 1;
-			break;
-		}
-		optind++;
-	}
-
-	if (!operation || !opt_ind) {
-		print_usage();
-		exit(EXIT_FAILURE);
-	}
-
-	if (optind < argc - 1)
-		lsname = argv[opt_ind];
-	else if (need_lsname) {
-		fprintf(stderr, "lockspace name required\n");
-		exit(EXIT_FAILURE);
-	}
-}
-
-static int do_write(int fd, void *buf, size_t count)
-{
-	int rv, off = 0;
-
- retry:
-	rv = write(fd, (char *)buf + off, count);
-	if (rv == -1 && errno == EINTR)
-		goto retry;
-	if (rv < 0)
-		return rv;
-
-	if (rv != count) {
-		count -= rv;
-		off += rv;
-		goto retry;
-	}
-	return 0;
-}
-
-static char *flag_str(uint32_t flags)
-{
-	static char join_flags[128];
-
-	memset(join_flags, 0, sizeof(join_flags));
-
-	strcat(join_flags, "flags ");
-
-	if (flags & DLM_LSFL_NODIR)
-		strcat(join_flags, "NODIR ");
-
-	if (flags & DLM_LSFL_NEWEXCL)
-		strcat(join_flags, "NEWEXCL ");
-
-	if (flags & DLM_LSFL_FS)
-		strcat(join_flags, "FS ");
-
-	return join_flags;
-}
-
-static void do_join(char *name)
-{
-	dlm_lshandle_t *dh;
-	uint32_t flags = 0;
-
-	if (!opt_dir)
-		flags |= DLM_LSFL_NODIR;
-
-	if (opt_excl)
-		flags |= DLM_LSFL_NEWEXCL;
-
-	if (opt_fs)
-		flags |= DLM_LSFL_FS;
-
-	printf("Joining lockspace \"%s\" permission %o %s\n",
-	       name, create_mode, flags ? flag_str(flags) : "");
-	fflush(stdout);
-
-	dh = dlm_new_lockspace(name, create_mode, flags);
-	if (!dh) {
-		fprintf(stderr, "dlm_new_lockspace %s error %d\n",
-			name, errno);
-		exit(-1);
-	}
-
-	dlm_close_lockspace(dh);
-	/* there's no autofree so the ls should stay around */
-	printf("done\n");
-}
-
-static void do_leave(char *name)
-{
-	dlm_lshandle_t *dh;
-
-	printf("Leaving lockspace \"%s\"\n", name);
-	fflush(stdout);
-
-	dh = dlm_open_lockspace(name);
-	if (!dh) {
-		fprintf(stderr, "dlm_open_lockspace %s error %p %d\n",
-			name, dh, errno);
-		exit(-1);
-	}
-
-	dlm_release_lockspace(name, dh, 1);
-	printf("done\n");
-}
-
-static char *pr_master(int nodeid)
-{
-	static char buf[64];
-
-	memset(buf, 0, sizeof(buf));
-
-	if (nodeid > 0)
-		sprintf(buf, "Local %d", nodeid);
-	else if (!nodeid)
-		sprintf(buf, "Master");
-	else if (nodeid == -1)
-		sprintf(buf, "Lookup");
-
-	return buf;
-}
-
-static char *pr_extra(uint32_t flags, int root_list, int recover_list,
-	       int recover_locks_count, char *first_lkid)
-{
-	static char buf[128];
-	int first = 0;
-
-	memset(buf, 0, sizeof(buf));
-
-	if (strcmp(first_lkid, "0"))
-		first = 1;
-
-	if (flags || first || root_list || recover_list || recover_locks_count)
-		sprintf(buf,
-		   "flags %08x first_lkid %s root %d recover %d locks %d",
-		   flags, first_lkid, root_list, recover_list, recover_locks_count);
-
-	return buf;
-}
-
-static void print_rsb(char *line, struct rinfo *ri)
-{
-	char type[4], namefmt[4], *p;
-	char addr[64];
-	char first_lkid[64];
-	int rv, nodeid, root_list, recover_list, recover_locks_count, namelen;
-	uint32_t flags;
-
-	rv = sscanf(line, "%s %s %d %s %u %d %d %u %u %s",
-		    type,
-		    addr,
-		    &nodeid,
-		    first_lkid,
-		    &flags,
-		    &root_list,
-		    &recover_list,
-		    &recover_locks_count,
-		    &namelen,
-		    namefmt);
-
-	if (rv != 10)
-		goto fail;
-
-	/* used for lkb prints */
-	ri->nodeid = nodeid;
-
-	ri->namelen = namelen;
-	
-	p = strchr(line, '\n');
-	if (!p)
-		goto fail;
-	*p = '\0';
-
-	p = strstr(line, namefmt);
-	if (!p)
-		goto fail;
-	p += 4;
-
-	strcat(addr, " ");
-
-	if (!strncmp(namefmt, "str", 3))
-		printf("Resource len %2d  \"%s\"\n", namelen, p);
-	else if (!strncmp(namefmt, "hex", 3))
-		printf("Resource len %2d hex %s\n", namelen, p);
-	else
-		goto fail;
-
-	printf("%-16s %s\n",
-		pr_master(nodeid),
-		pr_extra(flags, root_list, recover_list, recover_locks_count, first_lkid));
-	return;
-
- fail:
-	fprintf(stderr, "print_rsb error rv %d line \"%s\"\n", rv, line);
-}
-
-static void print_lvb(char *line)
-{
-	char lvb[1024];
-	char type[4];
-	int i, c, rv, lvblen;
-	uint32_t lvbseq;
-
-	memset(lvb, 0, 1024);
-
-	rv = sscanf(line, "%s %u %d %[0-9A-Fa-f ]", type, &lvbseq, &lvblen, lvb);
-
-	if (rv != 4) {
-		fprintf(stderr, "print_lvb error rv %d line \"%s\"\n", rv, line);
-		return;
-	}
-
-	printf("LVB len %d seq %u\n", lvblen, lvbseq);
-
-	for (c = 0, i = 0; ; i++) {
-		printf("%c", lvb[i]);
-		if (lvb[i] != ' ')
-			c++;
-		if (!wide && lvb[i] == ' ' && !(c % 32))
-			printf("\n");
-		if (c == (lvblen * 2))
-			break;
-	}
-	printf("\n");
-}
-
-struct lkb {
-	uint64_t xid, timestamp, time_bast;
-	uint32_t id, remid, exflags, flags, lvbseq;
-	int nodeid, ownpid, status, grmode, rqmode, highbast, rsb_lookup, wait_type;
-};
-
-static const char *pr_grmode(struct lkb *lkb)
-{
-	if (lkb->status == DLM_LKSTS_GRANTED || lkb->status == DLM_LKSTS_CONVERT)
-		return mode_str(lkb->grmode);
-	else if (lkb->status == DLM_LKSTS_WAITING || lkb->rsb_lookup)
-		return "--";
-	else
-		return "XX";
-}
-
-static const char *pr_rqmode(struct lkb *lkb)
-{
-	static char buf[5];
-
-	memset(buf, 0, sizeof(buf));
-
-	if (lkb->status == DLM_LKSTS_GRANTED) {
-		return "    ";
-	} else if (lkb->status == DLM_LKSTS_CONVERT ||
-		   lkb->status == DLM_LKSTS_WAITING ||
-		   lkb->rsb_lookup) {
-		sprintf(buf, "(%s)", mode_str(lkb->rqmode));
-		return buf;
-	} else {
-		return "(XX)";
-	}
-}
-
-static const char *pr_remote(struct lkb *lkb, struct rinfo *ri)
-{
-	static char buf[64];
-
-	memset(buf, 0, sizeof(buf));
-
-	if (!lkb->nodeid) {
-		return "                    ";
-	} else if (lkb->nodeid != ri->nodeid) {
-		sprintf(buf, "Remote: %3d %08x", lkb->nodeid, lkb->remid);
-		return buf;
-	} else {
-		sprintf(buf, "Master: %3d %08x", lkb->nodeid, lkb->remid);
-		return buf;
-	}
-}
-
-static const char *pr_wait(struct lkb *lkb)
-{
-	static char buf[16];
-
-	memset(buf, 0, sizeof(buf));
-
-	if (!lkb->wait_type) {
-		return "        ";
-	} else {
-		sprintf(buf, " wait %02d", lkb->wait_type);
-		return buf;
-	}
-}
-
-static char *pr_verbose(struct lkb *lkb)
-{
-	static char buf[128];
-
-	memset(buf, 0, sizeof(buf));
-
-	sprintf(buf, "time %016llu flags %08x %08x bast %d %llu",
-		(unsigned long long)lkb->timestamp,
-		lkb->exflags, lkb->flags, lkb->highbast,
-		(unsigned long long)lkb->time_bast);
-
-	return buf;
-}
-
-static void print_lkb(char *line, struct rinfo *ri)
-{
-	struct lkb lkb;
-	char type[4];
-	int rv;
-
-	rv = sscanf(line, "%s %x %d %x %u %"PRIu64" %x %x %d %d %d %d %d %d %u %"PRIu64" %"PRIu64,
-		    type,
-		    &lkb.id,
-		    &lkb.nodeid,
-		    &lkb.remid,
-		    &lkb.ownpid,
-		    &lkb.xid,
-		    &lkb.exflags,
-		    &lkb.flags,
-		    &lkb.status,
-		    &lkb.grmode,
-		    &lkb.rqmode,
-		    &lkb.highbast,
-		    &lkb.rsb_lookup,
-		    &lkb.wait_type,
-		    &lkb.lvbseq,
-		    &lkb.timestamp,
-		    &lkb.time_bast);
-
-	ri->lkb_count++;
-
-	if (lkb.status == DLM_LKSTS_GRANTED) {
-	       	if (!ri->print_granted++)
-			printf("Granted\n");
-		ri->lkb_granted++;
-	}
-	if (lkb.status == DLM_LKSTS_CONVERT) {
-		if (!ri->print_convert++)
-			printf("Convert\n");
-		ri->lkb_convert++;
-	}
-	if (lkb.status == DLM_LKSTS_WAITING) {
-	       	if (!ri->print_waiting++)
-			printf("Waiting\n");
-		ri->lkb_waiting++;
-	}
-	if (lkb.rsb_lookup) {
-	       	if (!ri->print_lookup++)
-			printf("Lookup\n");
-		ri->lkb_lookup++;
-	}
-
-	if (lkb.wait_type)
-		ri->lkb_wait_msg++;
-
-	if (!ri->nodeid) {
-		if (lkb.nodeid)
-			ri->lkb_master_copy++;
-		else
-			ri->lkb_local_copy++;
-	} else {
-		ri->lkb_process_copy++;
-	}
-
-	printf("%08x %s %s %s %s %s\n",
-	       lkb.id, pr_grmode(&lkb), pr_rqmode(&lkb),
-	       pr_remote(&lkb, ri), pr_wait(&lkb),
-	       (verbose && wide) ? pr_verbose(&lkb) : "");
-
-	if (verbose && !wide)
-		printf("%s\n", pr_verbose(&lkb));
-}
-
-static void clear_rinfo(struct rinfo *ri)
-{
-	memset(ri, 0, sizeof(struct rinfo));
-	ri->nodeid = -9;
-}
-
-static void count_rinfo(struct summary *s, struct rinfo *ri)
-{
-	/* the first time called */
-	if (!ri->namelen)
-		return;
-
-	s->rsb_total++;
-
-	if (ri->lvb)
-		s->rsb_with_lvb++;
-
-	if (!ri->lkb_count) {
-		s->rsb_no_locks++;
-		printf("no locks\n");
-	}
-
-	if (!ri->nodeid)
-		s->rsb_master++;
-	else if (ri->nodeid == -1)
-		s->rsb_lookup++;
-	else if (ri->nodeid > 0)
-		s->rsb_local++;
-	else
-		s->rsb_nodeid_error++;
-
-	s->lkb_count        += ri->lkb_count;
-	s->lkb_granted      += ri->lkb_granted;
-	s->lkb_convert      += ri->lkb_convert;
-	s->lkb_waiting      += ri->lkb_waiting;
-	s->lkb_lookup       += ri->lkb_lookup;
-	s->lkb_wait_msg     += ri->lkb_wait_msg;
-	s->lkb_master_copy  += ri->lkb_master_copy;
-	s->lkb_local_copy   += ri->lkb_local_copy;
-	s->lkb_process_copy += ri->lkb_process_copy;
-}
-
-static void print_summary(struct summary *s)
-{
-	printf("rsb\n");
-	printf("  total         %u\n", s->rsb_total);
-	printf("  master        %u\n", s->rsb_master);
-	printf("  remote master %u\n", s->rsb_local);
-	printf("  lookup master %u\n", s->rsb_lookup);
-	printf("  with lvb      %u\n", s->rsb_with_lvb);
-	printf("  with no locks %u\n", s->rsb_no_locks);
-	printf("  nodeid error  %u\n", s->rsb_nodeid_error);
-	printf("\n");
-
-	printf("lkb\n");
-	printf("  total         %u\n", s->lkb_count);
-	printf("  granted       %u\n", s->lkb_granted);
-	printf("  convert       %u\n", s->lkb_convert);
-	printf("  waiting       %u\n", s->lkb_waiting);
-	printf("  local copy    %u\n", s->lkb_local_copy);
-	printf("  master copy   %u\n", s->lkb_master_copy);
-	printf("  process copy  %u\n", s->lkb_process_copy);
-	printf("  rsb lookup    %u\n", s->lkb_lookup);
-	printf("  wait message  %u\n", s->lkb_wait_msg);
-	printf("  expect reply  %u\n", s->expect_replies);
-}
-
-#define LOCK_LINE_MAX 1024
-
-static void do_waiters(char *name, struct summary *sum)
-{
-	FILE *file;
-	char path[PATH_MAX];
-	char line[LOCK_LINE_MAX];
-	char rname[65];
-	int header = 0;
-	int i, j, spaces;
-	int rv, nodeid, wait_type;
-	uint32_t id;
-
-	snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_waiters", name);
-
-	file = fopen(path, "r");
-	if (!file)
-		return;
-
-	while (fgets(line, LOCK_LINE_MAX, file)) {
-		if (!header) {
-			printf("\n");
-			printf("Expecting reply\n");
-			header = 1;
-		}
-
-		rv = sscanf(line, "%x %d %d",
-			    &id, &wait_type, &nodeid);
-
-		if (rv != 3) {
-			printf("waiters: %s", line);
-			continue;
-		}
-
-		/* parse the resource name from the remainder of the line */
-		j = 0;
-		spaces = 0;
-
-		for (i = 0; i < LOCK_LINE_MAX; i++) {
-			if (line[i] == '\n')
-				break;
-			if (spaces == 3) {
-				rname[j++] = line[i];
-				if (j == (sizeof(rname) - 1))
-					break;
-			} else if (line[i] == ' ') {
-				spaces++;
-			}
-		}
-
-		printf("nodeid %2d msg %s lkid %08x resource \"%s\"\n",
-		       nodeid, msg_str(wait_type), id, rname);
-
-		sum->expect_replies++;
-	}
-	fclose(file);
-}
-
-static void do_lockdebug(char *name)
-{
-	struct summary summary;
-	struct rinfo info;
-	FILE *file;
-	char path[PATH_MAX];
-	char line[LOCK_LINE_MAX];
-	int old = 0;
-
-	snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_all", name);
-
-	file = fopen(path, "r");
-	if (!file) {
-		snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s", name);
-		file = fopen(path, "r");
-		if (!file) {
-			fprintf(stderr, "can't open %s: %s\n", path, strerror(errno));
-			return;
-		}
-		old = 1;
-	}
-
-	memset(&summary, 0, sizeof(struct summary));
-	memset(&info, 0, sizeof(struct rinfo));
-
-	while (fgets(line, LOCK_LINE_MAX, file)) {
-
-		if (old)
-			goto raw;
-
-		if (!strncmp(line, "version", 7))
-			continue;
-
-		if (!strncmp(line, "rsb", 3)) {
-			count_rinfo(&summary, &info);
-			clear_rinfo(&info);
-			printf("\n");
-			print_rsb(line, &info);
-			continue;
-		}
-		
-		if (!strncmp(line, "lvb", 3)) {
-			print_lvb(line);
-			info.lvb = 1;
-			continue;
-		}
-		
-		if (!strncmp(line, "lkb", 3)) {
-			print_lkb(line, &info);
-			continue;
-		}
- raw:
-		printf("%s", line);
-	}
-	fclose(file);
-
-	do_waiters(name, &summary);
-
-	if (summarize) {
-		printf("\n");
-		print_summary(&summary);
-	}
-}
-
-static void parse_r_name(char *line, char *name)
-{
-	char *p;
-	int i = 0;
-	int begin = 0;
-
-	for (p = line; ; p++) {
-		if (*p == '"') {
-			if (begin)
-				break;
-			begin = 1;
-			continue;
-		}
-		if (begin)
-			name[i++] = *p;
-	}
-}
-
-static void do_lockdump(char *name)
-{
-	FILE *file;
-	char path[PATH_MAX];
-	char line[LOCK_LINE_MAX];
-	char r_name[65];
-	int r_nodeid;
-	int r_len;
-	int rv;
-	unsigned int time;
-	unsigned long long xid;
-	uint32_t	id;
-	int		nodeid;
-	uint32_t	remid;
-	int		ownpid;
-	uint32_t	exflags;
-	uint32_t	flags;
-	int8_t		status;
-	int8_t		grmode;
-	int8_t		rqmode;
-
-	snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_locks", name);
-
-	file = fopen(path, "r");
-	if (!file) {
-		fprintf(stderr, "can't open %s: %s\n", path, strerror(errno));
-		return;
-	}
-
-	/* skip the header on the first line */
-	if (!fgets(line, LOCK_LINE_MAX, file))
-		return;
-
-	while (fgets(line, LOCK_LINE_MAX, file)) {
-		rv = sscanf(line, "%x %d %x %u %llu %x %x %hhd %hhd %hhd %u %d %d",
-		       &id,
-		       &nodeid,
-		       &remid,
-		       &ownpid,
-		       &xid,
-		       &exflags,
-		       &flags,
-		       &status,
-		       &grmode,
-		       &rqmode,
-		       &time,
-		       &r_nodeid,
-		       &r_len);
-
-		if (rv != 13) {
-			fprintf(stderr, "invalid debugfs line %d: %s\n",
-				rv, line);
-			return;
-		}
-
-		memset(r_name, 0, sizeof(r_name));
-		parse_r_name(line, r_name);
-
-		/* don't print MSTCPY locks without -M */
-		if (!r_nodeid && nodeid) {
-			if (!dump_mstcpy)
-				continue;
-			printf("id %08x gr %s rq %s pid %u MSTCPY %d \"%s\"\n",
-				id, mode_str(grmode), mode_str(rqmode),
-				ownpid, nodeid, r_name);
-			continue;
-		}
-
-		/* A hack because dlm-kernel doesn't set rqmode back to IV when
-		   a NOQUEUE convert fails, which means in a lockdump it looks
-		   like a granted lock is still converting since rqmode is not
-		   IV.  (does it make sense to include status in the output,
-		   e.g. G,C,W?) */
-
-		if (status == DLM_LKSTS_GRANTED)
-			rqmode = LKM_IVMODE;
-
-		printf("id %08x gr %s rq %s pid %u master %d \"%s\"\n",
-			id, mode_str(grmode), mode_str(rqmode),
-			ownpid, nodeid, r_name);
-	}
-
-	fclose(file);
-}
-
-static char *dlmc_lf_str(uint32_t flags)
-{
-	static char str[128];
-	int i = 0;
-
-	memset(str, 0, sizeof(str));
-
-	if (flags & DLMC_LF_SAVE_PLOCKS) {
-		i++;
-		strcat(str, "save_plock");
-	}
-	if (flags & DLMC_LF_NEED_PLOCKS) {
-		strcat(str, i++ ? "," : "");
-		strcat(str, "need_plock");
-	}
-	if (flags & DLMC_LF_FS_REGISTERED) {
-		strcat(str, i++ ? "," : "");
-		strcat(str, "fs_reg");
-	}
-	if (flags & DLMC_LF_KERNEL_STOPPED) {
-		strcat(str, i++ ? "," : "");
-		strcat(str, "kern_stop");
-	}
-	if (flags & DLMC_LF_LEAVING) {
-		strcat(str, i++ ? "," : "");
-		strcat(str, "leave");
-	}
-	if (flags & DLMC_LF_JOINING) {
-		strcat(str, i++ ? "," : "");
-		strcat(str, "join");
-	}
-
-	return str;
-}
-
-static const char *nf_check_str(uint32_t flags)
-{
-	if (flags & DLMC_NF_CHECK_FENCING)
-		return "fence";
-
-	if (flags & DLMC_NF_CHECK_QUORUM)
-		return "quorum";
-
-	if (flags & DLMC_NF_CHECK_FS)
-		return "fs";
-
-	return "none";
-}
-
-static const char *condition_str(int cond)
-{
-	switch (cond) {
-	case 0:
-		return "";
-	case 1:
-		return "fencing";
-	case 2:
-		return "quorum";
-	case 3:
-		return "fs";
-	case 4:
-		return "pending";
-	default:
-		return "unknown";
-	}
-}
-
-static int node_compare(const void *va, const void *vb)
-{
-	const struct dlmc_node *a = va;
-	const struct dlmc_node *b = vb;
-
-	return a->nodeid - b->nodeid;
-}
-
-static void show_nodeids(int count, struct dlmc_node *nodes_in)
-{
-	struct dlmc_node *n = nodes_in;
-	int i;
-
-	for (i = 0; i < count; i++) {
-		printf("%d ", n->nodeid);
-		n++;
-	}
-	printf("\n");
-}
-
-static void show_ls(struct dlmc_lockspace *ls)
-{
-	int rv, node_count;
-
-	printf("name          %s\n", ls->name);
-	printf("id            0x%08x\n", ls->global_id);
-	printf("flags         0x%08x %s\n",
-		ls->flags, dlmc_lf_str(ls->flags));
-	printf("change        member %d joined %d remove %d failed %d seq %d,%d\n",
-		ls->cg_prev.member_count, ls->cg_prev.joined_count,
-		ls->cg_prev.remove_count, ls->cg_prev.failed_count,
-		ls->cg_prev.combined_seq, ls->cg_prev.seq);
-
-	node_count = 0;
-	memset(&nodes, 0, sizeof(nodes));
-	rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_MEMBERS,
-				  MAX_NODES, &node_count, nodes);
-	if (rv < 0) {
-		printf("members       error\n");
-		goto next;
-	}
-	qsort(nodes, node_count, sizeof(struct dlmc_node), node_compare);
-
-	printf("members       ");
-	show_nodeids(node_count, nodes);
-
- next:
-	if (!ls->cg_next.seq)
-		return;
-
-	printf("new change    member %d joined %d remove %d failed %d seq %d,%d\n",
-		ls->cg_next.member_count, ls->cg_next.joined_count,
-		ls->cg_next.remove_count, ls->cg_next.failed_count,
-	        ls->cg_next.combined_seq, ls->cg_next.seq);
-
-	printf("new status    wait_messages %d wait_condition %d %s\n",
-		ls->cg_next.wait_messages, ls->cg_next.wait_condition,
-		condition_str(ls->cg_next.wait_condition));
-
-	node_count = 0;
-	memset(&nodes, 0, sizeof(nodes));
-	rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_NEXT,
-				  MAX_NODES, &node_count, nodes);
-	if (rv < 0) {
-		printf("new members   error\n");
-		return;
-	}
-	qsort(nodes, node_count, sizeof(struct dlmc_node), node_compare);
-
-	printf("new members   ");
-	show_nodeids(node_count, nodes);
-}
-
-static int member_int(struct dlmc_node *n)
-{
-	if (n->flags & DLMC_NF_DISALLOWED)
-		return -1;
-	if (n->flags & DLMC_NF_MEMBER)
-		return 1;
-	return 0;
-}
-
-static void show_all_nodes(int count, struct dlmc_node *nodes_in)
-{
-	struct dlmc_node *n = nodes_in;
-	int i;
-
-	for (i = 0; i < count; i++) {
-		printf("nodeid %d member %d failed %d start %d seq_add %u seq_rem %u check %s\n",
-			n->nodeid,
-			member_int(n),
-			n->failed_reason,
-			(n->flags & DLMC_NF_START) ? 1 : 0,
-			n->added_seq,
-			n->removed_seq,
-			nf_check_str(n->flags));
-		n++;
-	}
-}
-
-static void do_list(char *name)
-{
-	struct dlmc_lockspace *ls;
-	int node_count;
-	int ls_count;
-	int rv;
-	int i;
-
-	memset(lss, 0, sizeof(lss));
-
-	if (name) {
-		ls_count = 1;
-		rv = dlmc_lockspace_info(name, lss);
-	} else {
-		rv = dlmc_lockspaces(MAX_LS, &ls_count, lss);
-	}
-
-	if (rv < 0)
-		exit(EXIT_FAILURE); /* dlm_controld probably not running */
-
-	if (ls_count)
-		printf("dlm lockspaces\n");
-
-	for (i = 0; i < ls_count; i++) {
-		ls = &lss[i];
-
-		show_ls(ls);
-
-		if (!ls_all_nodes)
-			goto next;
-
-		node_count = 0;
-		memset(&nodes, 0, sizeof(nodes));
-
-		rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_ALL,
-					  MAX_NODES, &node_count, nodes);
-		if (rv < 0) {
-			printf("all nodes error %d %d\n", rv, errno);
-			goto next;
-		}
-
-		qsort(nodes, node_count, sizeof(struct dlmc_node),node_compare);
-
-		printf("all nodes\n");
-		show_all_nodes(node_count, nodes);
- next:
-		printf("\n");
-	}
-}
-
-static void do_deadlock_check(char *name)
-{
-	dlmc_deadlock_check(name);
-}
-
-static void do_plocks(char *name)
-{
-	char buf[DLMC_DUMP_SIZE];
-
-	memset(buf, 0, sizeof(buf));
-
-	dlmc_dump_plocks(name, buf);
-
-	buf[DLMC_DUMP_SIZE-1] = '\0';
-
-	do_write(STDOUT_FILENO, buf, strlen(buf));
-}
-
-static void do_dump(void)
-{
-	char buf[DLMC_DUMP_SIZE];
-
-	memset(buf, 0, sizeof(buf));
-
-	dlmc_dump_debug(buf);
-
-	buf[DLMC_DUMP_SIZE-1] = '\0';
-
-	do_write(STDOUT_FILENO, buf, strlen(buf));
-	printf("\n");
-}
-
-static void do_log_plock(void)
-{
-	char buf[DLMC_DUMP_SIZE];
-
-	memset(buf, 0, sizeof(buf));
-
-	dlmc_dump_log_plock(buf);
-
-	buf[DLMC_DUMP_SIZE-1] = '\0';
-
-	do_write(STDOUT_FILENO, buf, strlen(buf));
-	printf("\n");
-}
-
-int main(int argc, char **argv)
-{
-	prog_name = argv[0];
-	decode_arguments(argc, argv);
-
-	switch (operation) {
-
-	/* calls to libdlm; pass a command to dlm-kernel */
-
-	case OP_JOIN:
-		do_join(lsname);
-		break;
-
-	case OP_LEAVE:
-		do_leave(lsname);
-		break;
-
-	case OP_JOINLEAVE:
-		do_join(lsname);
-		do_leave(lsname);
-		break;
-
-	/* calls to libdlmcontrol; pass a command/query to dlm_controld */
-
-	case OP_LIST:
-		do_list(lsname);
-		break;
-
-	case OP_DUMP:
-		do_dump();
-		break;
-
-	case OP_LOG_PLOCK:
-		do_log_plock();
-		break;
-
-	case OP_PLOCKS:
-		do_plocks(lsname);
-		break;
-
-	case OP_DEADLOCK_CHECK:
-		do_deadlock_check(lsname);
-		break;
-
-	/* calls to read debugfs; query info from dlm-kernel */
-
-	case OP_LOCKDUMP:
-		do_lockdump(lsname);
-		break;
-
-	case OP_LOCKDEBUG:
-		do_lockdebug(lsname);
-		break;
-	}
-	return 0;
-}
-
diff --git a/dlm_controld/dlm_daemon.h b/dlm_controld/dlm_daemon.h
index 70ad2d8..0c89f67 100644
--- a/dlm_controld/dlm_daemon.h
+++ b/dlm_controld/dlm_daemon.h
@@ -41,7 +41,7 @@
 #include "config.h"
 #include "list.h"
 #include "rbtree.h"
-#include "endian.h"
+#include "linux_endian.h"
 
 /* TODO: cleanup */
 #define CLUSTERVARLIB "/var/lib/cluster"
diff --git a/dlm_controld/endian.h b/dlm_controld/endian.h
deleted file mode 100644
index 43089d2..0000000
--- a/dlm_controld/endian.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef __LINUX_ENDIAN_DOT_H__
-#define __LINUX_ENDIAN_DOT_H__
-
-
-#include <endian.h>
-#include <byteswap.h>
-
-
-/*  I'm not sure which versions of alpha glibc/gcc are broken,
-    so fix all of them.  */
-#ifdef __alpha__
-#undef bswap_64
-static __inline__ unsigned long bswap_64(unsigned long x)
-{
-  unsigned int h = x >> 32;
-  unsigned int l = x;
-
-  h = bswap_32(h);
-  l = bswap_32(l);
-
-  return ((unsigned long)l << 32) | h;
-}
-#endif  /*  __alpha__  */
-
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-
-#define be16_to_cpu(x) (x)
-#define be32_to_cpu(x) (x)
-#define be64_to_cpu(x) (x)
-
-#define cpu_to_be16(x) (x)
-#define cpu_to_be32(x) (x)
-#define cpu_to_be64(x) (x)
-
-#define le16_to_cpu(x) (bswap_16((x)))
-#define le32_to_cpu(x) (bswap_32((x)))
-#define le64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_le16(x) (bswap_16((x)))
-#define cpu_to_le32(x) (bswap_32((x)))
-#define cpu_to_le64(x) (bswap_64((x)))
-
-#endif  /*  __BYTE_ORDER == __BIG_ENDIAN  */
-
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-
-#define be16_to_cpu(x) (bswap_16((x)))
-#define be32_to_cpu(x) (bswap_32((x)))
-#define be64_to_cpu(x) (bswap_64((x)))
-
-#define cpu_to_be16(x) (bswap_16((x)))
-#define cpu_to_be32(x) (bswap_32((x)))
-#define cpu_to_be64(x) (bswap_64((x))) 
-
-#define le16_to_cpu(x) (x)
-#define le32_to_cpu(x) (x)
-#define le64_to_cpu(x) (x)
-
-#define cpu_to_le16(x) (x)
-#define cpu_to_le32(x) (x)
-#define cpu_to_le64(x) (x)
-
-#endif  /*  __BYTE_ORDER == __LITTLE_ENDIAN  */
-
-
-#endif  /*  __LINUX_ENDIAN_DOT_H__  */
diff --git a/dlm_controld/linux_endian.h b/dlm_controld/linux_endian.h
new file mode 100644
index 0000000..43089d2
--- /dev/null
+++ b/dlm_controld/linux_endian.h
@@ -0,0 +1,68 @@
+#ifndef __LINUX_ENDIAN_DOT_H__
+#define __LINUX_ENDIAN_DOT_H__
+
+
+#include <endian.h>
+#include <byteswap.h>
+
+
+/*  I'm not sure which versions of alpha glibc/gcc are broken,
+    so fix all of them.  */
+#ifdef __alpha__
+#undef bswap_64
+static __inline__ unsigned long bswap_64(unsigned long x)
+{
+  unsigned int h = x >> 32;
+  unsigned int l = x;
+
+  h = bswap_32(h);
+  l = bswap_32(l);
+
+  return ((unsigned long)l << 32) | h;
+}
+#endif  /*  __alpha__  */
+
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+
+#define be16_to_cpu(x) (x)
+#define be32_to_cpu(x) (x)
+#define be64_to_cpu(x) (x)
+
+#define cpu_to_be16(x) (x)
+#define cpu_to_be32(x) (x)
+#define cpu_to_be64(x) (x)
+
+#define le16_to_cpu(x) (bswap_16((x)))
+#define le32_to_cpu(x) (bswap_32((x)))
+#define le64_to_cpu(x) (bswap_64((x)))
+
+#define cpu_to_le16(x) (bswap_16((x)))
+#define cpu_to_le32(x) (bswap_32((x)))
+#define cpu_to_le64(x) (bswap_64((x)))
+
+#endif  /*  __BYTE_ORDER == __BIG_ENDIAN  */
+
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+#define be16_to_cpu(x) (bswap_16((x)))
+#define be32_to_cpu(x) (bswap_32((x)))
+#define be64_to_cpu(x) (bswap_64((x)))
+
+#define cpu_to_be16(x) (bswap_16((x)))
+#define cpu_to_be32(x) (bswap_32((x)))
+#define cpu_to_be64(x) (bswap_64((x))) 
+
+#define le16_to_cpu(x) (x)
+#define le32_to_cpu(x) (x)
+#define le64_to_cpu(x) (x)
+
+#define cpu_to_le16(x) (x)
+#define cpu_to_le32(x) (x)
+#define cpu_to_le64(x) (x)
+
+#endif  /*  __BYTE_ORDER == __LITTLE_ENDIAN  */
+
+
+#endif  /*  __LINUX_ENDIAN_DOT_H__  */
diff --git a/dlm_tool/Makefile b/dlm_tool/Makefile
new file mode 100644
index 0000000..9f24a24
--- /dev/null
+++ b/dlm_tool/Makefile
@@ -0,0 +1,54 @@
+BIN_TARGET = dlm_tool
+MAN_TARGET = dlm_tool.8
+
+BIN_SOURCE = main.c
+
+BIN_CFLAGS += -D_GNU_SOURCE -g \
+	-Wall \
+	-Wformat \
+	-Wformat-security \
+	-Wmissing-prototypes \
+	-Wnested-externs \
+	-Wpointer-arith \
+	-Wextra -Wshadow \
+	-Wcast-align \
+	-Wwrite-strings \
+	-Waggregate-return \
+	-Wstrict-prototypes \
+	-Winline \
+	-Wredundant-decls \
+	-Wno-sign-compare \
+	-Wno-unused-parameter \
+	-Wp,-D_FORTIFY_SOURCE=2 \
+	-fexceptions \
+	-fasynchronous-unwind-tables \
+	-fdiagnostics-show-option \
+
+BIN_CFLAGS += -fPIE -DPIE
+BIN_CFLAGS += -I../include -I../dlm/libdlm -I../dlm_controld
+
+BIN_LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie
+BIN_LDFLAGS += -lpthread -ldlm -ldlmcontrol
+
+all: $(BIN_TARGET)
+
+$(BIN_TARGET): $(BIN_SOURCE)
+	$(CC) $(BIN_CFLAGS) $(BIN_LDFLAGS) $(BIN_SOURCE) -o $@
+
+clean:
+	rm -f *.o *.so *.so.* $(BIN_TARGET)
+
+
+INSTALL=$(shell which install)
+
+DESTDIR=
+BINDIR=/usr/sbin
+MANDIR=/usr/share/man
+
+.PHONY: install
+install: all
+	$(INSTALL) -d $(DESTDIR)/$(BINDIR)
+	$(INSTALL) -d $(DESTDIR)/$(MANDIR)/man8
+	$(INSTALL) -c -m 755 $(BIN_TARGET) $(DESTDIR)/$(BINDIR)
+	$(INSTALL) -m 644 $(MAN_TARGET) $(DESTDIR)/$(MANDIR)/man8/
+
diff --git a/dlm_tool/dlm_tool.8 b/dlm_tool/dlm_tool.8
new file mode 100644
index 0000000..df9aa64
--- /dev/null
+++ b/dlm_tool/dlm_tool.8
@@ -0,0 +1,98 @@
+.TH DLM_TOOL 8 2009-01-20 cluster cluster
+
+.SH NAME
+dlm_tool \- a utility for the dlm and dlm_controld daemon
+
+.SH SYNOPSIS
+.B dlm_tool
+[COMMAND] [OPTIONS]
+[
+.I name
+]
+
+.SH DESCRIPTION
+.TP
+.B ls
+Display internal dlm_controld state about lockspaces.
+
+.TP
+.B dump
+Dump dlm_controld debug buffer.
+
+.TP
+.B log_plock
+Dump dlm_controld plock debug buffer.
+
+.TP
+.BI plocks " name"
+Dump posix locks from dlm_controld for the lockspace.
+
+.TP
+.BI lockdump " name"
+Minimal display of locks from the lockspace.
+
+.TP
+.BI lockdebug " name"
+Extended display of locks from the lockspace.
+
+.TP
+.BI join " name"
+Join a lockspace.
+
+.TP
+.BI leave " name"
+Leave a lockspace.
+
+.TP
+.BI deadlock_check " name"
+Start a deadlock detection cycle for the lockspace.
+
+.SH OPTIONS
+.TP
+.B \-n
+Show all node information in ls.
+
+.TP
+.BI \-d " num"
+Resource directory enabled (1) or disabled (0) during join. Default 0.
+
+.TP
+.BI \-e " num"
+Exclusive create off/on (0/1) in join. Default 0.
+
+.TP
+.BI \-f " num"
+FS memory allocation off/on (0/1) in join. Default 0.
+
+.TP
+.BI \-m " mode"
+The permission mode (in octal) of the lockspace device created by join.
+Default 0600.
+
+.TP
+.B \-M
+Dump MSTCPY locks in addition to locks held by local processes.
+
+.TP
+.B \-s
+Summary following lockdebug output (experimental, format may change).
+
+.TP
+.B \-v
+Verbose lockdebug output.
+
+.TP
+.B \-w
+Wide lockdebug output.
+
+.TP
+.B \-h
+Print a help message describing available options, then exit.
+
+.TP
+.B \-V
+Print program version information, then exit.
+
+.SH SEE ALSO
+.BR dlm_controld (8)
+
diff --git a/dlm_tool/main.c b/dlm_tool/main.c
new file mode 100644
index 0000000..4df930a
--- /dev/null
+++ b/dlm_tool/main.c
@@ -0,0 +1,1334 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <inttypes.h>
+#include <netinet/in.h>
+
+#include <linux/dlmconstants.h>
+#include "libdlm.h"
+#include "libdlmcontrol.h"
+#include "copyright.cf"
+
+#define LKM_IVMODE -1
+
+#define OP_JOIN				1
+#define OP_LEAVE			2
+#define OP_JOINLEAVE			3
+#define OP_LIST				4
+#define OP_DEADLOCK_CHECK		5
+#define OP_DUMP				6
+#define OP_PLOCKS			7
+#define OP_LOCKDUMP			8
+#define OP_LOCKDEBUG			9
+#define OP_LOG_PLOCK			10
+
+static char *prog_name;
+static char *lsname;
+static int operation;
+static int opt_ind;
+static int ls_all_nodes = 0;
+static int opt_dir = 0;
+static int opt_excl = 0;
+static int opt_fs = 0;
+static int dump_mstcpy = 0;
+static mode_t create_mode = 0600;
+static int verbose;
+static int wide;
+static int summarize;
+
+#define VERSION "master"
+
+#define MAX_LS 128
+#define MAX_NODES 128
+
+/* from linux/fs/dlm/dlm_internal.h */
+#define DLM_LKSTS_WAITING       1
+#define DLM_LKSTS_GRANTED       2
+#define DLM_LKSTS_CONVERT       3
+
+#define DLM_MSG_REQUEST         1
+#define DLM_MSG_CONVERT         2
+#define DLM_MSG_UNLOCK          3
+#define DLM_MSG_CANCEL          4
+#define DLM_MSG_REQUEST_REPLY   5
+#define DLM_MSG_CONVERT_REPLY   6
+#define DLM_MSG_UNLOCK_REPLY    7
+#define DLM_MSG_CANCEL_REPLY    8
+#define DLM_MSG_GRANT           9
+#define DLM_MSG_BAST            10
+#define DLM_MSG_LOOKUP          11
+#define DLM_MSG_REMOVE          12
+#define DLM_MSG_LOOKUP_REPLY    13
+#define DLM_MSG_PURGE           14
+
+
+struct dlmc_lockspace lss[MAX_LS];
+struct dlmc_node nodes[MAX_NODES];
+
+struct rinfo {
+	int print_granted;
+	int print_convert;
+	int print_waiting;
+	int print_lookup;
+	int namelen;
+	int nodeid;
+	int lvb;
+	unsigned int lkb_count;
+	unsigned int lkb_granted;
+	unsigned int lkb_convert;
+	unsigned int lkb_waiting;
+	unsigned int lkb_lookup;
+	unsigned int lkb_wait_msg;
+	unsigned int lkb_master_copy;
+	unsigned int lkb_local_copy;
+	unsigned int lkb_process_copy;
+};
+
+struct summary {
+	unsigned int rsb_total;
+	unsigned int rsb_with_lvb;
+	unsigned int rsb_no_locks;
+	unsigned int rsb_lookup;
+	unsigned int rsb_master;
+	unsigned int rsb_local;
+	unsigned int rsb_nodeid_error;
+	unsigned int lkb_count;
+	unsigned int lkb_granted;
+	unsigned int lkb_convert;
+	unsigned int lkb_waiting;
+	unsigned int lkb_lookup;
+	unsigned int lkb_wait_msg;
+	unsigned int lkb_master_copy;
+	unsigned int lkb_local_copy;
+	unsigned int lkb_process_copy;
+	unsigned int expect_replies;
+};
+
+static const char *mode_str(int mode)
+{
+	switch (mode) {
+	case -1:
+		return "IV";
+	case LKM_NLMODE:
+		return "NL";
+	case LKM_CRMODE:
+		return "CR";
+	case LKM_CWMODE:
+		return "CW";
+	case LKM_PRMODE:
+		return "PR";
+	case LKM_PWMODE:
+		return "PW";
+	case LKM_EXMODE:
+		return "EX";
+	}
+	return "??";
+}
+
+static const char *msg_str(int type)
+{
+	switch (type) {
+	case DLM_MSG_REQUEST:
+		return "request";
+	case DLM_MSG_CONVERT:
+		return "convert";
+	case DLM_MSG_UNLOCK:
+		return "unlock ";
+	case DLM_MSG_CANCEL:
+		return "cancel ";
+	case DLM_MSG_REQUEST_REPLY:
+		return "r_reply";
+	case DLM_MSG_CONVERT_REPLY:
+		return "c_reply";
+	case DLM_MSG_UNLOCK_REPLY:
+		return "u_reply";
+	case DLM_MSG_CANCEL_REPLY:
+		return "c_reply";
+	case DLM_MSG_GRANT:
+		return "grant  ";
+	case DLM_MSG_BAST:
+		return "bast   ";
+	case DLM_MSG_LOOKUP:
+		return "lookup ";
+	case DLM_MSG_REMOVE:
+		return "remove ";
+	case DLM_MSG_LOOKUP_REPLY:
+		return "l_reply";
+	case DLM_MSG_PURGE:
+		return "purge  ";
+	default:
+		return "unknown";
+	}
+}
+
+static void print_usage(void)
+{
+	printf("Usage:\n");
+	printf("\n");
+	printf("dlm_tool [options] [join | leave | lockdump | lockdebug |\n"
+	       "                    ls | dump | log_plock | plocks |\n"
+	       "                    deadlock_check]\n");
+	printf("\n");
+	printf("Options:\n");
+	printf("  -n               Show all node information in ls\n");
+	printf("  -d <n>           Resource directory off/on (0/1) in join, default 0\n");
+	printf("  -e <n>           Exclusive create off/on (0/1) in join, default 0\n");
+	printf("  -f <n>           FS memory allocation off/on (0/1) in join, default 0\n");
+	printf("  -m <mode>        Permission mode for lockspace device (octal), default 0600\n");
+	printf("  -M               Print MSTCPY locks in lockdump\n"
+	       "                   (remote locks that are locally mastered)\n");
+	printf("  -s               Summary following lockdebug output\n");
+	printf("                   (experimental, format not fixed)\n");
+	printf("  -v               Verbose lockdebug output\n");
+	printf("  -w               Wide lockdebug output\n");
+	printf("  -h               Print this help, then exit\n");
+	printf("  -V               Print program version information, then exit\n");
+	printf("\n");
+}
+
+#define OPTION_STRING "MhVnd:m:e:f:vws"
+
+static void decode_arguments(int argc, char **argv)
+{
+	int cont = 1;
+	int optchar;
+	int need_lsname;
+	char modebuf[8];
+
+	while (cont) {
+		optchar = getopt(argc, argv, OPTION_STRING);
+
+		switch (optchar) {
+		case 'd':
+			opt_dir = atoi(optarg);
+			break;
+
+		case 'e':
+			opt_excl = atoi(optarg);
+			break;
+
+		case 'f':
+			opt_fs = atoi(optarg);
+			break;
+
+		case 'm':
+			memset(modebuf, 0, sizeof(modebuf));
+			snprintf(modebuf, 8, "%s", optarg);
+			sscanf(modebuf, "%o", &create_mode);
+			break;
+
+		case 'M':
+			dump_mstcpy = 1;
+			break;
+
+		case 'n':
+			ls_all_nodes = 1;
+			break;
+
+		case 's':
+			summarize = 1;
+			break;
+
+		case 'v':
+			verbose = 1;
+			break;
+
+		case 'w':
+			wide = 1;
+			break;
+
+		case 'h':
+			print_usage();
+			exit(EXIT_SUCCESS);
+			break;
+
+		case 'V':
+			printf("%s %s (built %s %s)\n",
+				prog_name, VERSION, __DATE__, __TIME__);
+			printf("%s\n", REDHAT_COPYRIGHT);
+			exit(EXIT_SUCCESS);
+			break;
+
+		case ':':
+		case '?':
+			fprintf(stderr, "Please use '-h' for usage.\n");
+			exit(EXIT_FAILURE);
+			break;
+
+		case EOF:
+			cont = 0;
+			break;
+
+		default:
+			fprintf(stderr, "unknown option: %c\n", optchar);
+			exit(EXIT_FAILURE);
+			break;
+		};
+	}
+
+	need_lsname = 1;
+
+	while (optind < argc) {
+
+		/*
+		 * libdlm
+		 */
+
+		if (!strncmp(argv[optind], "join", 4) &&
+		    (strlen(argv[optind]) == 4)) {
+			operation = OP_JOIN;
+			opt_ind = optind + 1;
+			break;
+		} else if (!strncmp(argv[optind], "leave", 5) &&
+			   (strlen(argv[optind]) == 5)) {
+			operation = OP_LEAVE;
+			opt_ind = optind + 1;
+			break;
+		} else if (!strncmp(argv[optind], "joinleave", 9) &&
+			   (strlen(argv[optind]) == 9)) {
+			operation = OP_JOINLEAVE;
+			opt_ind = optind + 1;
+			break;
+		}
+
+		/*
+		 * libdlmcontrol
+		 */
+
+		else if (!strncmp(argv[optind], "ls", 2) &&
+			   (strlen(argv[optind]) == 2)) {
+			operation = OP_LIST;
+			opt_ind = optind + 1;
+			need_lsname = 0;
+			break;
+		} else if (!strncmp(argv[optind], "deadlock_check", 14) &&
+			   (strlen(argv[optind]) == 14)) {
+			operation = OP_DEADLOCK_CHECK;
+			opt_ind = optind + 1;
+			break;
+		} else if (!strncmp(argv[optind], "dump", 4) &&
+			   (strlen(argv[optind]) == 4)) {
+			operation = OP_DUMP;
+			opt_ind = optind + 1;
+			need_lsname = 0;
+			break;
+		} else if (!strncmp(argv[optind], "plocks", 6) &&
+			   (strlen(argv[optind]) == 6)) {
+			operation = OP_PLOCKS;
+			opt_ind = optind + 1;
+			break;
+		} else if (!strncmp(argv[optind], "log_plock", 9) &&
+			   (strlen(argv[optind]) == 9)) {
+			operation = OP_LOG_PLOCK;
+			opt_ind = optind + 1;
+			need_lsname = 0;
+			break;
+		}
+
+		/*
+		 * debugfs
+		 */
+
+		else if (!strncmp(argv[optind], "lockdump", 8) &&
+			   (strlen(argv[optind]) == 8)) {
+			operation = OP_LOCKDUMP;
+			opt_ind = optind + 1;
+			break;
+		} else if (!strncmp(argv[optind], "lockdebug", 9) &&
+			   (strlen(argv[optind]) == 9)) {
+			operation = OP_LOCKDEBUG;
+			opt_ind = optind + 1;
+			break;
+		}
+		optind++;
+	}
+
+	if (!operation || !opt_ind) {
+		print_usage();
+		exit(EXIT_FAILURE);
+	}
+
+	if (optind < argc - 1)
+		lsname = argv[opt_ind];
+	else if (need_lsname) {
+		fprintf(stderr, "lockspace name required\n");
+		exit(EXIT_FAILURE);
+	}
+}
+
+static int do_write(int fd, void *buf, size_t count)
+{
+	int rv, off = 0;
+
+ retry:
+	rv = write(fd, (char *)buf + off, count);
+	if (rv == -1 && errno == EINTR)
+		goto retry;
+	if (rv < 0)
+		return rv;
+
+	if (rv != count) {
+		count -= rv;
+		off += rv;
+		goto retry;
+	}
+	return 0;
+}
+
+static char *flag_str(uint32_t flags)
+{
+	static char join_flags[128];
+
+	memset(join_flags, 0, sizeof(join_flags));
+
+	strcat(join_flags, "flags ");
+
+	if (flags & DLM_LSFL_NODIR)
+		strcat(join_flags, "NODIR ");
+
+	if (flags & DLM_LSFL_NEWEXCL)
+		strcat(join_flags, "NEWEXCL ");
+
+	if (flags & DLM_LSFL_FS)
+		strcat(join_flags, "FS ");
+
+	return join_flags;
+}
+
+static void do_join(char *name)
+{
+	dlm_lshandle_t *dh;
+	uint32_t flags = 0;
+
+	if (!opt_dir)
+		flags |= DLM_LSFL_NODIR;
+
+	if (opt_excl)
+		flags |= DLM_LSFL_NEWEXCL;
+
+	if (opt_fs)
+		flags |= DLM_LSFL_FS;
+
+	printf("Joining lockspace \"%s\" permission %o %s\n",
+	       name, create_mode, flags ? flag_str(flags) : "");
+	fflush(stdout);
+
+	dh = dlm_new_lockspace(name, create_mode, flags);
+	if (!dh) {
+		fprintf(stderr, "dlm_new_lockspace %s error %d\n",
+			name, errno);
+		exit(-1);
+	}
+
+	dlm_close_lockspace(dh);
+	/* there's no autofree so the ls should stay around */
+	printf("done\n");
+}
+
+static void do_leave(char *name)
+{
+	dlm_lshandle_t *dh;
+
+	printf("Leaving lockspace \"%s\"\n", name);
+	fflush(stdout);
+
+	dh = dlm_open_lockspace(name);
+	if (!dh) {
+		fprintf(stderr, "dlm_open_lockspace %s error %p %d\n",
+			name, dh, errno);
+		exit(-1);
+	}
+
+	dlm_release_lockspace(name, dh, 1);
+	printf("done\n");
+}
+
+static char *pr_master(int nodeid)
+{
+	static char buf[64];
+
+	memset(buf, 0, sizeof(buf));
+
+	if (nodeid > 0)
+		sprintf(buf, "Local %d", nodeid);
+	else if (!nodeid)
+		sprintf(buf, "Master");
+	else if (nodeid == -1)
+		sprintf(buf, "Lookup");
+
+	return buf;
+}
+
+static char *pr_extra(uint32_t flags, int root_list, int recover_list,
+	       int recover_locks_count, char *first_lkid)
+{
+	static char buf[128];
+	int first = 0;
+
+	memset(buf, 0, sizeof(buf));
+
+	if (strcmp(first_lkid, "0"))
+		first = 1;
+
+	if (flags || first || root_list || recover_list || recover_locks_count)
+		sprintf(buf,
+		   "flags %08x first_lkid %s root %d recover %d locks %d",
+		   flags, first_lkid, root_list, recover_list, recover_locks_count);
+
+	return buf;
+}
+
+static void print_rsb(char *line, struct rinfo *ri)
+{
+	char type[4], namefmt[4], *p;
+	char addr[64];
+	char first_lkid[64];
+	int rv, nodeid, root_list, recover_list, recover_locks_count, namelen;
+	uint32_t flags;
+
+	rv = sscanf(line, "%s %s %d %s %u %d %d %u %u %s",
+		    type,
+		    addr,
+		    &nodeid,
+		    first_lkid,
+		    &flags,
+		    &root_list,
+		    &recover_list,
+		    &recover_locks_count,
+		    &namelen,
+		    namefmt);
+
+	if (rv != 10)
+		goto fail;
+
+	/* used for lkb prints */
+	ri->nodeid = nodeid;
+
+	ri->namelen = namelen;
+	
+	p = strchr(line, '\n');
+	if (!p)
+		goto fail;
+	*p = '\0';
+
+	p = strstr(line, namefmt);
+	if (!p)
+		goto fail;
+	p += 4;
+
+	strcat(addr, " ");
+
+	if (!strncmp(namefmt, "str", 3))
+		printf("Resource len %2d  \"%s\"\n", namelen, p);
+	else if (!strncmp(namefmt, "hex", 3))
+		printf("Resource len %2d hex %s\n", namelen, p);
+	else
+		goto fail;
+
+	printf("%-16s %s\n",
+		pr_master(nodeid),
+		pr_extra(flags, root_list, recover_list, recover_locks_count, first_lkid));
+	return;
+
+ fail:
+	fprintf(stderr, "print_rsb error rv %d line \"%s\"\n", rv, line);
+}
+
+static void print_lvb(char *line)
+{
+	char lvb[1024];
+	char type[4];
+	int i, c, rv, lvblen;
+	uint32_t lvbseq;
+
+	memset(lvb, 0, 1024);
+
+	rv = sscanf(line, "%s %u %d %[0-9A-Fa-f ]", type, &lvbseq, &lvblen, lvb);
+
+	if (rv != 4) {
+		fprintf(stderr, "print_lvb error rv %d line \"%s\"\n", rv, line);
+		return;
+	}
+
+	printf("LVB len %d seq %u\n", lvblen, lvbseq);
+
+	for (c = 0, i = 0; ; i++) {
+		printf("%c", lvb[i]);
+		if (lvb[i] != ' ')
+			c++;
+		if (!wide && lvb[i] == ' ' && !(c % 32))
+			printf("\n");
+		if (c == (lvblen * 2))
+			break;
+	}
+	printf("\n");
+}
+
+struct lkb {
+	uint64_t xid, timestamp, time_bast;
+	uint32_t id, remid, exflags, flags, lvbseq;
+	int nodeid, ownpid, status, grmode, rqmode, highbast, rsb_lookup, wait_type;
+};
+
+static const char *pr_grmode(struct lkb *lkb)
+{
+	if (lkb->status == DLM_LKSTS_GRANTED || lkb->status == DLM_LKSTS_CONVERT)
+		return mode_str(lkb->grmode);
+	else if (lkb->status == DLM_LKSTS_WAITING || lkb->rsb_lookup)
+		return "--";
+	else
+		return "XX";
+}
+
+static const char *pr_rqmode(struct lkb *lkb)
+{
+	static char buf[5];
+
+	memset(buf, 0, sizeof(buf));
+
+	if (lkb->status == DLM_LKSTS_GRANTED) {
+		return "    ";
+	} else if (lkb->status == DLM_LKSTS_CONVERT ||
+		   lkb->status == DLM_LKSTS_WAITING ||
+		   lkb->rsb_lookup) {
+		sprintf(buf, "(%s)", mode_str(lkb->rqmode));
+		return buf;
+	} else {
+		return "(XX)";
+	}
+}
+
+static const char *pr_remote(struct lkb *lkb, struct rinfo *ri)
+{
+	static char buf[64];
+
+	memset(buf, 0, sizeof(buf));
+
+	if (!lkb->nodeid) {
+		return "                    ";
+	} else if (lkb->nodeid != ri->nodeid) {
+		sprintf(buf, "Remote: %3d %08x", lkb->nodeid, lkb->remid);
+		return buf;
+	} else {
+		sprintf(buf, "Master: %3d %08x", lkb->nodeid, lkb->remid);
+		return buf;
+	}
+}
+
+static const char *pr_wait(struct lkb *lkb)
+{
+	static char buf[16];
+
+	memset(buf, 0, sizeof(buf));
+
+	if (!lkb->wait_type) {
+		return "        ";
+	} else {
+		sprintf(buf, " wait %02d", lkb->wait_type);
+		return buf;
+	}
+}
+
+static char *pr_verbose(struct lkb *lkb)
+{
+	static char buf[128];
+
+	memset(buf, 0, sizeof(buf));
+
+	sprintf(buf, "time %016llu flags %08x %08x bast %d %llu",
+		(unsigned long long)lkb->timestamp,
+		lkb->exflags, lkb->flags, lkb->highbast,
+		(unsigned long long)lkb->time_bast);
+
+	return buf;
+}
+
+static void print_lkb(char *line, struct rinfo *ri)
+{
+	struct lkb lkb;
+	char type[4];
+	int rv;
+
+	rv = sscanf(line, "%s %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu",
+		    type,
+		    &lkb.id,
+		    &lkb.nodeid,
+		    &lkb.remid,
+		    &lkb.ownpid,
+		    (unsigned long long *)&lkb.xid,
+		    &lkb.exflags,
+		    &lkb.flags,
+		    &lkb.status,
+		    &lkb.grmode,
+		    &lkb.rqmode,
+		    &lkb.highbast,
+		    &lkb.rsb_lookup,
+		    &lkb.wait_type,
+		    &lkb.lvbseq,
+		    (unsigned long long *)&lkb.timestamp,
+		    (unsigned long long *)&lkb.time_bast);
+
+	ri->lkb_count++;
+
+	if (lkb.status == DLM_LKSTS_GRANTED) {
+	       	if (!ri->print_granted++)
+			printf("Granted\n");
+		ri->lkb_granted++;
+	}
+	if (lkb.status == DLM_LKSTS_CONVERT) {
+		if (!ri->print_convert++)
+			printf("Convert\n");
+		ri->lkb_convert++;
+	}
+	if (lkb.status == DLM_LKSTS_WAITING) {
+	       	if (!ri->print_waiting++)
+			printf("Waiting\n");
+		ri->lkb_waiting++;
+	}
+	if (lkb.rsb_lookup) {
+	       	if (!ri->print_lookup++)
+			printf("Lookup\n");
+		ri->lkb_lookup++;
+	}
+
+	if (lkb.wait_type)
+		ri->lkb_wait_msg++;
+
+	if (!ri->nodeid) {
+		if (lkb.nodeid)
+			ri->lkb_master_copy++;
+		else
+			ri->lkb_local_copy++;
+	} else {
+		ri->lkb_process_copy++;
+	}
+
+	printf("%08x %s %s %s %s %s\n",
+	       lkb.id, pr_grmode(&lkb), pr_rqmode(&lkb),
+	       pr_remote(&lkb, ri), pr_wait(&lkb),
+	       (verbose && wide) ? pr_verbose(&lkb) : "");
+
+	if (verbose && !wide)
+		printf("%s\n", pr_verbose(&lkb));
+}
+
+static void clear_rinfo(struct rinfo *ri)
+{
+	memset(ri, 0, sizeof(struct rinfo));
+	ri->nodeid = -9;
+}
+
+static void count_rinfo(struct summary *s, struct rinfo *ri)
+{
+	/* the first time called */
+	if (!ri->namelen)
+		return;
+
+	s->rsb_total++;
+
+	if (ri->lvb)
+		s->rsb_with_lvb++;
+
+	if (!ri->lkb_count) {
+		s->rsb_no_locks++;
+		printf("no locks\n");
+	}
+
+	if (!ri->nodeid)
+		s->rsb_master++;
+	else if (ri->nodeid == -1)
+		s->rsb_lookup++;
+	else if (ri->nodeid > 0)
+		s->rsb_local++;
+	else
+		s->rsb_nodeid_error++;
+
+	s->lkb_count        += ri->lkb_count;
+	s->lkb_granted      += ri->lkb_granted;
+	s->lkb_convert      += ri->lkb_convert;
+	s->lkb_waiting      += ri->lkb_waiting;
+	s->lkb_lookup       += ri->lkb_lookup;
+	s->lkb_wait_msg     += ri->lkb_wait_msg;
+	s->lkb_master_copy  += ri->lkb_master_copy;
+	s->lkb_local_copy   += ri->lkb_local_copy;
+	s->lkb_process_copy += ri->lkb_process_copy;
+}
+
+static void print_summary(struct summary *s)
+{
+	printf("rsb\n");
+	printf("  total         %u\n", s->rsb_total);
+	printf("  master        %u\n", s->rsb_master);
+	printf("  remote master %u\n", s->rsb_local);
+	printf("  lookup master %u\n", s->rsb_lookup);
+	printf("  with lvb      %u\n", s->rsb_with_lvb);
+	printf("  with no locks %u\n", s->rsb_no_locks);
+	printf("  nodeid error  %u\n", s->rsb_nodeid_error);
+	printf("\n");
+
+	printf("lkb\n");
+	printf("  total         %u\n", s->lkb_count);
+	printf("  granted       %u\n", s->lkb_granted);
+	printf("  convert       %u\n", s->lkb_convert);
+	printf("  waiting       %u\n", s->lkb_waiting);
+	printf("  local copy    %u\n", s->lkb_local_copy);
+	printf("  master copy   %u\n", s->lkb_master_copy);
+	printf("  process copy  %u\n", s->lkb_process_copy);
+	printf("  rsb lookup    %u\n", s->lkb_lookup);
+	printf("  wait message  %u\n", s->lkb_wait_msg);
+	printf("  expect reply  %u\n", s->expect_replies);
+}
+
+#define LOCK_LINE_MAX 1024
+
+static void do_waiters(char *name, struct summary *sum)
+{
+	FILE *file;
+	char path[PATH_MAX];
+	char line[LOCK_LINE_MAX];
+	char rname[65];
+	int header = 0;
+	int i, j, spaces;
+	int rv, nodeid, wait_type;
+	uint32_t id;
+
+	snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_waiters", name);
+
+	file = fopen(path, "r");
+	if (!file)
+		return;
+
+	while (fgets(line, LOCK_LINE_MAX, file)) {
+		if (!header) {
+			printf("\n");
+			printf("Expecting reply\n");
+			header = 1;
+		}
+
+		rv = sscanf(line, "%x %d %d",
+			    &id, &wait_type, &nodeid);
+
+		if (rv != 3) {
+			printf("waiters: %s", line);
+			continue;
+		}
+
+		/* parse the resource name from the remainder of the line */
+		j = 0;
+		spaces = 0;
+
+		for (i = 0; i < LOCK_LINE_MAX; i++) {
+			if (line[i] == '\n')
+				break;
+			if (spaces == 3) {
+				rname[j++] = line[i];
+				if (j == (sizeof(rname) - 1))
+					break;
+			} else if (line[i] == ' ') {
+				spaces++;
+			}
+		}
+
+		printf("nodeid %2d msg %s lkid %08x resource \"%s\"\n",
+		       nodeid, msg_str(wait_type), id, rname);
+
+		sum->expect_replies++;
+	}
+	fclose(file);
+}
+
+static void do_lockdebug(char *name)
+{
+	struct summary summary;
+	struct rinfo info;
+	FILE *file;
+	char path[PATH_MAX];
+	char line[LOCK_LINE_MAX];
+	int old = 0;
+
+	snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_all", name);
+
+	file = fopen(path, "r");
+	if (!file) {
+		snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s", name);
+		file = fopen(path, "r");
+		if (!file) {
+			fprintf(stderr, "can't open %s: %s\n", path, strerror(errno));
+			return;
+		}
+		old = 1;
+	}
+
+	memset(&summary, 0, sizeof(struct summary));
+	memset(&info, 0, sizeof(struct rinfo));
+
+	while (fgets(line, LOCK_LINE_MAX, file)) {
+
+		if (old)
+			goto raw;
+
+		if (!strncmp(line, "version", 7))
+			continue;
+
+		if (!strncmp(line, "rsb", 3)) {
+			count_rinfo(&summary, &info);
+			clear_rinfo(&info);
+			printf("\n");
+			print_rsb(line, &info);
+			continue;
+		}
+		
+		if (!strncmp(line, "lvb", 3)) {
+			print_lvb(line);
+			info.lvb = 1;
+			continue;
+		}
+		
+		if (!strncmp(line, "lkb", 3)) {
+			print_lkb(line, &info);
+			continue;
+		}
+ raw:
+		printf("%s", line);
+	}
+	fclose(file);
+
+	do_waiters(name, &summary);
+
+	if (summarize) {
+		printf("\n");
+		print_summary(&summary);
+	}
+}
+
+static void parse_r_name(char *line, char *name)
+{
+	char *p;
+	int i = 0;
+	int begin = 0;
+
+	for (p = line; ; p++) {
+		if (*p == '"') {
+			if (begin)
+				break;
+			begin = 1;
+			continue;
+		}
+		if (begin)
+			name[i++] = *p;
+	}
+}
+
+static void do_lockdump(char *name)
+{
+	FILE *file;
+	char path[PATH_MAX];
+	char line[LOCK_LINE_MAX];
+	char r_name[65];
+	int r_nodeid;
+	int r_len;
+	int rv;
+	unsigned int tm;
+	unsigned long long xid;
+	uint32_t	id;
+	int		nodeid;
+	uint32_t	remid;
+	int		ownpid;
+	uint32_t	exflags;
+	uint32_t	flags;
+	int8_t		status;
+	int8_t		grmode;
+	int8_t		rqmode;
+
+	snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_locks", name);
+
+	file = fopen(path, "r");
+	if (!file) {
+		fprintf(stderr, "can't open %s: %s\n", path, strerror(errno));
+		return;
+	}
+
+	/* skip the header on the first line */
+	if (!fgets(line, LOCK_LINE_MAX, file))
+		return;
+
+	while (fgets(line, LOCK_LINE_MAX, file)) {
+		rv = sscanf(line, "%x %d %x %u %llu %x %x %hhd %hhd %hhd %u %d %d",
+		       &id,
+		       &nodeid,
+		       &remid,
+		       &ownpid,
+		       &xid,
+		       &exflags,
+		       &flags,
+		       &status,
+		       &grmode,
+		       &rqmode,
+		       &tm,
+		       &r_nodeid,
+		       &r_len);
+
+		if (rv != 13) {
+			fprintf(stderr, "invalid debugfs line %d: %s\n",
+				rv, line);
+			return;
+		}
+
+		memset(r_name, 0, sizeof(r_name));
+		parse_r_name(line, r_name);
+
+		/* don't print MSTCPY locks without -M */
+		if (!r_nodeid && nodeid) {
+			if (!dump_mstcpy)
+				continue;
+			printf("id %08x gr %s rq %s pid %u MSTCPY %d \"%s\"\n",
+				id, mode_str(grmode), mode_str(rqmode),
+				ownpid, nodeid, r_name);
+			continue;
+		}
+
+		/* A hack because dlm-kernel doesn't set rqmode back to IV when
+		   a NOQUEUE convert fails, which means in a lockdump it looks
+		   like a granted lock is still converting since rqmode is not
+		   IV.  (does it make sense to include status in the output,
+		   e.g. G,C,W?) */
+
+		if (status == DLM_LKSTS_GRANTED)
+			rqmode = LKM_IVMODE;
+
+		printf("id %08x gr %s rq %s pid %u master %d \"%s\"\n",
+			id, mode_str(grmode), mode_str(rqmode),
+			ownpid, nodeid, r_name);
+	}
+
+	fclose(file);
+}
+
+static char *dlmc_lf_str(uint32_t flags)
+{
+	static char str[128];
+	int i = 0;
+
+	memset(str, 0, sizeof(str));
+
+	if (flags & DLMC_LF_SAVE_PLOCKS) {
+		i++;
+		strcat(str, "save_plock");
+	}
+	if (flags & DLMC_LF_NEED_PLOCKS) {
+		strcat(str, i++ ? "," : "");
+		strcat(str, "need_plock");
+	}
+	if (flags & DLMC_LF_FS_REGISTERED) {
+		strcat(str, i++ ? "," : "");
+		strcat(str, "fs_reg");
+	}
+	if (flags & DLMC_LF_KERNEL_STOPPED) {
+		strcat(str, i++ ? "," : "");
+		strcat(str, "kern_stop");
+	}
+	if (flags & DLMC_LF_LEAVING) {
+		strcat(str, i++ ? "," : "");
+		strcat(str, "leave");
+	}
+	if (flags & DLMC_LF_JOINING) {
+		strcat(str, i++ ? "," : "");
+		strcat(str, "join");
+	}
+
+	return str;
+}
+
+static const char *nf_check_str(uint32_t flags)
+{
+	if (flags & DLMC_NF_CHECK_FENCING)
+		return "fence";
+
+	if (flags & DLMC_NF_CHECK_QUORUM)
+		return "quorum";
+
+	if (flags & DLMC_NF_CHECK_FS)
+		return "fs";
+
+	return "none";
+}
+
+static const char *condition_str(int cond)
+{
+	switch (cond) {
+	case 0:
+		return "";
+	case 1:
+		return "fencing";
+	case 2:
+		return "quorum";
+	case 3:
+		return "fs";
+	case 4:
+		return "pending";
+	default:
+		return "unknown";
+	}
+}
+
+static int node_compare(const void *va, const void *vb)
+{
+	const struct dlmc_node *a = va;
+	const struct dlmc_node *b = vb;
+
+	return a->nodeid - b->nodeid;
+}
+
+static void show_nodeids(int count, struct dlmc_node *nodes_in)
+{
+	struct dlmc_node *n = nodes_in;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		printf("%d ", n->nodeid);
+		n++;
+	}
+	printf("\n");
+}
+
+static void show_ls(struct dlmc_lockspace *ls)
+{
+	int rv, node_count;
+
+	printf("name          %s\n", ls->name);
+	printf("id            0x%08x\n", ls->global_id);
+	printf("flags         0x%08x %s\n",
+		ls->flags, dlmc_lf_str(ls->flags));
+	printf("change        member %d joined %d remove %d failed %d seq %d,%d\n",
+		ls->cg_prev.member_count, ls->cg_prev.joined_count,
+		ls->cg_prev.remove_count, ls->cg_prev.failed_count,
+		ls->cg_prev.combined_seq, ls->cg_prev.seq);
+
+	node_count = 0;
+	memset(&nodes, 0, sizeof(nodes));
+	rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_MEMBERS,
+				  MAX_NODES, &node_count, nodes);
+	if (rv < 0) {
+		printf("members       error\n");
+		goto next;
+	}
+	qsort(nodes, node_count, sizeof(struct dlmc_node), node_compare);
+
+	printf("members       ");
+	show_nodeids(node_count, nodes);
+
+ next:
+	if (!ls->cg_next.seq)
+		return;
+
+	printf("new change    member %d joined %d remove %d failed %d seq %d,%d\n",
+		ls->cg_next.member_count, ls->cg_next.joined_count,
+		ls->cg_next.remove_count, ls->cg_next.failed_count,
+	        ls->cg_next.combined_seq, ls->cg_next.seq);
+
+	printf("new status    wait_messages %d wait_condition %d %s\n",
+		ls->cg_next.wait_messages, ls->cg_next.wait_condition,
+		condition_str(ls->cg_next.wait_condition));
+
+	node_count = 0;
+	memset(&nodes, 0, sizeof(nodes));
+	rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_NEXT,
+				  MAX_NODES, &node_count, nodes);
+	if (rv < 0) {
+		printf("new members   error\n");
+		return;
+	}
+	qsort(nodes, node_count, sizeof(struct dlmc_node), node_compare);
+
+	printf("new members   ");
+	show_nodeids(node_count, nodes);
+}
+
+static int member_int(struct dlmc_node *n)
+{
+	if (n->flags & DLMC_NF_DISALLOWED)
+		return -1;
+	if (n->flags & DLMC_NF_MEMBER)
+		return 1;
+	return 0;
+}
+
+static void show_all_nodes(int count, struct dlmc_node *nodes_in)
+{
+	struct dlmc_node *n = nodes_in;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		printf("nodeid %d member %d failed %d start %d seq_add %u seq_rem %u check %s\n",
+			n->nodeid,
+			member_int(n),
+			n->failed_reason,
+			(n->flags & DLMC_NF_START) ? 1 : 0,
+			n->added_seq,
+			n->removed_seq,
+			nf_check_str(n->flags));
+		n++;
+	}
+}
+
+static void do_list(char *name)
+{
+	struct dlmc_lockspace *ls;
+	int node_count;
+	int ls_count;
+	int rv;
+	int i;
+
+	memset(lss, 0, sizeof(lss));
+
+	if (name) {
+		ls_count = 1;
+		rv = dlmc_lockspace_info(name, lss);
+	} else {
+		rv = dlmc_lockspaces(MAX_LS, &ls_count, lss);
+	}
+
+	if (rv < 0)
+		exit(EXIT_FAILURE); /* dlm_controld probably not running */
+
+	if (ls_count)
+		printf("dlm lockspaces\n");
+
+	for (i = 0; i < ls_count; i++) {
+		ls = &lss[i];
+
+		show_ls(ls);
+
+		if (!ls_all_nodes)
+			goto next;
+
+		node_count = 0;
+		memset(&nodes, 0, sizeof(nodes));
+
+		rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_ALL,
+					  MAX_NODES, &node_count, nodes);
+		if (rv < 0) {
+			printf("all nodes error %d %d\n", rv, errno);
+			goto next;
+		}
+
+		qsort(nodes, node_count, sizeof(struct dlmc_node),node_compare);
+
+		printf("all nodes\n");
+		show_all_nodes(node_count, nodes);
+ next:
+		printf("\n");
+	}
+}
+
+static void do_deadlock_check(char *name)
+{
+	dlmc_deadlock_check(name);
+}
+
+static void do_plocks(char *name)
+{
+	char buf[DLMC_DUMP_SIZE];
+
+	memset(buf, 0, sizeof(buf));
+
+	dlmc_dump_plocks(name, buf);
+
+	buf[DLMC_DUMP_SIZE-1] = '\0';
+
+	do_write(STDOUT_FILENO, buf, strlen(buf));
+}
+
+static void do_dump(void)
+{
+	char buf[DLMC_DUMP_SIZE];
+
+	memset(buf, 0, sizeof(buf));
+
+	dlmc_dump_debug(buf);
+
+	buf[DLMC_DUMP_SIZE-1] = '\0';
+
+	do_write(STDOUT_FILENO, buf, strlen(buf));
+	printf("\n");
+}
+
+static void do_log_plock(void)
+{
+	char buf[DLMC_DUMP_SIZE];
+
+	memset(buf, 0, sizeof(buf));
+
+	dlmc_dump_log_plock(buf);
+
+	buf[DLMC_DUMP_SIZE-1] = '\0';
+
+	do_write(STDOUT_FILENO, buf, strlen(buf));
+	printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+	prog_name = argv[0];
+	decode_arguments(argc, argv);
+
+	switch (operation) {
+
+	/* calls to libdlm; pass a command to dlm-kernel */
+
+	case OP_JOIN:
+		do_join(lsname);
+		break;
+
+	case OP_LEAVE:
+		do_leave(lsname);
+		break;
+
+	case OP_JOINLEAVE:
+		do_join(lsname);
+		do_leave(lsname);
+		break;
+
+	/* calls to libdlmcontrol; pass a command/query to dlm_controld */
+
+	case OP_LIST:
+		do_list(lsname);
+		break;
+
+	case OP_DUMP:
+		do_dump();
+		break;
+
+	case OP_LOG_PLOCK:
+		do_log_plock();
+		break;
+
+	case OP_PLOCKS:
+		do_plocks(lsname);
+		break;
+
+	case OP_DEADLOCK_CHECK:
+		do_deadlock_check(lsname);
+		break;
+
+	/* calls to read debugfs; query info from dlm-kernel */
+
+	case OP_LOCKDUMP:
+		do_lockdump(lsname);
+		break;
+
+	case OP_LOCKDEBUG:
+		do_lockdebug(lsname);
+		break;
+	}
+	return 0;
+}
+


More information about the cluster-commits mailing list