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   	
(1) Event cond_true: Condition "off < count", taking true branch.
(9) Event loop_begin: Jumped back to beginning of loop.
(10) Event cond_true: Condition "off < count", taking true branch.
28   		while (off < count) {
(11) Event tainted_data_argument: Calling function "read" taints parameter "(char *)buf[off]". [Note: The source code implementation of the function has been overridden by a builtin model.]
29   			rv = read(fd, (char *)buf + off, count - off);
(2) Event cond_false: Condition "rv == 0", taking false branch.
(12) Event cond_true: Condition "rv == 0", taking true branch.
30   			if (rv == 0)
(3) Event if_end: End of if statement.
31   				return -1;
(4) Event cond_false: Condition "rv == -1", taking false branch.
32   			if (rv == -1 && errno == EINTR)
(5) Event if_end: End of if statement.
33   				continue;
(6) Event cond_false: Condition "rv == -1", taking false branch.
34   			if (rv == -1)
(7) Event if_end: End of if statement.
35   				return -1;
36   			off += rv;
(8) Event loop: Jumping back to the beginning of the loop.
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);
(1) Event cond_false: Condition "!reply", taking false branch.
747  		if (!reply) {
748  			rv = -1;
749  			goto out;
(2) Event if_end: End of if statement.
750  		}
751  		memset(reply, 0, reply_len);
752  	
753  		fd = do_connect(DLMC_QUERY_SOCK_PATH);
(3) Event cond_false: Condition "fd < 0", taking false branch.
754  		if (fd < 0) {
755  			rv = fd;
756  			goto out;
(4) Event if_end: End of if statement.
757  		}
758  	
759  		rv = do_write(fd, &h, sizeof(h));
(5) Event cond_false: Condition "rv < 0", taking false branch.
760  		if (rv < 0)
(6) Event if_end: End of if statement.
761  			goto out_close;
762  	
763  		/* won't usually get back the full reply_len */
(7) Event tainted_data_argument: Calling function "do_read" taints parameter "*reply". [details]
Also see events: [var_assign_alias][var_assign_alias][lower_bounds][parm_assign]
764  		do_read(fd, reply, reply_len);
765  	
(8) Event var_assign_alias: Assigning: "rh" = "(struct dlmc_header *)reply", which taints "rh".
Also see events: [tainted_data_argument][var_assign_alias][lower_bounds][parm_assign]
766  		rh = (struct dlmc_header *)reply;
(9) Event var_assign_alias: Assigning: "result" = "rh->data", which taints "result".
Also see events: [tainted_data_argument][var_assign_alias][lower_bounds][parm_assign]
767  		result = rh->data;
(10) Event cond_false: Condition "result < 0", taking false branch.
(12) Event lower_bounds: Checking lower bounds of signed scalar "result" by taking the false branch of "result < 0".
Also see events: [tainted_data_argument][var_assign_alias][var_assign_alias][parm_assign]
768  		if (result < 0 && result != -E2BIG) {
769  			rv = result;
770  			goto out_close;
(11) Event if_end: End of if statement.
771  		}
772  	
(13) Event cond_false: Condition "result == -7", taking false branch.
773  		if (result == -E2BIG) {
774  			*count = -E2BIG;
775  			node_count = max;
(14) Event else_branch: Reached else branch.
776  		} else {
(15) Event parm_assign: Assigning: "*count" = "result", which taints "*count".
Also see events: [tainted_data_argument][var_assign_alias][var_assign_alias][lower_bounds]
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