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));
1355 rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_MEMBERS,
1356 MAX_NODES, &node_count, nodes);
1357 if (rv < 0) {
1358 printf("members error\n");
1359 goto next;
1360 }
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
|
(1) Event cond_true: |
Condition "name", taking true branch. |
1430 if (name) {
1431 /* get only one specific lockspace by name */
1432 ls_count = 1;
1433 lss = malloc(sizeof(struct dlmc_lockspace));
|
(2) Event cond_false: |
Condition "!lss", taking false branch. |
1434 if (!lss)
|
(3) Event if_end: |
End of if statement. |
1435 exit(EXIT_FAILURE);
1436
1437 rv = dlmc_lockspace_info(name, lss);
|
(4) Event if_fallthrough: |
Falling through to end of if statement. |
1438 } else {
1439 rv = dlmc_lockspaces(&ls_count, &lss);
|
(5) Event if_end: |
End of if statement. |
1440 }
1441
|
(6) Event cond_false: |
Condition "rv < 0", taking false branch. |
1442 if (rv < 0)
|
(7) Event if_end: |
End of if statement. |
1443 exit(EXIT_FAILURE); /* dlm_controld probably not running */
1444
|
(8) Event cond_true: |
Condition "ls_count", taking true branch. |
1445 if (ls_count)
1446 printf("dlm lockspaces\n");
1447
|
(9) Event cond_true: |
Condition "i < ls_count", taking true branch. |
1448 for (i = 0; i < ls_count; i++) {
1449 ls = &lss[i];
1450
1451 show_ls(ls);
1452
|
(10) Event cond_false: |
Condition "!ls_all_nodes", taking false branch. |
1453 if (!ls_all_nodes)
|
(11) Event if_end: |
End of if statement. |
1454 goto next;
1455
1456 node_count = 0;
1457 memset(&nodes, 0, sizeof(nodes));
1458
|
(12) Event tainted_argument: |
Calling function "dlmc_lockspace_nodes" taints argument "node_count". [details] |
| Also see events: |
[tainted_data][remediation] |
1459 rv = dlmc_lockspace_nodes(ls->name, DLMC_NODES_ALL,
1460 MAX_NODES, &node_count, nodes);
|
(13) Event cond_false: |
Condition "rv < 0", taking false branch. |
1461 if (rv < 0) {
1462 printf("all nodes error %d %d\n", rv, errno);
1463 goto next;
|
(14) Event if_end: |
End of if statement. |
1464 }
1465
|
(15) Event tainted_data: |
Passing tainted expression "node_count" to "qsort", which uses it as an offset. |
|
(16) Event remediation: |
Ensure that tainted values are properly sanitized, by checking that their values are within a permissible range. |
| Also see events: |
[tainted_argument] |
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