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 <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <stdint.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <time.h>
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <sys/un.h>
19
20 #include <linux/dlmconstants.h>
21 #include "dlm_controld.h"
22 #include "libdlmcontrol.h"
23
24 static int do_read(int fd, void *buf, size_t count)
25 {
26 int rv, off = 0;
27
28 while (off < count) {
29 rv = read(fd, (char *)buf + off, count - off);
30 if (rv == 0)
31 return -1;
32 if (rv == -1 && errno == EINTR)
33 continue;
34 if (rv == -1)
35 return -1;
36 off += rv;
37 }
38 return 0;
39 }
40
41 static int do_write(int fd, void *buf, size_t count)
42 {
43 int rv, off = 0;
44
45 retry:
46 rv = write(fd, (char *)buf + off, count);
47 if (rv == -1 && errno == EINTR)
48 goto retry;
49 if (rv < 0) {
50 return rv;
51 }
52
53 if (rv != count) {
54 count -= rv;
55 off += rv;
56 goto retry;
57 }
58 return 0;
59 }
60
61 static int do_connect(const char *sock_path)
62 {
63 struct sockaddr_un sun;
64 socklen_t addrlen;
65 int rv, fd;
66
67 fd = socket(PF_UNIX, SOCK_STREAM, 0);
68 if (fd < 0)
69 goto out;
70
71 memset(&sun, 0, sizeof(sun));
72 sun.sun_family = AF_UNIX;
73 strcpy(&sun.sun_path[1], sock_path);
74 addrlen = sizeof(sa_family_t) + strlen(sun.sun_path+1) + 1;
75
76 rv = connect(fd, (struct sockaddr *) &sun, addrlen);
77 if (rv < 0) {
78 close(fd);
79 fd = rv;
80 }
81 out:
82 return fd;
83 }
84
85 static inline void init_header_name(struct dlmc_header *h,
86 const char *name, size_t len)
87 {
88 #pragma GCC diagnostic push
89 #if __GNUC__ >= 8
90 #pragma GCC diagnostic ignored "-Wstringop-truncation"
91 #endif
92 strncpy(h->name, name, len);
93 #pragma GCC diagnostic pop
94 }
95
96 static void init_header(struct dlmc_header *h, int cmd, char *name,
97 int extra_len)
98 {
99 memset(h, 0, sizeof(struct dlmc_header));
100
101 h->magic = DLMC_MAGIC;
102 h->version = DLMC_VERSION;
103 h->len = sizeof(struct dlmc_header) + extra_len;
104 h->command = cmd;
105
106 if (name)
107 init_header_name(h, name, DLM_LOCKSPACE_LEN);
108 }
109
110 static char copy_buf[DLMC_DUMP_SIZE];
111
112 static int do_dump(int cmd, char *name, char *buf, int *data)
113 {
114 struct dlmc_header h;
115 int fd, rv, len;
116
117 memset(copy_buf, 0, DLMC_DUMP_SIZE);
118
119 init_header(&h, cmd, name, 0);
120
121 *data = 0;
122
123 fd = do_connect(DLMC_QUERY_SOCK_PATH);
124 if (fd < 0) {
125 rv = fd;
126 goto out;
127 }
128
129 rv = do_write(fd, &h, sizeof(h));
130 if (rv < 0)
131 goto out_close;
132
133 memset(&h, 0, sizeof(h));
134
135 rv = do_read(fd, &h, sizeof(h));
136 if (rv < 0)
137 goto out_close;
138
139 *data = h.data;
140 len = h.len - sizeof(h);
141
142 if (len <= 0 || len > DLMC_DUMP_SIZE)
143 goto out_close;
144
145 rv = do_read(fd, copy_buf, len);
146 if (rv < 0)
147 goto out_close;
148
149 memcpy(buf, copy_buf, len);
150 out_close:
151 close(fd);
152 out:
153 return rv;
154 }
155
156 int dlmc_dump_debug(char *buf, int *data)
157 {
158 return do_dump(DLMC_CMD_DUMP_DEBUG, NULL, buf, data);
159 }
160
161 int dlmc_dump_config(char *buf, int *data)
162 {
163 return do_dump(DLMC_CMD_DUMP_CONFIG, NULL, buf, data);
164 }
165
166 int dlmc_dump_log_plock(char *buf, int *data)
167 {
168 return do_dump(DLMC_CMD_DUMP_LOG_PLOCK, NULL, buf, data);
169 }
170
171 int dlmc_dump_plocks(char *name, char *buf, int *data)
172 {
173 return do_dump(DLMC_CMD_DUMP_PLOCKS, name, buf, data);
174 }
175
176 int dlmc_dump_run(char *buf, int *data)
177 {
178 return do_dump(DLMC_CMD_DUMP_RUN, NULL, buf, data);
179 }
180
181 int dlmc_reload_config(void)
182 {
183 struct dlmc_header h;
184 int fd, rv;
185
186 init_header(&h, DLMC_CMD_RELOAD_CONFIG, NULL, 0);
187
188 fd = do_connect(DLMC_SOCK_PATH);
189 if (fd < 0) {
190 rv = fd;
191 goto out;
192 }
193
194 rv = do_write(fd, &h, sizeof(h));
195 close(fd);
196 out:
197 return rv;
198 }
199
200 int dlmc_set_config(char *command)
201 {
202 struct dlmc_header h;
203 char *cmdbuf;
204 int fd, rv;
205
206 cmdbuf = malloc(DLMC_RUN_COMMAND_LEN);
207 if (!cmdbuf)
208 return -1;
209
210 memset(cmdbuf, 0, DLMC_RUN_COMMAND_LEN);
211 strncpy(cmdbuf, command, DLMC_RUN_COMMAND_LEN-1);
212
213 init_header(&h, DLMC_CMD_SET_CONFIG, NULL, DLMC_RUN_COMMAND_LEN);
214
215 fd = do_connect(DLMC_SOCK_PATH);
216 if (fd < 0) {
217 rv = fd;
218 goto out;
219 }
220
221 rv = do_write(fd, &h, sizeof(h));
222 if (rv < 0)
223 goto out_close;
224
225 rv = do_write(fd, cmdbuf, DLMC_RUN_COMMAND_LEN);
226 if (rv < 0)
227 goto out_close;
228
229 out_close:
230 close(fd);
231 out:
232 free(cmdbuf);
233 return rv;
234 }
235
236 static int nodeid_compare(const void *va, const void *vb)
237 {
238 const int *a = va;
239 const int *b = vb;
240
241 return *a - *b;
242 }
243
244 static void print_str(char *str, int len)
245 {
246 char *p;
247 int i;
248
249 p = &str[0];
250 for (i = 0; i < len-1; i++) {
251 if (str[i] == ' ') {
252 str[i] = '\0';
253 printf(" %s\n", p);
254 p = &str[i+1];
255 }
256 }
257
258 if (p)
259 printf(" %s\n", p);
260 }
261
262 static unsigned int kv(char *str, const char *k)
263 {
264 char valstr[64];
265 char *p;
266 int i;
267
268 p = strstr(str, k);
269 if (!p)
270 return 0;
271
272 p = strstr(p, "=");
273 if (!p)
274 return 0;
275
276 /* move pointer after '=' */
277 p++;
278
279 memset(valstr, 0, 64);
280
281 for (i = 0; i < 64; i++) {
282 if (*p == ' ')
283 break;
284 if (*p == '\0')
285 break;
286 if (*p == '\n')
287 break;
288 valstr[i] = *p;
289 p++;
290 }
291
292 return (unsigned int)strtoul(valstr, NULL, 0);
293 }
294
295 static char *ks(char *str, const char *k)
296 {
297 static char valstr[64];
298 char *p;
299 int i;
300
301 p = strstr(str, k);
302 if (!p)
303 return 0;
304
305 p = strstr(p, "=");
306 if (!p)
307 return 0;
308
309 /* move pointer after '=' */
310 p++;
311
312 memset(valstr, 0, 64);
313
314 for (i = 0; i < 64; i++) {
315 if (*p == ' ')
316 break;
317 if (*p == '\0')
318 break;
319 if (*p == '\n')
320 break;
321 valstr[i] = *p;
322 p++;
323 }
324
325 return valstr;
326 }
327
328 static void print_daemon(struct dlmc_state *st, char *str, char *bin, uint32_t flags)
329 {
330 unsigned int cluster_ringid, daemon_ringid;
331 unsigned int fipu;
332
333 if (flags & DLMC_STATUS_VERBOSE) {
334 printf("our_nodeid %d\n", st->nodeid);
335 print_str(str, st->str_len);
336 return;
337 }
338
339 cluster_ringid = kv(str, "cluster_ringid");
340 daemon_ringid = kv(str, "daemon_ringid");
341
342 printf("cluster nodeid %d quorate %u ring seq %u %u\n",
343 st->nodeid,
344 kv(str, "quorate"),
345 cluster_ringid, daemon_ringid);
346
347 fipu = kv(str, "fence_in_progress_unknown");
348
349 printf("daemon now %u fence_pid %u %s\n",
350 kv(str, "monotime"),
351 kv(str, "fence_pid"),
352 fipu ? "fence_init" : "");
353 }
354
355 static void format_daemon_node(struct dlmc_state *st, char *str, char *bin, uint32_t flags,
356 char *node_line, char *fence_line)
357 {
358 unsigned int delay_fencing, result_wait, killed;
359 char letter;
360
361 if (st->type == DLMC_STATE_STARTUP_NODE)
362 letter = 'U';
363 else if (kv(str, "member"))
364 letter = 'M';
365 else
366 letter = 'X';
367
368
369 snprintf(node_line, DLMC_STATE_MAXSTR - 1,
370 "node %d %c add %u rem %u fail %u fence %u at %u %u\n",
371 st->nodeid,
372 letter,
373 kv(str, "add_time"),
374 kv(str, "rem_time"),
375 kv(str, "fail_monotime"),
376 kv(str, "fence_monotime"),
377 kv(str, "actor_done"),
378 kv(str, "fence_walltime"));
379
380 if (!kv(str, "need_fencing"))
381 return;
382
383 delay_fencing = kv(str, "delay_fencing");
384 result_wait = kv(str, "fence_result_wait");
385 killed = kv(str, "killed");
386
387 if (delay_fencing)
388 snprintf(fence_line, DLMC_STATE_MAXSTR - 1,
389 "fence %d %s delay actor %u fail %u fence %u now %u%s%s\n",
390 st->nodeid,
391 ks(str, "left_reason"),
392 kv(str, "actor_last"),
393 kv(str, "fail_walltime"),
394 kv(str, "fence_walltime"),
395 (unsigned int)time(NULL),
396 result_wait ? " result_wait" : "",
397 killed ? " killed" : "");
398 else
399 snprintf(fence_line, DLMC_STATE_MAXSTR - 1,
400 "fence %d %s pid %d actor %u fail %u fence %u now %u%s%s\n",
401 st->nodeid,
402 ks(str, "left_reason"),
403 kv(str, "fence_pid"),
404 kv(str, "actor_last"),
405 kv(str, "fail_walltime"),
406 kv(str, "fence_walltime"),
407 (unsigned int)time(NULL),
408 result_wait ? " result_wait" : "",
409 killed ? " killed" : "");
410 }
411
412 #define MAX_SORT 64
413
414 int dlmc_print_status(uint32_t flags)
415 {
416 struct dlmc_header h;
417 struct dlmc_state state;
418 struct dlmc_state *st;
419 char maxstr[DLMC_STATE_MAXSTR];
420 char maxbin[DLMC_STATE_MAXBIN];
421 char *str;
422 char *bin;
423 int all_count, node_count, fence_count, startup_count;
424 int all_ids[MAX_SORT];
425 int node_ids[MAX_SORT];
426 int fence_ids[MAX_SORT];
427 int startup_ids[MAX_SORT];
428 char *node_lines[MAX_SORT];
429 char *fence_lines[MAX_SORT];
430 char *node_line;
431 char *fence_line;
432 int found_node;
433 int fd, rv;
434 int i, j;
435
436 init_header(&h, DLMC_CMD_DUMP_STATUS, NULL, 0);
437
438 fd = do_connect(DLMC_QUERY_SOCK_PATH);
439 if (fd < 0) {
440 printf("cannot connect to dlm_controld\n");
441 rv = fd;
442 goto out;
443 }
444
445 rv = do_write(fd, &h, sizeof(h));
446 if (rv < 0) {
447 printf("cannot send to dlm_controld\n");
448 goto out_close;
449 }
450
451 st = &state;
452 str = maxstr;
453 bin = maxbin;
454
455 all_count = 0;
456 node_count = 0;
457 fence_count = 0;
458 startup_count = 0;
459 memset(&all_ids, 0, sizeof(all_ids));
460 memset(&node_ids, 0, sizeof(node_ids));
461 memset(&fence_ids, 0, sizeof(fence_ids));
462 memset(&startup_ids, 0, sizeof(startup_ids));
463 memset(node_lines, 0, sizeof(node_lines));
464 memset(fence_lines, 0, sizeof(fence_lines));
465
466 while (1) {
467 memset(&state, 0, sizeof(state));
468 memset(maxstr, 0, sizeof(maxstr));
469 memset(maxbin, 0, sizeof(maxbin));
470
471 rv = recv(fd, st, sizeof(struct dlmc_state), MSG_WAITALL);
472 if (!rv)
473 break;
474 if (rv != sizeof(struct dlmc_state))
475 break;
476
477 if (st->str_len) {
478 rv = recv(fd, str, st->str_len, MSG_WAITALL);
479 if (rv != st->str_len)
480 break;
481 }
482
483 if (st->bin_len) {
484 rv = recv(fd, bin, st->bin_len, MSG_WAITALL);
485 if (rv != st->bin_len)
486 break;
487 }
488
489 switch (st->type) {
490 case DLMC_STATE_DAEMON:
491 print_daemon(st, str, bin, flags);
492 break;
493
494 case DLMC_STATE_STARTUP_NODE:
495 startup_ids[startup_count++] = st->nodeid;
496 break;
497
498 case DLMC_STATE_DAEMON_NODE:
499 if (flags & DLMC_STATUS_VERBOSE) {
500 printf("nodeid %d\n", st->nodeid);
501 print_str(str, st->str_len);
502 } else {
503 node_line = malloc(DLMC_STATE_MAXSTR);
504 if (!node_line)
505 break;
506 fence_line = malloc(DLMC_STATE_MAXSTR);
507 if (!fence_line) {
508 free(node_line);
509 break;
510 }
511 memset(node_line, 0, DLMC_STATE_MAXSTR);
512 memset(fence_line, 0, DLMC_STATE_MAXSTR);
513
514 format_daemon_node(st, str, bin, flags,
515 node_line, fence_line);
516
517 all_ids[all_count++] = st->nodeid;
518
519 node_ids[node_count] = st->nodeid;
520 node_lines[node_count] = node_line;
521 node_count++;
522
523 if (!fence_line[0]) {
524 free(fence_line);
525 } else {
526 fence_ids[fence_count] = st->nodeid;
527 fence_lines[fence_count] = fence_line;
528 fence_count++;
529 }
530 }
531 break;
532
533 default:
534 break;
535 }
536
537 if (rv < 0)
538 break;
539 }
540
541 if (all_count)
542 qsort(all_ids, all_count, sizeof(int), nodeid_compare);
543
544 /* don't free any node_lines in this startup loop because we are just
545 borrowing them; they are needed in the real node loop below. */
546
547 if (startup_count) {
548 for (i = 0; i < startup_count; i++) {
549 found_node = 0;
550 for (j = 0; j < node_count; j++) {
551 if (startup_ids[i] != node_ids[j])
552 continue;
553 found_node = 1;
554 if (!node_lines[j])
555 printf("startup node %d\n", st->nodeid);
556 else
557 printf("startup %s", node_lines[j]);
558 break;
559 }
560 if (!found_node)
561 printf("startup node %d\n", st->nodeid);
562 }
563 }
564
565 if (all_count && fence_count) {
566 for (i = 0; i < all_count; i++) {
567 for (j = 0; j < fence_count; j++) {
568 if (all_ids[i] != fence_ids[j])
569 continue;
570 if (!fence_lines[j]) {
571 printf("fence %d no data\n", fence_ids[j]);
572 } else {
573 printf("%s", fence_lines[j]);
574 free(fence_lines[j]);
575 fence_lines[j] = NULL;
576 }
577 break;
578 }
579 }
580 }
581
582 if (all_count && node_count) {
583 for (i = 0; i < all_count; i++) {
584 for (j = 0; j < node_count; j++) {
585 if (all_ids[i] != node_ids[j])
586 continue;
587 if (!node_lines[j]) {
588 printf("node %d no data\n", node_ids[j]);
589 } else {
590 printf("%s", node_lines[j]);
591 free(node_lines[j]);
592 node_lines[j] = NULL;
593 }
594 break;
595 }
596 }
597 }
598
599 out_close:
600 close(fd);
601 out:
602 return rv;
603 }
604
605 int dlmc_node_info(char *name, int nodeid, struct dlmc_node *node)
606 {
607 struct dlmc_header h, *rh;
608 char reply[sizeof(struct dlmc_header) + sizeof(struct dlmc_node)];
609 int fd, rv;
610
611 init_header(&h, DLMC_CMD_NODE_INFO, name, 0);
612 h.data = nodeid;
613
614 memset(reply, 0, sizeof(reply));
615
616 fd = do_connect(DLMC_QUERY_SOCK_PATH);
617 if (fd < 0) {
618 rv = fd;
619 goto out;
620 }
621
622 rv = do_write(fd, &h, sizeof(h));
623 if (rv < 0)
624 goto out_close;
625
626 rv = do_read(fd, reply, sizeof(reply));
627 if (rv < 0)
628 goto out_close;
629
630 rh = (struct dlmc_header *)reply;
631 rv = rh->data;
632 if (rv < 0)
633 goto out_close;
634
635 memcpy(node, (char *)reply + sizeof(struct dlmc_header),
636 sizeof(struct dlmc_node));
637 out_close:
638 close(fd);
639 out:
640 return rv;
641 }
642
643 int dlmc_lockspace_info(char *name, struct dlmc_lockspace *lockspace)
644 {
645 struct dlmc_header h, *rh;
646 char reply[sizeof(struct dlmc_header) + sizeof(struct dlmc_lockspace)];
647 int fd, rv;
648
649 init_header(&h, DLMC_CMD_LOCKSPACE_INFO, name, 0);
650
651 memset(reply, 0, sizeof(reply));
652
653 fd = do_connect(DLMC_QUERY_SOCK_PATH);
654 if (fd < 0) {
655 rv = fd;
656 goto out;
657 }
658
659 rv = do_write(fd, &h, sizeof(h));
660 if (rv < 0)
661 goto out_close;
662
663 rv = do_read(fd, reply, sizeof(reply));
664 if (rv < 0)
665 goto out_close;
666
667 rh = (struct dlmc_header *)reply;
668 rv = rh->data;
669 if (rv < 0)
670 goto out_close;
671
672 memcpy(lockspace, (char *)reply + sizeof(struct dlmc_header),
673 sizeof(struct dlmc_lockspace));
674 out_close:
675 close(fd);
676 out:
677 return rv;
678 }
679
680 int dlmc_lockspaces(int *count, struct dlmc_lockspace **lss)
681 {
682 struct dlmc_header h;
683 int reply_len;
684 int fd, rv, result;
685
686 fd = do_connect(DLMC_QUERY_SOCK_PATH);
687 if (fd < 0) {
688 rv = fd;
689 goto out;
690 }
691
692 init_header(&h, DLMC_CMD_LOCKSPACES, NULL, 0);
693
694 rv = do_write(fd, &h, sizeof(h));
695 if (rv < 0)
696 goto out_close;
697
698 rv = do_read(fd, &h, sizeof(h));
699 if (rv <0)
700 goto out_close;
701
702 result = h.data;
703 if (result < 0) {
704 rv = result;
705 goto out_close;
706 }
707
708 *count = result;
709
710 reply_len = h.len - sizeof(struct dlmc_header);
711 *lss = malloc(reply_len);
712 if (!*lss) {
713 rv = -1;
714 goto out;
715 }
716 memset(*lss, 0, reply_len);
717
718 rv = do_read(fd, *lss, reply_len);
719 if (rv < 0) {
720 free(*lss);
721 goto out;
722 }
723
724 rv = 0;
725
726 out_close:
727 close(fd);
728 out:
729 return rv;
730 }
731
732 int dlmc_lockspace_nodes(char *name, int type, int max, int *count,
733 struct dlmc_node *nodes)
734 {
735 struct dlmc_header h, *rh;
736 char *reply;
737 int reply_len;
738 int fd, rv, result, node_count;
739
740 init_header(&h, DLMC_CMD_LOCKSPACE_NODES, name, 0);
741 h.option = type;
742 h.data = max;
743
744 reply_len = sizeof(struct dlmc_header) +
745 (max * sizeof(struct dlmc_node));
746 reply = malloc(reply_len);
747 if (!reply) {
748 rv = -1;
749 goto out;
750 }
751 memset(reply, 0, reply_len);
752
753 fd = do_connect(DLMC_QUERY_SOCK_PATH);
754 if (fd < 0) {
755 rv = fd;
756 goto out;
757 }
758
759 rv = do_write(fd, &h, sizeof(h));
760 if (rv < 0)
761 goto out_close;
762
763 /* won't usually get back the full reply_len */
764 do_read(fd, reply, reply_len);
765
766 rh = (struct dlmc_header *)reply;
767 result = rh->data;
768 if (result < 0 && result != -E2BIG) {
769 rv = result;
770 goto out_close;
771 }
772
773 if (result == -E2BIG) {
774 *count = -E2BIG;
775 node_count = max;
776 } else {
777 *count = result;
778 node_count = result;
779 }
780 rv = 0;
781
782 memcpy(nodes, (char *)reply + sizeof(struct dlmc_header),
783 node_count * sizeof(struct dlmc_node));
784 out_close:
785 close(fd);
786 out:
787 return rv;
788 }
789
790 int dlmc_fs_connect(void)
791 {
792 return do_connect(DLMC_SOCK_PATH);
793 }
794
795 void dlmc_fs_disconnect(int fd)
796 {
797 close(fd);
798 }
799
800 int dlmc_fs_register(int fd, char *name)
801 {
802 struct dlmc_header h;
803
804 init_header(&h, DLMC_CMD_FS_REGISTER, name, 0);
805
806 return do_write(fd, &h, sizeof(h));
807 }
808
809 int dlmc_fs_unregister(int fd, char *name)
810 {
811 struct dlmc_header h;
812
813 init_header(&h, DLMC_CMD_FS_UNREGISTER, name, 0);
814
815 return do_write(fd, &h, sizeof(h));
816 }
817
818 int dlmc_fs_notified(int fd, char *name, int nodeid)
819 {
820 struct dlmc_header h;
821
822 init_header(&h, DLMC_CMD_FS_NOTIFIED, name, 0);
823 h.data = nodeid;
824
825 return do_write(fd, &h, sizeof(h));
826 }
827
828 int dlmc_fs_result(int fd, char *name, int *type, int *nodeid, int *result)
829 {
830 struct dlmc_header h;
831 int rv;
832
833 rv = do_read(fd, &h, sizeof(h));
834 if (rv < 0)
835 goto out;
836
837 strncpy(name, h.name, DLM_LOCKSPACE_LEN);
838 *nodeid = h.option;
839 *result = h.data;
840
841 switch (h.command) {
842 case DLMC_CMD_FS_REGISTER:
843 *type = DLMC_RESULT_REGISTER;
844 break;
845 case DLMC_CMD_FS_NOTIFIED:
846 *type = DLMC_RESULT_NOTIFIED;
847 break;
848 default:
849 *type = 0;
850 }
851 out:
852 return rv;
853 }
854
855 int dlmc_deadlock_check(char *name)
856 {
857 struct dlmc_header h;
858 int fd, rv;
859
860 init_header(&h, DLMC_CMD_DEADLOCK_CHECK, name, 0);
861
862 fd = do_connect(DLMC_SOCK_PATH);
863 if (fd < 0) {
864 rv = fd;
865 goto out;
866 }
867
868 rv = do_write(fd, &h, sizeof(h));
869 close(fd);
870 out:
871 return rv;
872 }
873
874 int dlmc_fence_ack(char *name)
875 {
876 struct dlmc_header h;
877 int fd, rv;
878
879 init_header(&h, DLMC_CMD_FENCE_ACK, name, 0);
880
881 fd = do_connect(DLMC_SOCK_PATH);
882 if (fd < 0) {
883 rv = fd;
884 goto out;
885 }
886
887 rv = do_write(fd, &h, sizeof(h));
888 close(fd);
889 out:
890 return rv;
891 }
892
893 int dlmc_run_start(char *run_command, int len, int nodeid, uint32_t flags, char *run_uuid)
894 {
895 struct dlmc_header h;
896 struct dlmc_header rh;
897 char *cmdbuf;
898 int fd, rv;
899
900 cmdbuf = malloc(DLMC_RUN_COMMAND_LEN);
901 if (!cmdbuf)
902 return -1;
903
904 memset(cmdbuf, 0, DLMC_RUN_COMMAND_LEN);
905 strncpy(cmdbuf, run_command, DLMC_RUN_COMMAND_LEN-1);
906
907 init_header(&h, DLMC_CMD_RUN_START, NULL, DLMC_RUN_COMMAND_LEN);
908 h.data = nodeid;
909 h.flags = flags;
910
911 memset(&rh, 0, sizeof(rh));
912
913 fd = do_connect(DLMC_SOCK_PATH);
914 if (fd < 0) {
915 rv = fd;
916 goto out;
917 }
918
919 rv = do_write(fd, &h, sizeof(h));
920 if (rv < 0)
921 goto out_close;
922
923 rv = do_write(fd, cmdbuf, DLMC_RUN_COMMAND_LEN);
924 if (rv < 0)
925 goto out_close;
926
927 rv = do_read(fd, &rh, sizeof(rh));
928 if (rv < 0)
929 goto out_close;
930
931 rv = rh.data;
932 if (rv < 0)
933 goto out_close;
934
935 memcpy(run_uuid, rh.name, DLMC_RUN_UUID_LEN);
936 rv = 0;
937
938 out_close:
939 close(fd);
940 out:
941 free(cmdbuf);
942 return rv;
943 }
944
945 int dlmc_run_check(char *run_uuid, int len, int wait_sec, uint32_t flags,
946 uint32_t *check_status)
947 {
948 struct dlmc_header h;
949 struct dlmc_header rh;
950 struct dlmc_run_check_state state;
951 uint64_t wait_start = 0;
952 int fd, rv;
953
954 init_header(&h, DLMC_CMD_RUN_CHECK, NULL, 0);
955 h.flags = flags;
956 init_header_name(&h, run_uuid, DLMC_RUN_UUID_LEN);
957
958 memset(&rh, 0, sizeof(rh));
959
960 fd = do_connect(DLMC_SOCK_PATH);
961 if (fd < 0) {
962 rv = fd;
963 goto out;
964 }
965
966 retry:
967
968 rv = do_write(fd, &h, sizeof(h));
969 if (rv < 0) {
970 goto out_close;
971 }
972
973 rv = do_read(fd, &rh, sizeof(rh));
974 if (rv < 0) {
975 goto out_close;
976 }
977
978 rv = do_read(fd, &state, sizeof(state));
979 if (rv < 0) {
980 goto out_close;
981 }
982
983 if ((state.check_status & DLMC_RUN_STATUS_WAITING) && wait_sec) {
984 if (!wait_start) {
985 wait_start = time(NULL);
986 sleep(1);
987 goto retry;
988 }
989
990 if (time(NULL) - wait_start < wait_sec) {
991 sleep(1);
992 goto retry;
993 }
994 }
995
996 *check_status = state.check_status;
997 rv = 0;
998
999 out_close:
1000 close(fd);
1001 out:
1002 return rv;
1003 }
1004
1005