1    	/*
2    	 * Copyright 2004-2012 Red Hat, Inc.
3    	 *
4    	 * This copyrighted material is made available to anyone wishing to use,
5    	 * modify, copy, or redistribute it subject to the terms and conditions
6    	 * of the GNU General Public License v2 or (at your option) any later version.
7    	 */
8    	
9    	#include <unistd.h>
10   	#include <stdio.h>
11   	#include <stdint.h>
12   	#include <stddef.h>
13   	#include <stdlib.h>
14   	#include <fcntl.h>
15   	#include <string.h>
16   	#include <errno.h>
17   	#include <limits.h>
18   	#include <sys/types.h>
19   	#include <sys/un.h>
20   	#include <inttypes.h>
21   	#include <netinet/in.h>
22   	
23   	#include <linux/dlmconstants.h>
24   	#include "libdlm.h"
25   	#include "libdlmcontrol.h"
26   	#include "dlm_controld.h"
27   	#include "dlm_sand_sock.h"
28   	#include "copyright.cf"
29   	#include "version.cf"
30   	
31   	#define LKM_IVMODE -1
32   	
33   	#define OP_JOIN				1
34   	#define OP_LEAVE			2
35   	#define OP_JOINLEAVE			3
36   	#define OP_LIST				4
37   	#define OP_DEADLOCK_CHECK		5
38   	#define OP_DUMP_DEBUG			6
39   	#define OP_PLOCKS			7
40   	#define OP_LOCKDUMP			8
41   	#define OP_LOCKDEBUG			9
42   	#define OP_LOG_PLOCK			10
43   	#define OP_FENCE_ACK			11
44   	#define OP_DUMP_STATUS			12
45   	#define OP_DUMP_CONFIG			13
46   	#define OP_RUN				14
47   	#define OP_RUN_START			15
48   	#define OP_RUN_CHECK			16
49   	#define OP_RUN_CANCEL			17
50   	#define OP_RUN_LIST			18
51   	#define OP_DUMP_RUN			19
52   	#define OP_RELOAD_CONFIG		20
53   	#define OP_SET_CONFIG			21
54   	
55   	static char *prog_name;
56   	static char *lsname;
57   	static int operation;
58   	static int opt_ind;
59   	static int ls_all_nodes = 0;
60   	static int opt_excl = 0;
61   	static int opt_fs = 0;
62   	static int dump_mstcpy = 0;
63   	static mode_t create_mode = 0600;
64   	static int verbose;
65   	static int wide;
66   	static int wait_sec;
67   	static int summarize;
68   	static int use_dlmc;
69   	static int use_dlms;
70   	static int dlms_fd;
71   	
72   	char run_command[DLMC_RUN_COMMAND_LEN];
73   	char run_uuid[DLMC_RUN_UUID_LEN];
74   	
75   	#define MAX_NODES 128
76   	
77   	/* from linux/fs/dlm/dlm_internal.h */
78   	#define DLM_LKSTS_WAITING       1
79   	#define DLM_LKSTS_GRANTED       2
80   	#define DLM_LKSTS_CONVERT       3
81   	
82   	#define DLM_MSG_REQUEST         1
83   	#define DLM_MSG_CONVERT         2
84   	#define DLM_MSG_UNLOCK          3
85   	#define DLM_MSG_CANCEL          4
86   	#define DLM_MSG_REQUEST_REPLY   5
87   	#define DLM_MSG_CONVERT_REPLY   6
88   	#define DLM_MSG_UNLOCK_REPLY    7
89   	#define DLM_MSG_CANCEL_REPLY    8
90   	#define DLM_MSG_GRANT           9
91   	#define DLM_MSG_BAST            10
92   	#define DLM_MSG_LOOKUP          11
93   	#define DLM_MSG_REMOVE          12
94   	#define DLM_MSG_LOOKUP_REPLY    13
95   	#define DLM_MSG_PURGE           14
96   	
97   	
98   	struct dlmc_node nodes[MAX_NODES];
99   	
100  	struct rinfo {
101  		int print_granted;
102  		int print_convert;
103  		int print_waiting;
104  		int print_lookup;
105  		int namelen;
106  		int nodeid;
107  		int lvb;
108  		unsigned int lkb_count;
109  		unsigned int lkb_granted;
110  		unsigned int lkb_convert;
111  		unsigned int lkb_waiting;
112  		unsigned int lkb_lookup;
113  		unsigned int lkb_wait_msg;
114  		unsigned int lkb_master_copy;
115  		unsigned int lkb_local_copy;
116  		unsigned int lkb_process_copy;
117  	};
118  	
119  	struct summary {
120  		unsigned int rsb_total;
121  		unsigned int rsb_with_lvb;
122  		unsigned int rsb_no_locks;
123  		unsigned int rsb_lookup;
124  		unsigned int rsb_master;
125  		unsigned int rsb_local;
126  		unsigned int rsb_nodeid_error;
127  		unsigned int lkb_count;
128  		unsigned int lkb_granted;
129  		unsigned int lkb_convert;
130  		unsigned int lkb_waiting;
131  		unsigned int lkb_lookup;
132  		unsigned int lkb_wait_msg;
133  		unsigned int lkb_master_copy;
134  		unsigned int lkb_local_copy;
135  		unsigned int lkb_process_copy;
136  		unsigned int expect_replies;
137  		unsigned int toss_total;
138  	};
139  	
140  	static const char *mode_str(int mode)
141  	{
142  		switch (mode) {
143  		case -1:
144  			return "IV";
145  		case LKM_NLMODE:
146  			return "NL";
147  		case LKM_CRMODE:
148  			return "CR";
149  		case LKM_CWMODE:
150  			return "CW";
151  		case LKM_PRMODE:
152  			return "PR";
153  		case LKM_PWMODE:
154  			return "PW";
155  		case LKM_EXMODE:
156  			return "EX";
157  		}
158  		return "??";
159  	}
160  	
161  	static const char *msg_str(int type)
162  	{
163  		switch (type) {
164  		case DLM_MSG_REQUEST:
165  			return "request";
166  		case DLM_MSG_CONVERT:
167  			return "convert";
168  		case DLM_MSG_UNLOCK:
169  			return "unlock ";
170  		case DLM_MSG_CANCEL:
171  			return "cancel ";
172  		case DLM_MSG_REQUEST_REPLY:
173  			return "r_reply";
174  		case DLM_MSG_CONVERT_REPLY:
175  			return "c_reply";
176  		case DLM_MSG_UNLOCK_REPLY:
177  			return "u_reply";
178  		case DLM_MSG_CANCEL_REPLY:
179  			return "c_reply";
180  		case DLM_MSG_GRANT:
181  			return "grant  ";
182  		case DLM_MSG_BAST:
183  			return "bast   ";
184  		case DLM_MSG_LOOKUP:
185  			return "lookup ";
186  		case DLM_MSG_REMOVE:
187  			return "remove ";
188  		case DLM_MSG_LOOKUP_REPLY:
189  			return "l_reply";
190  		case DLM_MSG_PURGE:
191  			return "purge  ";
192  		default:
193  			return "unknown";
194  		}
195  	}
196  	
197  	static void print_usage(void)
198  	{
199  		printf("Usage:\n");
200  		printf("\n");
201  		printf("dlm_tool [command] [options] [name]\n");
202  		printf("\n");
203  		printf("Commands:\n");
204  		printf("ls, status, dump, fence_ack\n");
205  		printf("dump_config, reload_config, set_config\n");
206  		printf("log_plock, plocks\n");
207  		printf("join, leave, lockdebug\n");
208  		printf("run, run_start, run_check, run_cancel, run_list\n");
209  		printf("\n");
210  		printf("Options:\n");
211  		printf("  -n               Show all node information in ls\n");
212  		printf("  -e 0|1           Exclusive create off/on in join, default 0\n");
213  		printf("  -f 0|1           FS (filesystem) flag off/on in join, default 0\n");
214  		printf("  -m <mode>        Permission mode for lockspace device (octal), default 0600\n");
215  		printf("  -s               Summary following lockdebug output (experimental)\n");
216  		printf("  -v               Verbose lockdebug output\n");
217  		printf("  -w               Wide lockdebug output\n");
218  		printf("  -i <sec>         Wait for <sec>.\n");
219  		printf("  -h               Print help, then exit\n");
220  		printf("  -V               Print program version information, then exit\n");
221  		printf("\n");
222  	}
223  	
224  	#define OPTION_STRING "MhVnm:e:f:vwsi:"
225  	
226  	static void decode_arguments(int argc, char **argv)
227  	{
228  		int cont = 1;
229  		int optchar;
230  		int need_lsname;
231  		int need_command = 0;
232  		int need_uuid = 0;
233  		int optional_lsname = 0;
234  		int i;
235  		char modebuf[8];
236  	
237  		while (cont) {
238  			optchar = getopt(argc, argv, OPTION_STRING);
239  	
240  			switch (optchar) {
241  			case 'e':
242  				opt_excl = atoi(optarg);
243  				break;
244  	
245  			case 'f':
246  				opt_fs = atoi(optarg);
247  				break;
248  	
249  			case 'm':
250  				memset(modebuf, 0, sizeof(modebuf));
251  				snprintf(modebuf, 8, "%s", optarg);
252  				sscanf(modebuf, "%o", &create_mode);
253  				break;
254  	
255  			case 'M':
256  				dump_mstcpy = 1;
257  				break;
258  	
259  			case 'n':
260  				ls_all_nodes = 1;
261  				break;
262  	
263  			case 's':
264  				summarize = 1;
265  				break;
266  	
267  			case 'v':
268  				verbose = 1;
269  				break;
270  	
271  			case 'w':
272  				wide = 1;
273  				break;
274  	
275  			case 'i':
276  				wait_sec = atoi(optarg);
277  				break;
278  	
279  			case 'h':
280  				print_usage();
281  				exit(EXIT_SUCCESS);
282  				break;
283  	
284  			case 'V':
285  				printf("%s %s (built %s %s)\n",
286  					prog_name, RELEASE_VERSION, __DATE__, __TIME__);
287  				printf("%s\n", REDHAT_COPYRIGHT);
288  				exit(EXIT_SUCCESS);
289  				break;
290  	
291  			case ':':
292  			case '?':
293  				fprintf(stderr, "Please use '-h' for usage.\n");
294  				exit(EXIT_FAILURE);
295  				break;
296  	
297  			case EOF:
298  				cont = 0;
299  				break;
300  	
301  			default:
302  				fprintf(stderr, "unknown option: %c\n", optchar);
303  				exit(EXIT_FAILURE);
304  				break;
305  			};
306  		}
307  	
308  		need_lsname = 1;
309  	
310  		while (optind < argc) {
311  			if (!strncmp(argv[optind], "join", 4) &&
312  			    (strlen(argv[optind]) == 4)) {
313  				operation = OP_JOIN;
314  				opt_ind = optind + 1;
315  				break;
316  			} else if (!strncmp(argv[optind], "leave", 5) &&
317  				   (strlen(argv[optind]) == 5)) {
318  				operation = OP_LEAVE;
319  				opt_ind = optind + 1;
320  				break;
321  			} else if (!strncmp(argv[optind], "joinleave", 9) &&
322  				   (strlen(argv[optind]) == 9)) {
323  				operation = OP_JOINLEAVE;
324  				opt_ind = optind + 1;
325  				break;
326  			} else if (!strncmp(argv[optind], "ls", 2) &&
327  				   (strlen(argv[optind]) == 2)) {
328  				operation = OP_LIST;
329  				opt_ind = optind + 1;
330  				need_lsname = 0;
331  				optional_lsname = 1;
332  				break;
333  			} else if (!strncmp(argv[optind], "status", 6) &&
334  				   (strlen(argv[optind]) == 6)) {
335  				operation = OP_DUMP_STATUS;
336  				opt_ind = optind + 1;
337  				need_lsname = 0;
338  				break;
339  			} else if (!strncmp(argv[optind], "deadlock_check", 14) &&
340  				   (strlen(argv[optind]) == 14)) {
341  				operation = OP_DEADLOCK_CHECK;
342  				opt_ind = optind + 1;
343  				break;
344  			} else if (!strncmp(argv[optind], "fence_ack", 9) &&
345  				   (strlen(argv[optind]) == 9)) {
346  				operation = OP_FENCE_ACK;
347  				opt_ind = optind + 1;
348  				break;
349  			} else if (!strncmp(argv[optind], "dump", 4) &&
350  				   (strlen(argv[optind]) == 4)) {
351  				operation = OP_DUMP_DEBUG;
352  				opt_ind = optind + 1;
353  				need_lsname = 0;
354  				break;
355  			} else if (!strncmp(argv[optind], "dump_config", 11) &&
356  				   (strlen(argv[optind]) == 11)) {
357  				operation = OP_DUMP_CONFIG;
358  				opt_ind = optind + 1;
359  				need_lsname = 0;
360  				break;
361  			} else if (!strncmp(argv[optind], "reload_config", 13) &&
362  				   (strlen(argv[optind]) == 13)) {
363  				operation = OP_RELOAD_CONFIG;
364  				opt_ind = optind + 1;
365  				need_lsname = 0;
366  				break;
367  			} else if (!strncmp(argv[optind], "set_config", 10) &&
368  				   (strlen(argv[optind]) == 10)) {
369  				operation = OP_SET_CONFIG;
370  				opt_ind = optind + 1;
371  				need_lsname = 0;
372  				need_command = 1;
373  				break;
374  			} else if (!strncmp(argv[optind], "plocks", 6) &&
375  				   (strlen(argv[optind]) == 6)) {
376  				operation = OP_PLOCKS;
377  				opt_ind = optind + 1;
378  				break;
379  			} else if (!strncmp(argv[optind], "log_plock", 9) &&
380  				   (strlen(argv[optind]) == 9)) {
381  				operation = OP_LOG_PLOCK;
382  				opt_ind = optind + 1;
383  				need_lsname = 0;
384  				break;
385  			} else if (!strcmp(argv[optind], "run")) {
386  				operation = OP_RUN;
387  				opt_ind = optind + 1;
388  				need_lsname = 0;
389  				need_command = 1;
390  				break;
391  			} else if (!strcmp(argv[optind], "run_start")) {
392  				operation = OP_RUN_START;
393  				opt_ind = optind + 1;
394  				need_lsname = 0;
395  				need_command = 1;
396  				break;
397  			} else if (!strcmp(argv[optind], "run_check")) {
398  				operation = OP_RUN_CHECK;
399  				opt_ind = optind + 1;
400  				need_lsname = 0;
401  				need_uuid = 1;
402  				break;
403  			} else if (!strcmp(argv[optind], "run_cancel")) {
404  				operation = OP_RUN_CANCEL;
405  				opt_ind = optind + 1;
406  				need_lsname = 0;
407  				need_uuid = 1;
408  				break;
409  			} else if (!strcmp(argv[optind], "run_list")) {
410  				operation = OP_DUMP_RUN;
411  				opt_ind = optind + 1;
412  				need_lsname = 0;
413  				need_uuid = 0;
414  				break;
415  			}
416  	
417  	
418  			/*
419  			 * debugfs
420  			 */
421  	
422  			else if (!strncmp(argv[optind], "lockdump", 8) &&
423  				   (strlen(argv[optind]) == 8)) {
424  				operation = OP_LOCKDUMP;
425  				opt_ind = optind + 1;
426  				break;
427  			} else if (!strncmp(argv[optind], "lockdebug", 9) &&
428  				   (strlen(argv[optind]) == 9)) {
429  				operation = OP_LOCKDEBUG;
430  				opt_ind = optind + 1;
431  				break;
432  			}
433  			optind++;
434  		}
435  	
436  		if (!operation || !opt_ind) {
437  			print_usage();
438  			exit(EXIT_FAILURE);
439  		}
440  	
441  		/*
442  		 * The operation does not require an arg, but may
443  		 * accept an optional arg, i.e. dlm_tool ls [name]
444  		 */
445  		if (!need_lsname && !need_uuid && !need_command) {
446  			if (optind < argc - 1) {
447  				if (optional_lsname)
448  					lsname = argv[opt_ind];
449  			}
450  			return;
451  		}
452  	
453  		if (optind < argc - 1) {
454  			if (need_lsname)
455  				lsname = argv[opt_ind];
456  			else if (need_uuid) {
457  				strncpy(run_uuid, argv[opt_ind], DLMC_RUN_UUID_LEN - 1);
458  				run_uuid[DLMC_RUN_UUID_LEN - 1] = '\0';
459  			} else if (need_command)
460  				goto copy_command;
461  		} else if (need_lsname) {
462  			if (operation == OP_FENCE_ACK)
463  				fprintf(stderr, "nodeid required\n");
464  			else
465  				fprintf(stderr, "lockspace name required\n");
466  			exit(EXIT_FAILURE);
467  		} else if (need_command) {
468  			fprintf(stderr, "command required\n");
469  			exit(EXIT_FAILURE);
470  		} else if (need_uuid) {
471  			fprintf(stderr, "uuid required\n");
472  			exit(EXIT_FAILURE);
473  		} else {
474  			fprintf(stderr, "missing arg\n");
475  			exit(EXIT_FAILURE);
476  		}
477  	
478  	 copy_command:
479  		for (i = opt_ind; i < argc; i++) {
480  			if (strlen(run_command) + strlen(argv[i]) + 2 > DLMC_RUN_COMMAND_LEN) {
481  				fprintf(stderr, "command too long (max %d)\n", DLMC_RUN_COMMAND_LEN);
482  				exit(EXIT_FAILURE);
483  			}
484  	
485  			if (strlen(argv[i])) {
486  				strcat(run_command, argv[i]);
487  				strcat(run_command, " ");
488  			}
489  		}
490  	}
491  	
492  	static int do_read(int fd, void *buf, size_t count)
493  	{
494  		int rv, off = 0;
495  	
496  		while (off < count) {
497  			rv = read(fd, (char *)buf + off, count - off);
498  			if (rv == 0)
499  				return -1;
500  			if (rv == -1 && errno == EINTR)
501  				continue;
502  			if (rv == -1)
503  				return -1;
504  			off += rv;
505  		}
506  		return 0;
507  	}
508  	
509  	static int do_write(int fd, void *buf, size_t count)
510  	{
511  		int rv, off = 0;
512  	
513  	 retry:
514  		rv = write(fd, (char *)buf + off, count);
515  		if (rv == -1 && errno == EINTR)
516  			goto retry;
517  		if (rv < 0)
518  			return rv;
519  	
520  		if (rv != count) {
521  			count -= rv;
522  			off += rv;
523  			goto retry;
524  		}
525  		return 0;
526  	}
527  	
528  	static char *flag_str(uint32_t flags)
529  	{
530  		static char join_flags[128];
531  	
532  		memset(join_flags, 0, sizeof(join_flags));
533  	
534  		strcat(join_flags, "flags ");
535  	
536  		if (flags & DLM_LSFL_NEWEXCL)
537  			strcat(join_flags, "NEWEXCL ");
538  	
539  		if (flags & DLM_LSFL_FS)
540  			strcat(join_flags, "FS ");
541  	
542  		return join_flags;
543  	}
544  	
545  	static void do_join(char *name)
546  	{
547  		dlm_lshandle_t *dh;
548  		uint32_t flags = 0;
549  	
550  		if (opt_excl)
551  			flags |= DLM_LSFL_NEWEXCL;
552  	
553  		if (opt_fs)
554  			flags |= DLM_LSFL_FS;
555  	
556  		printf("Joining lockspace \"%s\" permission %o %s\n",
557  		       name, create_mode, flags ? flag_str(flags) : "");
558  		fflush(stdout);
559  	
560  		dh = dlm_new_lockspace(name, create_mode, flags);
561  		if (!dh) {
562  			fprintf(stderr, "dlm_new_lockspace %s error %d\n",
563  				name, errno);
564  			exit(-1);
565  		}
566  	
567  		dlm_close_lockspace(dh);
568  		/* there's no autofree so the ls should stay around */
569  		printf("done\n");
570  	}
571  	
572  	static void do_leave(char *name)
573  	{
574  		dlm_lshandle_t *dh;
575  	
576  		printf("Leaving lockspace \"%s\"\n", name);
577  		fflush(stdout);
578  	
579  		dh = dlm_open_lockspace(name);
580  		if (!dh) {
581  			fprintf(stderr, "dlm_open_lockspace %s error %p %d\n",
582  				name, dh, errno);
583  			exit(-1);
584  		}
585  	
586  		dlm_release_lockspace(name, dh, 1);
587  		printf("done\n");
588  	}
589  	
590  	static char *pr_master(int nodeid)
591  	{
592  		static char buf[64];
593  	
594  		memset(buf, 0, sizeof(buf));
595  	
596  		if (nodeid > 0)
597  			sprintf(buf, "Master:%d", nodeid);
598  		else if (!nodeid)
599  			sprintf(buf, "Master");
600  		else if (nodeid == -1)
601  			sprintf(buf, "Lookup");
602  	
603  		return buf;
604  	}
605  	
606  	static char *pr_extra(uint32_t flags, int root_list, int recover_list,
607  		       int recover_locks_count, char *first_lkid)
608  	{
609  		static char buf[128];
610  		int first = 0;
611  	
612  		memset(buf, 0, sizeof(buf));
613  	
614  		if (strcmp(first_lkid, "0"))
615  			first = 1;
616  	
617  		if (flags || first || root_list || recover_list || recover_locks_count)
618  			sprintf(buf,
619  			   "flags %08x first_lkid %s root %d recover %d locks %d",
620  			   flags, first_lkid, root_list, recover_list, recover_locks_count);
621  	
622  		return buf;
623  	}
624  	
625  	static void print_rsb(char *line, struct rinfo *ri)
626  	{
627  		char type[4], namefmt[4], *p;
628  		char addr[64];
629  		char first_lkid[64];
630  		int rv, nodeid, root_list, recover_list, recover_locks_count, namelen;
631  		uint32_t flags;
632  	
633  		rv = sscanf(line, "%s %s %d %s %u %d %d %u %u %s",
634  			    type,
635  			    addr,
636  			    &nodeid,
637  			    first_lkid,
638  			    &flags,
639  			    &root_list,
640  			    &recover_list,
641  			    &recover_locks_count,
642  			    &namelen,
643  			    namefmt);
644  	
645  		if (rv != 10)
646  			goto fail;
647  	
648  		/* used for lkb prints */
649  		ri->nodeid = nodeid;
650  	
651  		ri->namelen = namelen;
652  		
653  		p = strchr(line, '\n');
654  		if (!p)
655  			goto fail;
656  		*p = '\0';
657  	
658  		p = strstr(line, namefmt);
659  		if (!p)
660  			goto fail;
661  		p += 4;
662  	
663  		strcat(addr, " ");
664  	
665  		if (!strncmp(namefmt, "str", 3))
666  			printf("Resource len %2d  \"%s\"\n", namelen, p);
667  		else if (!strncmp(namefmt, "hex", 3))
668  			printf("Resource len %2d hex %s\n", namelen, p);
669  		else
670  			goto fail;
671  	
672  		printf("%-16s %s\n",
673  			pr_master(nodeid),
674  			pr_extra(flags, root_list, recover_list, recover_locks_count, first_lkid));
675  		return;
676  	
677  	 fail:
678  		fprintf(stderr, "print_rsb error rv %d line \"%s\"\n", rv, line);
679  	}
680  	
681  	static void print_lvb(char *line)
682  	{
683  		char lvb[1024];
684  		char type[4];
685  		int i, c, rv, lvblen;
686  		uint32_t lvbseq;
687  	
688  		memset(lvb, 0, 1024);
689  	
690  		rv = sscanf(line, "%s %u %d %[0-9A-Fa-f ]", type, &lvbseq, &lvblen, lvb);
691  	
692  		if (rv != 4) {
693  			fprintf(stderr, "print_lvb error rv %d line \"%s\"\n", rv, line);
694  			return;
695  		}
696  	
697  		printf("LVB len %d seq %u\n", lvblen, lvbseq);
698  	
699  		for (c = 0, i = 0; ; i++) {
700  			printf("%c", lvb[i]);
701  			if (lvb[i] != ' ')
702  				c++;
703  			if (!wide && lvb[i] == ' ' && !(c % 32))
704  				printf("\n");
705  			if (c == (lvblen * 2))
706  				break;
707  		}
708  		printf("\n");
709  	}
710  	
711  	struct lkb {
712  		uint64_t xid, timestamp, time_bast;
713  		uint32_t id, remid, exflags, flags, lvbseq;
714  		int nodeid, ownpid, status, grmode, rqmode, highbast, rsb_lookup, wait_type;
715  	};
716  	
717  	static const char *pr_grmode(struct lkb *lkb)
718  	{
719  		if (lkb->status == DLM_LKSTS_GRANTED || lkb->status == DLM_LKSTS_CONVERT)
720  			return mode_str(lkb->grmode);
721  		else if (lkb->status == DLM_LKSTS_WAITING || lkb->rsb_lookup)
722  			return "--";
723  		else
724  			return "XX";
725  	}
726  	
727  	static const char *pr_rqmode(struct lkb *lkb)
728  	{
729  		static char buf[5];
730  	
731  		memset(buf, 0, sizeof(buf));
732  	
733  		if (lkb->status == DLM_LKSTS_GRANTED) {
734  			return "    ";
735  		} else if (lkb->status == DLM_LKSTS_CONVERT ||
736  			   lkb->status == DLM_LKSTS_WAITING ||
737  			   lkb->rsb_lookup) {
738  			sprintf(buf, "(%s)", mode_str(lkb->rqmode));
739  			return buf;
740  		} else {
741  			return "(XX)";
742  		}
743  	}
744  	
745  	static const char *pr_remote(struct lkb *lkb, struct rinfo *ri)
746  	{
747  		static char buf[64];
748  	
749  		memset(buf, 0, sizeof(buf));
750  	
751  		if (!lkb->nodeid) {
752  			return "                    ";
753  		} else if (lkb->nodeid != ri->nodeid) {
754  			sprintf(buf, "Remote: %3d %08x", lkb->nodeid, lkb->remid);
755  			return buf;
756  		} else {
757  			sprintf(buf, "Master: %3d %08x", lkb->nodeid, lkb->remid);
758  			return buf;
759  		}
760  	}
761  	
762  	static const char *pr_wait(struct lkb *lkb)
763  	{
764  		static char buf[16];
765  	
766  		memset(buf, 0, sizeof(buf));
767  	
768  		if (!lkb->wait_type) {
769  			return "        ";
770  		} else {
771  			sprintf(buf, " wait %02d", lkb->wait_type);
772  			return buf;
773  		}
774  	}
775  	
776  	static char *pr_verbose(struct lkb *lkb)
777  	{
778  		static char buf[128];
779  	
780  		memset(buf, 0, sizeof(buf));
781  	
782  		sprintf(buf, "time %016llu flags %08x %08x bast %d %llu pid %d",
783  			(unsigned long long)lkb->timestamp,
784  			lkb->exflags, lkb->flags, lkb->highbast,
785  			(unsigned long long)lkb->time_bast, lkb->ownpid);
786  	
787  		return buf;
788  	}
789  	
790  	static void print_lkb(char *line, struct rinfo *ri)
791  	{
792  		struct lkb lkb;
793  		char type[4];
794  	
795  		sscanf(line, "%s %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu",
796  			    type,
797  			    &lkb.id,
798  			    &lkb.nodeid,
799  			    &lkb.remid,
800  			    &lkb.ownpid,
801  			    (unsigned long long *)&lkb.xid,
802  			    &lkb.exflags,
803  			    &lkb.flags,
804  			    &lkb.status,
805  			    &lkb.grmode,
806  			    &lkb.rqmode,
807  			    &lkb.highbast,
808  			    &lkb.rsb_lookup,
809  			    &lkb.wait_type,
810  			    &lkb.lvbseq,
811  			    (unsigned long long *)&lkb.timestamp,
812  			    (unsigned long long *)&lkb.time_bast);
813  	
814  		ri->lkb_count++;
815  	
816  		if (lkb.status == DLM_LKSTS_GRANTED) {
817  		       	if (!ri->print_granted++)
818  				printf("Granted\n");
819  			ri->lkb_granted++;
820  		}
821  		if (lkb.status == DLM_LKSTS_CONVERT) {
822  			if (!ri->print_convert++)
823  				printf("Convert\n");
824  			ri->lkb_convert++;
825  		}
826  		if (lkb.status == DLM_LKSTS_WAITING) {
827  		       	if (!ri->print_waiting++)
828  				printf("Waiting\n");
829  			ri->lkb_waiting++;
830  		}
831  		if (lkb.rsb_lookup) {
832  		       	if (!ri->print_lookup++)
833  				printf("Lookup\n");
834  			ri->lkb_lookup++;
835  		}
836  	
837  		if (lkb.wait_type)
838  			ri->lkb_wait_msg++;
839  	
840  		if (!ri->nodeid) {
841  			if (lkb.nodeid)
842  				ri->lkb_master_copy++;
843  			else
844  				ri->lkb_local_copy++;
845  		} else {
846  			ri->lkb_process_copy++;
847  		}
848  	
849  		printf("%08x %s %s %s %s %s\n",
850  		       lkb.id, pr_grmode(&lkb), pr_rqmode(&lkb),
851  		       pr_remote(&lkb, ri), pr_wait(&lkb),
852  		       (verbose && wide) ? pr_verbose(&lkb) : "");
853  	
854  		if (verbose && !wide)
855  			printf("%s\n", pr_verbose(&lkb));
856  	}
857  	
858  	static void print_rsb_toss(char *line)
859  	{
860  		char type[4], namefmt[4], *p;
861  		char addr[64];
862  		char toss_time[16];
863  		int res_nodeid, master_nodeid, dir_nodeid, our_nodeid;
864  		int rv, namelen;
865  		uint32_t flags;
866  	
867  		rv = sscanf(line, "%s %s %d %d %d %d %s %u %u %s",
868  			    type,
869  			    addr,
870  			    &res_nodeid,
871  			    &master_nodeid,
872  			    &dir_nodeid,
873  			    &our_nodeid,
874  			    toss_time,
875  			    &flags,
876  			    &namelen,
877  			    namefmt);
878  	
879  		if (rv != 10)
880  			goto fail;
881  	
882  		p = strchr(line, '\n');
883  		if (!p)
884  			goto fail;
885  		*p = '\0';
886  	
887  		p = strstr(line, namefmt);
888  		if (!p)
889  			goto fail;
890  		p += 4;
891  	
892  		strcat(addr, " ");
893  	
894  		if (!strncmp(namefmt, "str", 3))
895  			printf("Resource len %2d  \"%s\"\n", namelen, p);
896  		else if (!strncmp(namefmt, "hex", 3))
897  			printf("Resource len %2d hex %s\n", namelen, p);
898  		else
899  			goto fail;
900  	
901  		if (master_nodeid != our_nodeid)
902  			printf("Master:%d", master_nodeid);
903  		else
904  			printf("Master");
905  	
906  		if (dir_nodeid != our_nodeid)
907  			printf(" Dir:%d", dir_nodeid);
908  		else
909  			printf(" Dir");
910  	
911  		if (master_nodeid == our_nodeid && res_nodeid != 0)
912  			printf(" res_nodeid %d", res_nodeid);
913  	
914  		printf("\n");
915  	
916  		return;
917  	
918  	 fail:
919  		fprintf(stderr, "print_rsb_toss error rv %d line \"%s\"\n", rv, line);
920  	}
921  	
922  	static void clear_rinfo(struct rinfo *ri)
923  	{
924  		memset(ri, 0, sizeof(struct rinfo));
925  		ri->nodeid = -9;
926  	}
927  	
928  	static void count_rinfo(struct summary *s, struct rinfo *ri)
929  	{
930  		/* the first time called */
931  		if (!ri->namelen)
932  			return;
933  	
934  		s->rsb_total++;
935  	
936  		if (ri->lvb)
937  			s->rsb_with_lvb++;
938  	
939  		if (!ri->lkb_count) {
940  			s->rsb_no_locks++;
941  			printf("no locks\n");
942  		}
943  	
944  		if (!ri->nodeid)
945  			s->rsb_master++;
946  		else if (ri->nodeid == -1)
947  			s->rsb_lookup++;
948  		else if (ri->nodeid > 0)
949  			s->rsb_local++;
950  		else
951  			s->rsb_nodeid_error++;
952  	
953  		s->lkb_count        += ri->lkb_count;
954  		s->lkb_granted      += ri->lkb_granted;
955  		s->lkb_convert      += ri->lkb_convert;
956  		s->lkb_waiting      += ri->lkb_waiting;
957  		s->lkb_lookup       += ri->lkb_lookup;
958  		s->lkb_wait_msg     += ri->lkb_wait_msg;
959  		s->lkb_master_copy  += ri->lkb_master_copy;
960  		s->lkb_local_copy   += ri->lkb_local_copy;
961  		s->lkb_process_copy += ri->lkb_process_copy;
962  	}
963  	
964  	static void print_summary(struct summary *s)
965  	{
966  		printf("rsb\n");
967  		printf("  active        %u\n", s->rsb_total);
968  		printf("  master        %u\n", s->rsb_master);
969  		printf("  remote master %u\n", s->rsb_local);
970  		printf("  lookup master %u\n", s->rsb_lookup);
971  		printf("  with lvb      %u\n", s->rsb_with_lvb);
972  		printf("  with no locks %u\n", s->rsb_no_locks);
973  		printf("  nodeid error  %u\n", s->rsb_nodeid_error);
974  		printf("  inactive      %u\n", s->toss_total);
975  		printf("\n");
976  	
977  		printf("lkb\n");
978  		printf("  total         %u\n", s->lkb_count);
979  		printf("  granted       %u\n", s->lkb_granted);
980  		printf("  convert       %u\n", s->lkb_convert);
981  		printf("  waiting       %u\n", s->lkb_waiting);
982  		printf("  local copy    %u\n", s->lkb_local_copy);
983  		printf("  master copy   %u\n", s->lkb_master_copy);
984  		printf("  process copy  %u\n", s->lkb_process_copy);
985  		printf("  rsb lookup    %u\n", s->lkb_lookup);
986  		printf("  wait message  %u\n", s->lkb_wait_msg);
987  		printf("  expect reply  %u\n", s->expect_replies);
988  	}
989  	
990  	#define LOCK_LINE_MAX 1024
991  	
992  	static void do_waiters(char *name, struct summary *sum)
993  	{
994  		FILE *file;
995  		char path[PATH_MAX];
996  		char line[LOCK_LINE_MAX];
997  		char rname[DLM_RESNAME_MAXLEN+1];
998  		int header = 0;
999  		int i, j, spaces;
1000 		int rv, nodeid, wait_type;
1001 		uint32_t id;
1002 	
1003 		snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_waiters", name);
1004 	
1005 		file = fopen(path, "r");
1006 		if (!file)
1007 			return;
1008 	
1009 		while (fgets(line, LOCK_LINE_MAX, file)) {
1010 			if (!header) {
1011 				printf("\n");
1012 				printf("Expecting reply\n");
1013 				header = 1;
1014 			}
1015 	
1016 			rv = sscanf(line, "%x %d %d",
1017 				    &id, &wait_type, &nodeid);
1018 	
1019 			if (rv != 3) {
1020 				printf("waiters: %s", line);
1021 				continue;
1022 			}
1023 	
1024 			/* parse the resource name from the remainder of the line */
1025 			j = 0;
1026 			spaces = 0;
1027 			memset(rname, 0, sizeof(rname));
1028 	
1029 			for (i = 0; i < LOCK_LINE_MAX; i++) {
1030 				if (line[i] == '\n')
1031 					break;
1032 				if (spaces == 3) {
1033 					rname[j++] = line[i];
1034 					if (j == (sizeof(rname) - 1))
1035 						break;
1036 				} else if (line[i] == ' ') {
1037 					spaces++;
1038 				}
1039 			}
1040 	
1041 			printf("nodeid %2d msg %s lkid %08x resource \"%s\"\n",
1042 			       nodeid, msg_str(wait_type), id, rname);
1043 	
1044 			sum->expect_replies++;
1045 		}
1046 		fclose(file);
1047 	}
1048 	
1049 	static void do_toss(char *name, struct summary *sum)
1050 	{
1051 		FILE *file;
1052 		char path[PATH_MAX];
1053 		char line[LOCK_LINE_MAX];
1054 	
1055 		snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_toss", name);
1056 	
1057 		file = fopen(path, "r");
1058 		if (!file)
1059 			return;
1060 	
1061 		while (fgets(line, LOCK_LINE_MAX, file)) {
1062 			if (!strncmp(line, "version", 7))
1063 				continue;
1064 	
1065 			if (!strncmp(line, "rsb", 3)) {
1066 				print_rsb_toss(line);
1067 				sum->toss_total++;
1068 				printf("\n");
1069 			}
1070 		}
1071 		fclose(file);
1072 	}
1073 	
1074 	static void do_lockdebug(char *name)
1075 	{
1076 		struct summary summary;
1077 		struct rinfo info;
1078 		FILE *file;
1079 		char path[PATH_MAX];
1080 		char line[LOCK_LINE_MAX];
1081 		int old = 0;
1082 	
1083 		snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_all", name);
1084 	
1085 		file = fopen(path, "r");
1086 		if (!file) {
1087 			snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s", name);
1088 			file = fopen(path, "r");
1089 			if (!file) {
1090 				fprintf(stderr, "can't open %s: %s\n", path, strerror(errno));
1091 				return;
1092 			}
1093 			old = 1;
1094 		}
1095 	
1096 		memset(&summary, 0, sizeof(struct summary));
1097 		memset(&info, 0, sizeof(struct rinfo));
1098 	
1099 		/* skip file header */
1100 		if (!fgets(line, LOCK_LINE_MAX, file))
1101 			goto done;
1102 	
1103 		while (fgets(line, LOCK_LINE_MAX, file)) {
1104 	
1105 			if (old)
1106 				goto raw;
1107 	
1108 			if (!strncmp(line, "version", 7))
1109 				continue;
1110 	
1111 			if (!strncmp(line, "rsb", 3)) {
1112 				count_rinfo(&summary, &info);
1113 				clear_rinfo(&info);
1114 				printf("\n");
1115 				print_rsb(line, &info);
1116 				continue;
1117 			}
1118 			
1119 			if (!strncmp(line, "lvb", 3)) {
1120 				print_lvb(line);
1121 				info.lvb = 1;
1122 				continue;
1123 			}
1124 			
1125 			if (!strncmp(line, "lkb", 3)) {
1126 				print_lkb(line, &info);
1127 				continue;
1128 			}
1129 	 raw:
1130 			printf("%s", line);
1131 		}
1132 	 done:
1133 		count_rinfo(&summary, &info);
1134 		clear_rinfo(&info);
1135 		printf("\n");
1136 		fclose(file);
1137 	
1138 		do_toss(name, &summary);
1139 	
1140 		do_waiters(name, &summary);
1141 	
1142 		if (summarize) {
1143 			printf("\n");
1144 			print_summary(&summary);
1145 		}
1146 	}
1147 	
1148 	static void parse_r_name(char *line, char *name)
1149 	{
1150 		char *p;
1151 		int i = 0;
1152 		int begin = 0;
1153 	
1154 		for (p = line; ; p++) {
1155 			if (*p == '"') {
1156 				if (begin)
1157 					break;
1158 				begin = 1;
1159 				continue;
1160 			}
1161 			if (begin)
1162 				name[i++] = *p;
1163 		}
1164 	}
1165 	
1166 	static void do_lockdump(char *name)
1167 	{
1168 		FILE *file;
1169 		char path[PATH_MAX];
1170 		char line[LOCK_LINE_MAX];
1171 		char r_name[DLM_RESNAME_MAXLEN+1];
1172 		int r_nodeid;
1173 		int r_len;
1174 		int rv;
1175 		unsigned int tm;
1176 		unsigned long long xid;
1177 		uint32_t	id;
1178 		int		nodeid;
1179 		uint32_t	remid;
1180 		int		ownpid;
1181 		uint32_t	exflags;
1182 		uint32_t	flags;
1183 		int8_t		status;
1184 		int8_t		grmode;
1185 		int8_t		rqmode;
1186 	
1187 		snprintf(path, PATH_MAX, "/sys/kernel/debug/dlm/%s_locks", name);
1188 	
1189 		file = fopen(path, "r");
1190 		if (!file) {
1191 			fprintf(stderr, "can't open %s: %s\n", path, strerror(errno));
1192 			return;
1193 		}
1194 	
1195 		/* skip the header on the first line */
1196 		if (!fgets(line, LOCK_LINE_MAX, file)) {
1197 			goto out;
1198 		}
1199 	
1200 		while (fgets(line, LOCK_LINE_MAX, file)) {
1201 			rv = sscanf(line, "%x %d %x %u %llu %x %x %hhd %hhd %hhd %u %d %d",
1202 			       &id,
1203 			       &nodeid,
1204 			       &remid,
1205 			       &ownpid,
1206 			       &xid,
1207 			       &exflags,
1208 			       &flags,
1209 			       &status,
1210 			       &grmode,
1211 			       &rqmode,
1212 			       &tm,
1213 			       &r_nodeid,
1214 			       &r_len);
1215 	
1216 			if (rv != 13) {
1217 				fprintf(stderr, "invalid debugfs line %d: %s\n",
1218 					rv, line);
1219 				goto out;
1220 			}
1221 	
1222 			memset(r_name, 0, sizeof(r_name));
1223 			parse_r_name(line, r_name);
1224 	
1225 			/* don't print MSTCPY locks without -M */
1226 			if (!r_nodeid && nodeid) {
1227 				if (!dump_mstcpy)
1228 					continue;
1229 				printf("id %08x gr %s rq %s pid %u MSTCPY %d \"%s\"\n",
1230 					id, mode_str(grmode), mode_str(rqmode),
1231 					ownpid, nodeid, r_name);
1232 				continue;
1233 			}
1234 	
1235 			/* A hack because dlm-kernel doesn't set rqmode back to IV when
1236 			   a NOQUEUE convert fails, which means in a lockdump it looks
1237 			   like a granted lock is still converting since rqmode is not
1238 			   IV.  (does it make sense to include status in the output,
1239 			   e.g. G,C,W?) */
1240 	
1241 			if (status == DLM_LKSTS_GRANTED)
1242 				rqmode = LKM_IVMODE;
1243 	
1244 			printf("id %08x gr %s rq %s pid %u master %d \"%s\"\n",
1245 				id, mode_str(grmode), mode_str(rqmode),
1246 				ownpid, nodeid, r_name);
1247 		}
1248 	
1249 	 out:
1250 		fclose(file);
1251 	}
1252 	
1253 	static char *dlmc_lf_str(uint32_t flags)
1254 	{
1255 		static char str[128];
1256 		int i = 0;
1257 	
1258 		memset(str, 0, sizeof(str));
1259 	
1260 		if (flags & DLMC_LF_SAVE_PLOCKS) {
1261 			i++;
1262 			strcat(str, "save_plock");
1263 		}
1264 		if (flags & DLMC_LF_NEED_PLOCKS) {
1265 			strcat(str, i++ ? "," : "");
1266 			strcat(str, "need_plock");
1267 		}
1268 		if (flags & DLMC_LF_FS_REGISTERED) {
1269 			strcat(str, i++ ? "," : "");
1270 			strcat(str, "fs_reg");
1271 		}
1272 		if (flags & DLMC_LF_KERNEL_STOPPED) {
1273 			strcat(str, i++ ? "," : "");
1274 			strcat(str, "kern_stop");
1275 		}
1276 		if (flags & DLMC_LF_LEAVING) {
1277 			strcat(str, i++ ? "," : "");
1278 			strcat(str, "leave");
1279 		}
1280 		if (flags & DLMC_LF_JOINING) {
1281 			strcat(str, i++ ? "," : "");
1282 			strcat(str, "join");
1283 		}
1284 	
1285 		return str;
1286 	}
1287 	
1288 	static const char *check_str(struct dlmc_node *n)
1289 	{
1290 		static char _check_str[32];
1291 	
1292 		if (n->flags & DLMC_NF_NEED_FENCING) {
1293 			memset(_check_str, 0, sizeof(_check_str));
1294 			snprintf(_check_str, sizeof(_check_str) - 1, "fence %llu",
1295 				(unsigned long long)n->fail_monotime);
1296 			return _check_str;
1297 		}
1298 	
1299 		if (n->flags & DLMC_NF_CHECK_FS)
1300 			return "fs";
1301 	
1302 		return "none";
1303 	}
1304 	
1305 	static const char *condition_str(int cond)
1306 	{
1307 		switch (cond) {
1308 		case DLMC_LS_WAIT_RINGID:
1309 			return "ringid";
1310 		case DLMC_LS_WAIT_QUORUM:
1311 			return "quorum";
1312 		case DLMC_LS_WAIT_FENCING:
1313 			return "fencing";
1314 		case DLMC_LS_WAIT_FSDONE:
1315 			return "fsdone";
1316 		default:
1317 			return "unknown";
1318 		}
1319 	}
1320 	
1321 	static int node_compare(const void *va, const void *vb)
1322 	{
1323 		const struct dlmc_node *a = va;
1324 		const struct dlmc_node *b = vb;
1325 	
1326 		return a->nodeid - b->nodeid;
1327 	}
1328 	
1329 	static void show_nodeids(int count, struct dlmc_node *nodes_in)
1330 	{
1331 		struct dlmc_node *n = nodes_in;
1332 		int i;
1333 	
1334 		for (i = 0; i < count; i++) {
1335 			printf("%d ", n->nodeid);
1336 			n++;
1337 		}
1338 		printf("\n");
1339 	}
1340 	
1341 	static void show_ls(struct dlmc_lockspace *ls)
1342 	{
1343 		int rv, node_count;
1344 	
1345 		printf("name          %s\n", ls->name);
1346 		printf("id            0x%08x\n", ls->global_id);
1347 		printf("flags         0x%08x %s\n", ls->flags, dlmc_lf_str(ls->flags));
1348 		printf("change        member %d joined %d remove %d failed %d seq %d,%d\n",
1349 			ls->cg_prev.member_count, ls->cg_prev.joined_count,
1350 			ls->cg_prev.remove_count, ls->cg_prev.failed_count,
1351 			ls->cg_prev.combined_seq, ls->cg_prev.seq);
1352 	
1353 		node_count = 0;
1354 		memset(&nodes, 0, sizeof(nodes));
(1) Event tainted_argument: Calling function "dlmc_lockspace_nodes" taints argument "node_count". [details]
Also see events: [tainted_data][remediation]
1355 		rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_MEMBERS,
1356 					  MAX_NODES, &node_count, nodes);
(2) Event cond_false: Condition "rv < 0", taking false branch.
1357 		if (rv < 0) {
1358 			printf("members       error\n");
1359 			goto next;
(3) Event if_end: End of if statement.
1360 		}
(4) Event tainted_data: Passing tainted expression "node_count" to "qsort", which uses it as an offset.
(5) Event remediation: Ensure that tainted values are properly sanitized, by checking that their values are within a permissible range.
Also see events: [tainted_argument]
1361 		qsort(nodes, node_count, sizeof(struct dlmc_node), node_compare);
1362 	
1363 		printf("members       ");
1364 		show_nodeids(node_count, nodes);
1365 	
1366 	 next:
1367 		if (!ls->cg_next.seq)
1368 			return;
1369 	
1370 		printf("new change    member %d joined %d remove %d failed %d seq %d,%d\n",
1371 			ls->cg_next.member_count, ls->cg_next.joined_count,
1372 			ls->cg_next.remove_count, ls->cg_next.failed_count,
1373 		        ls->cg_next.combined_seq, ls->cg_next.seq);
1374 	
1375 		if (ls->cg_next.wait_messages)
1376 			printf("new status    wait messages %d\n", ls->cg_next.wait_condition);
1377 		else
1378 			printf("new status    wait %s\n", condition_str(ls->cg_next.wait_condition));
1379 	
1380 		node_count = 0;
1381 		memset(&nodes, 0, sizeof(nodes));
1382 		rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_NEXT,
1383 					  MAX_NODES, &node_count, nodes);
1384 		if (rv < 0) {
1385 			printf("new members   error\n");
1386 			return;
1387 		}
1388 		qsort(nodes, node_count, sizeof(struct dlmc_node), node_compare);
1389 	
1390 		printf("new members   ");
1391 		show_nodeids(node_count, nodes);
1392 	}
1393 	
1394 	static int member_int(struct dlmc_node *n)
1395 	{
1396 		if (n->flags & DLMC_NF_DISALLOWED)
1397 			return -1;
1398 		if (n->flags & DLMC_NF_MEMBER)
1399 			return 1;
1400 		return 0;
1401 	}
1402 	
1403 	static void show_all_nodes(int count, struct dlmc_node *nodes_in)
1404 	{
1405 		struct dlmc_node *n = nodes_in;
1406 		int i;
1407 	
1408 		for (i = 0; i < count; i++) {
1409 			printf("nodeid %d member %d failed %d start %d seq_add %u seq_rem %u check %s\n",
1410 				n->nodeid,
1411 				member_int(n),
1412 				n->fail_reason,
1413 				(n->flags & DLMC_NF_START) ? 1 : 0,
1414 				n->added_seq,
1415 				n->removed_seq,
1416 				check_str(n));
1417 			n++;
1418 		}
1419 	}
1420 	
1421 	static void _dlmc_list(char *name)
1422 	{
1423 		struct dlmc_lockspace *lss;
1424 		struct dlmc_lockspace *ls;
1425 		int node_count;
1426 		int ls_count;
1427 		int rv;
1428 		int i;
1429 	
1430 		if (name) {
1431 			/* get only one specific lockspace by name */
1432 			ls_count = 1;
1433 			lss = malloc(sizeof(struct dlmc_lockspace));
1434 			if (!lss)
1435 				exit(EXIT_FAILURE);
1436 	
1437 			rv = dlmc_lockspace_info(name, lss);
1438 		} else {
1439 			rv = dlmc_lockspaces(&ls_count, &lss);
1440 		}
1441 	
1442 		if (rv < 0)
1443 			exit(EXIT_FAILURE); /* dlm_controld probably not running */
1444 	
1445 		if (ls_count)
1446 			printf("dlm lockspaces\n");
1447 	
1448 		for (i = 0; i < ls_count; i++) {
1449 			ls = &lss[i];
1450 	
1451 			show_ls(ls);
1452 	
1453 			if (!ls_all_nodes)
1454 				goto next;
1455 	
1456 			node_count = 0;
1457 			memset(&nodes, 0, sizeof(nodes));
1458 	
1459 			rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_ALL,
1460 						  MAX_NODES, &node_count, nodes);
1461 			if (rv < 0) {
1462 				printf("all nodes error %d %d\n", rv, errno);
1463 				goto next;
1464 			}
1465 	
1466 			qsort(nodes, node_count, sizeof(struct dlmc_node),node_compare);
1467 	
1468 			printf("all nodes\n");
1469 			show_all_nodes(node_count, nodes);
1470 	 next:
1471 			printf("\n");
1472 		}
1473 	
1474 		free(lss);
1475 	}
1476 	
1477 	static int _dlmc_plocks(char *name)
1478 	{
1479 		char buf[DLMC_DUMP_SIZE];
1480 		int rv, data;
1481 	
1482 		memset(buf, 0, sizeof(buf));
1483 	
1484 		rv = dlmc_dump_plocks(name, buf, &data);
1485 		if (rv)
1486 			return rv;
1487 		else if (data)
1488 			return data;
1489 	
1490 		buf[DLMC_DUMP_SIZE-1] = '\0';
1491 	
1492 		do_write(STDOUT_FILENO, buf, strlen(buf));
1493 	
1494 		return 0;
1495 	}
1496 	
1497 	static int _dlmc_dump(int op)
1498 	{
1499 		int rv = -EOPNOTSUPP, data;
1500 		char buf[DLMC_DUMP_SIZE];
1501 	
1502 		memset(buf, 0, sizeof(buf));
1503 	
1504 		if (op == OP_DUMP_DEBUG)
1505 			rv = dlmc_dump_debug(buf, &data);
1506 		else if (op == OP_DUMP_CONFIG)
1507 			rv = dlmc_dump_config(buf, &data);
1508 		else if (op == OP_DUMP_RUN)
1509 			rv = dlmc_dump_run(buf, &data);
1510 	
1511 		if (rv)
1512 			return rv;
1513 		else if (data)
1514 			return data;
1515 	
1516 		buf[DLMC_DUMP_SIZE-1] = '\0';
1517 	
1518 		do_write(STDOUT_FILENO, buf, strlen(buf));
1519 		printf("\n");
1520 	
1521 		return 0;
1522 	}
1523 	
1524 	static void _dlmc_reload_config(void)
1525 	{
1526 		if (dlmc_reload_config() < 0)
1527 			printf("reload_config failed\n");
1528 		else
1529 			printf("reload_config done\n");
1530 	}
1531 	
1532 	static void _dlmc_set_config(void)
1533 	{
1534 		if (dlmc_set_config(run_command) < 0)
1535 			printf("set_config failed\n");
1536 		else
1537 			printf("set_config done\n");
1538 	}
1539 	
1540 	static int _dlmc_log_plock(void)
1541 	{
1542 		char buf[DLMC_DUMP_SIZE];
1543 		int rv, data;
1544 	
1545 		memset(buf, 0, sizeof(buf));
1546 	
1547 		rv = dlmc_dump_log_plock(buf, &data);
1548 		if (rv)
1549 			return rv;
1550 		else if (data)
1551 			return data;
1552 	
1553 		buf[DLMC_DUMP_SIZE-1] = '\0';
1554 	
1555 		do_write(STDOUT_FILENO, buf, strlen(buf));
1556 		printf("\n");
1557 	
1558 		return 0;
1559 	}
1560 	
1561 	static int _dlmc_run(int op)
1562 	{
1563 		int do_start = (op == OP_RUN) || (op == OP_RUN_START);
1564 		int do_check = (op == OP_RUN) || (op == OP_RUN_CHECK);
1565 		int do_cancel = (op == OP_RUN_CANCEL);
1566 		uint32_t flags = 0;
1567 		uint32_t check_status = 0;
1568 		int rv = 0;
1569 	
1570 		if (do_start) {
1571 			/* FIXME: use proper option to specify */
1572 			flags = DLMC_FLAG_RUN_START_NODE_NONE;
1573 			if (ls_all_nodes)
1574 				flags = DLMC_FLAG_RUN_START_NODE_RECV;
1575 	
1576 			rv = dlmc_run_start(run_command, strlen(run_command), 0,
1577 					    flags, run_uuid);
1578 	
1579 			printf("run_uuid: %s\n", run_uuid);
1580 		}
1581 	
1582 		if (do_check || do_cancel) {
1583 			if (do_cancel)
1584 				flags = DLMC_FLAG_RUN_CHECK_CANCEL;
1585 			else
1586 				flags = DLMC_FLAG_RUN_CHECK_CLEAR;
1587 	
1588 			rv = dlmc_run_check(run_uuid, strlen(run_uuid), wait_sec, flags,
1589 					    &check_status);
1590 	
1591 			printf("check_status: ");
1592 	
1593 			if (check_status & DLMC_RUN_STATUS_WAITING)
1594 				printf("waiting ");
1595 			if (check_status & DLMC_RUN_STATUS_DONE)
1596 				printf("done ");
1597 			if (check_status & DLMC_RUN_STATUS_FAILED)
1598 				printf("failed ");
1599 			printf("\n");
1600 		}
1601 	
1602 		return rv;
1603 	}
1604 	
1605 	static char dlms_buf[DLM_SD_DUMP_SIZE];
1606 	
1607 	static int _dlms_dump(int op)
1608 	{
1609 		struct dlm_sd_header h = { 0 };
1610 		uint32_t cmd;
1611 		int len;
1612 		int rv;
1613 	
1614 		if (op == OP_DUMP_DEBUG)
1615 			cmd = DLM_SDQ_CMD_DUMP_DEBUG;
1616 		else if (op == OP_DUMP_CONFIG)
1617 			cmd = DLM_SDQ_CMD_DUMP_CONFIG;
1618 		else if (op == OP_DUMP_STATUS)
1619 			cmd = DLM_SDQ_CMD_DUMP_STATUS;
1620 		else
1621 			return -1;
1622 	
1623 		h.magic = DLM_SD_MAGIC;
1624 		h.version = DLM_SD_VERSION;
1625 		h.command = cmd;
1626 		h.len = sizeof(h);
1627 	
1628 		rv = do_write(dlms_fd, &h, sizeof(h));
1629 		if (rv < 0) {
1630 			printf("cannot send to dlm_sand\n");
1631 			return rv;
1632 		}
1633 	
1634 		memset(&h, 0, sizeof(h));
1635 	
1636 		rv = do_read(dlms_fd, &h, sizeof(h));
1637 		if (rv < 0)
1638 			return rv;
1639 	
1640 		len = h.len - sizeof(h);
1641 	
1642 		rv = do_read(dlms_fd, dlms_buf, len);
1643 		if (rv < 0)
1644 			return rv;
1645 	
1646 		fprintf(stdout, "%s\n", dlms_buf);
1647 		return 0;
1648 	}
1649 	
1650 	static int daemon_status(int v)
1651 	{
1652 		if (use_dlmc)
1653 			return dlmc_print_status(v ? DLMC_STATUS_VERBOSE : 0);
1654 		else
1655 			return _dlms_dump(OP_DUMP_STATUS);
1656 	}
1657 	
1658 	static int daemon_dump(int op)
1659 	{
1660 		if (use_dlmc)
1661 			return _dlmc_dump(op);
1662 		else
1663 			return _dlms_dump(op);
1664 	}
1665 	
1666 	static void daemon_reload_config(void)
1667 	{
1668 		if (use_dlmc)
1669 			_dlmc_reload_config();
1670 		/*
1671 		else
1672 			_dlms_reload_config();
1673 		*/
1674 	}
1675 	
1676 	static void daemon_set_config(void)
1677 	{
1678 		if (use_dlmc)
1679 			_dlmc_set_config();
1680 		/*
1681 		else
1682 			_dlms_set_config();
1683 		*/
1684 	}
1685 	
1686 	static int _daemon_socket_connect(const char *sock_path, int *fd_out)
1687 	{
1688 		struct sockaddr_un sun;
1689 		socklen_t addrlen;
1690 		int rv, fd;
1691 	
1692 		fd = socket(PF_UNIX, SOCK_STREAM, 0);
1693 		if (fd < 0)
1694 			return -1;
1695 	
1696 		memset(&sun, 0, sizeof(sun));
1697 		sun.sun_family = AF_UNIX;
1698 		strcpy(&sun.sun_path[1], sock_path);
1699 		addrlen = sizeof(sa_family_t) + strlen(sun.sun_path+1) + 1;
1700 	
1701 		rv = connect(fd, (struct sockaddr *) &sun, addrlen);
1702 		if (rv < 0) {
1703 			close(fd);
1704 			return rv;
1705 		}
1706 		*fd_out = fd;
1707 		return 0;
1708 	}
1709 	
1710 	static int _daemon_connect(int query_op, int *fd_out)
1711 	{
1712 		if (query_op) {
1713 			if (!_daemon_socket_connect(DLMC_QUERY_SOCK_PATH, fd_out)) {
1714 				use_dlmc = 1;
1715 				return 0;
1716 			}
1717 	
1718 			if (!_daemon_socket_connect(DLM_SDQ_SOCK_PATH, fd_out)) {
1719 				use_dlms = 1;
1720 				return 0;
1721 			}
1722 		} else {
1723 			if (!_daemon_socket_connect(DLMC_SOCK_PATH, fd_out)) {
1724 				use_dlmc = 1;
1725 				return 0;
1726 			}
1727 	
1728 			if (!_daemon_socket_connect(DLM_SD_SOCK_PATH, fd_out)) {
1729 				use_dlms = 1;
1730 				return 0;
1731 			}
1732 		}
1733 		return -1;
1734 	}
1735 	
1736 	static int is_daemon_op(int op, int *query_op, int *only_dlmc)
1737 	{
1738 		int rv = 0;
1739 	
1740 		switch (op) {
1741 		case OP_LIST:
1742 		case OP_LOG_PLOCK:
1743 		case OP_PLOCKS:
1744 		case OP_FENCE_ACK:
1745 		case OP_RUN:
1746 		case OP_RUN_START:
1747 		case OP_RUN_CHECK:
1748 		case OP_RUN_CANCEL:
1749 		case OP_DUMP_RUN:
1750 			*only_dlmc = 1;
1751 			rv = 1;
1752 			break;
1753 		case OP_DUMP_DEBUG:
1754 		case OP_DUMP_STATUS:
1755 		case OP_DUMP_CONFIG:
1756 		case OP_RELOAD_CONFIG:
1757 		case OP_SET_CONFIG:
1758 			*only_dlmc = 0;
1759 			rv = 1;
1760 			break;
1761 		default:
1762 			rv = 0;
1763 		}
1764 	
1765 		switch (op) {
1766 		case OP_LIST:
1767 		case OP_DUMP_RUN:
1768 		case OP_DUMP_DEBUG:
1769 		case OP_DUMP_STATUS:
1770 		case OP_DUMP_CONFIG:
1771 		case OP_LOG_PLOCK:
1772 		case OP_PLOCKS:
1773 			*query_op = 1;
1774 			rv = 1;
1775 			break;
1776 		case OP_FENCE_ACK:
1777 		case OP_RUN:
1778 		case OP_RUN_START:
1779 		case OP_RUN_CHECK:
1780 		case OP_RUN_CANCEL:
1781 		case OP_RELOAD_CONFIG:
1782 		case OP_SET_CONFIG:
1783 			*query_op = 0;
1784 			rv = 1;
1785 			break;
1786 		default:
1787 			rv = 0;
1788 		}
1789 	
1790 		return rv;
1791 	}
1792 	
1793 	int main(int argc, char **argv)
1794 	{
1795 		prog_name = argv[0];
1796 		decode_arguments(argc, argv);
1797 		int query_op = 0;
1798 		int only_dlmc = 0;
1799 		int fd;
1800 		int rv = 0;
1801 	
1802 		if (is_daemon_op(operation, &query_op, &only_dlmc)) {
1803 			rv = _daemon_connect(query_op, &fd);
1804 			if (rv < 0) {
1805 				fprintf(stderr, "Cannot connect to dlm daemon.\n");
1806 				return -1;
1807 			}
1808 	
1809 			/* libdlmcontrol apis create their own fd connection */
1810 			if (use_dlmc)
1811 				close(fd);
1812 			if (use_dlms)
1813 				dlms_fd = fd;
1814 		}
1815 	
1816 		if (!use_dlmc && only_dlmc) {
1817 			fprintf(stderr, "Command only valid for dlm_controld.\n");
1818 			return -1;
1819 		}
1820 	
1821 		switch (operation) {
1822 	
1823 		/* libdlm commands, kernel-based op */
1824 	
1825 		case OP_JOIN:
1826 			do_join(lsname);
1827 			break;
1828 		case OP_LEAVE:
1829 			do_leave(lsname);
1830 			break;
1831 		case OP_JOINLEAVE:
1832 			do_join(lsname);
1833 			do_leave(lsname);
1834 			break;
1835 	
1836 		/* debugfs commands */
1837 	
1838 		case OP_LOCKDUMP:
1839 			do_lockdump(lsname);
1840 			break;
1841 		case OP_LOCKDEBUG:
1842 			do_lockdebug(lsname);
1843 			break;
1844 	
1845 		/* dlm_controld-only commands */
1846 	
1847 		case OP_LIST:
1848 			_dlmc_list(lsname);
1849 			break;
1850 		case OP_LOG_PLOCK:
1851 			rv = _dlmc_log_plock();
1852 			break;
1853 		case OP_PLOCKS:
1854 			rv = _dlmc_plocks(lsname);
1855 			break;
1856 		case OP_FENCE_ACK:
1857 			dlmc_fence_ack(lsname);
1858 			break;
1859 		case OP_RUN:
1860 		case OP_RUN_START:
1861 		case OP_RUN_CHECK:
1862 		case OP_RUN_CANCEL:
1863 			rv = _dlmc_run(operation);
1864 			break;
1865 		case OP_DUMP_RUN:
1866 			rv = _dlmc_dump(operation);
1867 			break;
1868 	
1869 		/* dlm_controld or dlm_sand commands */
1870 	
1871 		case OP_DUMP_STATUS:
1872 			rv = daemon_status(verbose);
1873 			break;
1874 		case OP_DUMP_DEBUG:
1875 		case OP_DUMP_CONFIG:
1876 			rv = daemon_dump(operation);
1877 			break;
1878 		case OP_RELOAD_CONFIG:
1879 			daemon_reload_config();
1880 			break;
1881 		case OP_SET_CONFIG:
1882 			daemon_set_config();
1883 			break;
1884 		}
1885 	
1886 		if (dlms_fd)
1887 			close(dlms_fd);
1888 	
1889 		if (rv < 0) {
1890 			fprintf(stderr, "failed: %s\n", strerror(-rv));
1891 			return EXIT_FAILURE;
1892 		}
1893 	
1894 		return EXIT_SUCCESS;
1895 	}
1896