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 "dlm_daemon.h"
10   	
11   	#include <corosync/corotypes.h>
12   	#include <corosync/cmap.h>
13   	
14   	static int dir_members[MAX_NODES];
15   	static int dir_members_count;
16   	static int comms_nodes[MAX_NODES];
17   	static int comms_nodes_count;
18   	
19   	#define DLM_SYSFS_DIR "/sys/kernel/dlm"
20   	#define CLUSTER_DIR   "/sys/kernel/config/dlm/cluster"
21   	#define SPACES_DIR    "/sys/kernel/config/dlm/cluster/spaces"
22   	#define COMMS_DIR     "/sys/kernel/config/dlm/cluster/comms"
23   	
24   	static int detect_cluster_name(void)
25   	{
26   		cmap_handle_t handle;
27   		char *str = NULL;
28   		int rv, err = -1;
29   	
30   		rv = cmap_initialize(&handle);
31   		if (rv != CS_OK) {
32   			log_error("cmap_initialize error %d", rv);
33   			return -1; 
34   		}
35   	
36   		rv = cmap_get_string(handle, "totem.cluster_name", &str);
37   		if (rv != CS_OK) {
38   			log_error("cmap_get_string totem.cluster_name error %d", rv);
39   			goto out;
40   		} else
41   			err = 0;
42   	
43   		log_debug("cmap totem.cluster_name = '%s'", str);
44   	
45   		strncpy(cluster_name, str, DLM_LOCKSPACE_LEN);
46   	 out:
47   		if (str)
48   			free(str);
49   		cmap_finalize(handle);
50   		return err;
51   	}
52   	
53   	/* This is for the case where dlm_controld exits/fails, abandoning dlm
54   	   lockspaces in the kernel, and then dlm_controld is restarted.  When
55   	   dlm_controld exits and abandons lockspaces, that node needs to be
56   	   rebooted to clear the uncontrolled lockspaces from the kernel. */
57   	
58   	int check_uncontrolled_lockspaces(void)
59   	{
60   		DIR *d;
61   		struct dirent *de;
62   		int count = 0;
63   	
64   		d = opendir(DLM_SYSFS_DIR);
65   		if (!d)
66   			return 0;
67   	
68   		while ((de = readdir(d))) {
69   			if (de->d_name[0] == '.')
70   				continue;
71   	
72   			log_error("found uncontrolled lockspace %s", de->d_name);
73   			count++;
74   		}
75   		closedir(d);
76   	
77   		if (count) {
78   			kick_node_from_cluster(our_nodeid);
79   			return -1;
80   		}
81   		return 0;
82   	}
83   	
84   	static int do_sysfs(const char *name, const char *file, char *val)
85   	{
86   		char fname[512];
87   		int rv, fd;
88   	
89   		sprintf(fname, "%s/%s/%s", DLM_SYSFS_DIR, name, file);
90   	
91   		fd = open(fname, O_WRONLY);
92   		if (fd < 0) {
93   			log_error("open \"%s\" error %d %d", fname, fd, errno);
94   			return -1;
95   		}
96   	
97   		log_debug("write \"%s\" to \"%s\"", val, fname);
98   	
99   		rv = do_write(fd, val, strlen(val) + 1);
100  		close(fd);
101  		return rv;
102  	}
103  	
104  	int set_sysfs_control(char *name, int val)
105  	{
106  		char buf[32];
107  	
108  		memset(buf, 0, sizeof(buf));
109  		snprintf(buf, 32, "%d", val);
110  	
111  		return do_sysfs(name, "control", buf);
112  	}
113  	
114  	int set_sysfs_event_done(char *name, int val)
115  	{
116  		char buf[32];
117  	
118  		memset(buf, 0, sizeof(buf));
119  		snprintf(buf, 32, "%d", val);
120  	
121  		return do_sysfs(name, "event_done", buf);
122  	}
123  	
124  	int set_sysfs_id(char *name, uint32_t id)
125  	{
126  		char buf[32];
127  	
128  		memset(buf, 0, sizeof(buf));
129  		snprintf(buf, 32, "%u", id);
130  	
131  		return do_sysfs(name, "id", buf);
132  	}
133  	
134  	int set_sysfs_nodir(char *name, int val)
135  	{
136  		char buf[32];
137  	
138  		memset(buf, 0, sizeof(buf));
139  		snprintf(buf, 32, "%d", val);
140  	
141  		return do_sysfs(name, "nodir", buf);
142  	}
143  	
144  	static int update_dir_members(char *name)
145  	{
146  		char path[PATH_MAX];
147  		DIR *d;
148  		struct dirent *de;
149  		int i = 0;
150  	
151  		memset(path, 0, PATH_MAX);
152  		snprintf(path, PATH_MAX, "%s/%s/nodes", SPACES_DIR, name);
153  	
154  		d = opendir(path);
155  		if (!d) {
156  			log_debug("%s: opendir failed: %d", path, errno);
157  			return -1;
158  		}
159  	
160  		memset(dir_members, 0, sizeof(dir_members));
161  		dir_members_count = 0;
162  	
163  		/* FIXME: we should probably read the nodeid in each dir instead */
164  	
165  		while ((de = readdir(d))) {
166  			if (de->d_name[0] == '.')
167  				continue;
168  			dir_members[i++] = atoi(de->d_name);
169  			log_debug("dir_member %d", dir_members[i-1]);
170  		}
171  		closedir(d);
172  	
173  		dir_members_count = i;
174  		return 0;
175  	}
176  	
177  	static int id_exists(int id, int count, int *array)
178  	{
179  		int i;
180  		for (i = 0; i < count; i++) {
181  			if (array[i] == id)
182  				return 1;
183  		}
184  		return 0;
185  	}
186  	
187  	static int create_path(const char *path)
188  	{
189  		mode_t old_umask;
190  		int rv;
191  	
192  		old_umask = umask(0022);
193  		rv = mkdir(path, 0777);
194  		if (rv < 0 && errno == EEXIST)
195  			rv = 0;
196  		if (rv < 0)
197  			log_error("%s: mkdir failed: %d", path, errno);
198  		umask(old_umask);
199  		return rv;
200  	}
201  	
202  	int path_exists(const char *path)
203  	{
204  		struct stat buf;
205  	
206  		if (stat(path, &buf) < 0) {
207  			if (errno != ENOENT)
208  				log_error("%s: stat failed: %d", path, errno);
209  			return 0;
210  		}
211  		return 1;
212  	}
213  	
214  	/* The "renew" nodes are those that have left and rejoined since the last
215  	   call to set_members().  We rmdir/mkdir for these nodes so dlm-kernel
216  	   can notice they've left and rejoined. */
217  	
218  	int set_configfs_members(struct lockspace *ls, char *name,
219  				 int new_count, int *new_members,
220  				 int renew_count, int *renew_members)
221  	{
222  		char path[PATH_MAX];
223  		char buf[32];
224  		int i, w, fd, rv, id, old_count, *old_members;
225  		int do_renew;
226  	
227  		/*
228  		 * create lockspace dir if it doesn't exist yet
229  		 */
230  	
231  		memset(path, 0, PATH_MAX);
232  		snprintf(path, PATH_MAX, "%s/%s", SPACES_DIR, name);
233  	
234  		if (!path_exists(path)) {
235  			if (create_path(path))
236  				return -1;
237  		}
238  	
239  		/*
240  		 * remove/add lockspace members
241  		 */
242  	
243  		rv = update_dir_members(name);
244  		if (rv)
245  			return rv;
246  	
247  		old_members = dir_members;
248  		old_count = dir_members_count;
249  	
250  		for (i = 0; i < old_count; i++) {
251  			id = old_members[i];
252  			if (id_exists(id, new_count, new_members))
253  				continue;
254  	
255  			memset(path, 0, PATH_MAX);
256  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d",
257  				 SPACES_DIR, name, id);
258  	
259  			log_debug("set_members rmdir \"%s\"", path);
260  	
261  			rv = rmdir(path);
262  			if (rv) {
263  				log_error("%s: rmdir failed: %d", path, errno);
264  				goto out;
265  			}
266  		}
267  	
268  		/*
269  		 * remove lockspace dir after we've removed all the nodes
270  		 * (when we're shutting down and adding no new nodes)
271  		 */
272  	
273  		if (!new_count) {
274  			memset(path, 0, PATH_MAX);
275  			snprintf(path, PATH_MAX, "%s/%s", SPACES_DIR, name);
276  	
277  			log_debug("set_members lockspace rmdir \"%s\"", path);
278  	
279  			rv = rmdir(path);
280  			if (rv)
281  				log_error("%s: rmdir failed: %d", path, errno);
282  		}
283  	
284  		for (i = 0; i < new_count; i++) {
285  			id = new_members[i];
286  	
287  			do_renew = 0;
288  	
289  			if (id_exists(id, renew_count, renew_members))
290  				do_renew = 1;
291  			else if (id_exists(id, old_count, old_members))
292  				continue;
293  	
294  			if (!is_cluster_member(id))
295  				update_cluster();
296  			/*
297  			 * create node's dir
298  			 */
299  	
300  			memset(path, 0, PATH_MAX);
301  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d",
302  				 SPACES_DIR, name, id);
303  	
304  			if (do_renew) {
305  				log_debug("set_members renew rmdir \"%s\"", path);
306  				rv = rmdir(path);
307  				if (rv) {
308  					log_error("%s: renew rmdir failed: %d",
309  						  path, errno);
310  	
311  					/* don't quit here, there's a case where
312  					 * this can happen, where a node identified
313  					 * for renewal was not really added
314  					 * previously */
315  				}
316  			}
317  	
318  			log_debug("set_members mkdir \"%s\"", path);
319  	
320  			rv = create_path(path);
321  			if (rv)
322  				goto out;
323  	
324  			/*
325  			 * set node's nodeid
326  			 */
327  	
328  			memset(path, 0, PATH_MAX);
329  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d/nodeid",
330  				 SPACES_DIR, name, id);
331  	
332  			rv = fd = open(path, O_WRONLY);
333  			if (rv < 0) {
334  				log_error("%s: open failed: %d", path, errno);
335  				goto out;
336  			}
337  	
338  			memset(buf, 0, 32);
339  			snprintf(buf, 32, "%d", id);
340  	
(10) Event example_assign: Example 3: Assigning: "rv" = return value from "do_write(fd, buf, strlen(buf))".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_checked][example_assign][example_checked][example_assign][example_checked]
341  			rv = do_write(fd, buf, strlen(buf));
(11) Event example_checked: Example 3 (cont.): "rv" has its value checked in "rv < 0".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_assign][example_assign][example_checked][example_assign][example_checked]
342  			if (rv < 0) {
343  				log_error("%s: write failed: %d, %s", path, errno, buf);
344  				close(fd);
345  				goto out;
346  			}
347  			close(fd);
348  	
349  			/*
350  			 * set node's weight
351  			 */
352  	
353  			w = get_weight(ls, id);
354  	
355  			memset(path, 0, PATH_MAX);
356  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d/weight",
357  				 SPACES_DIR, name, id);
358  	
359  			rv = fd = open(path, O_WRONLY);
360  			if (rv < 0) {
361  				log_error("%s: open failed: %d", path, errno);
362  				goto out;
363  			}
364  	
365  			memset(buf, 0, 32);
366  			snprintf(buf, 32, "%d", w);
367  	
368  			rv = do_write(fd, buf, strlen(buf));
369  			if (rv < 0) {
370  				log_error("%s: write failed: %d, %s", path, errno, buf);
371  				close(fd);
372  				goto out;
373  			}
374  			close(fd);
375  		}
376  	
377  		rv = 0;
378  	 out:
379  		return rv;
380  	}
381  	
382  	#if 0
383  	char *str_ip(char *addr)
384  	{
385  		static char ip[256];
386  		struct sockaddr_in *sin = (struct sockaddr_in *) addr;
387  		memset(ip, 0, sizeof(ip));
388  		inet_ntop(AF_INET, &sin->sin_addr, ip, 256);
389  		return ip;
390  	}
391  	#endif
392  	
393  	static char *str_ip(char *addr)
394  	{
395  		static char str_ip_buf[INET6_ADDRSTRLEN];
396  		struct sockaddr_storage *ss = (struct sockaddr_storage *)addr;
397  		struct sockaddr_in *sin = (struct sockaddr_in *)addr;
398  		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
399  		void *saddr;
400  	
401  		if (ss->ss_family == AF_INET6)
402  			saddr = &sin6->sin6_addr;
403  		else
404  			saddr = &sin->sin_addr;
405  	
406  		inet_ntop(ss->ss_family, saddr, str_ip_buf, sizeof(str_ip_buf));
407  		return str_ip_buf;
408  	}
409  	
410  	/* record the nodeids that are currently listed under
411  	   config/dlm/cluster/comms/ so that we can remove all of them */
412  	
413  	static int update_comms_nodes(void)
414  	{
415  		char path[PATH_MAX];
416  		DIR *d;
417  		struct dirent *de;
418  		int i = 0;
419  	
420  		memset(path, 0, PATH_MAX);
421  		snprintf(path, PATH_MAX, COMMS_DIR);
422  	
423  		d = opendir(path);
424  		if (!d) {
425  			log_debug("%s: opendir failed: %d", path, errno);
426  			return -1;
427  		}
428  	
429  		memset(comms_nodes, 0, sizeof(comms_nodes));
430  		comms_nodes_count = 0;
431  	
432  		while ((de = readdir(d))) {
433  			if (de->d_name[0] == '.')
434  				continue;
435  			comms_nodes[i++] = atoi(de->d_name);
436  		}
437  		closedir(d);
438  	
439  		comms_nodes_count = i;
440  		return 0;
441  	}
442  	
443  	/* clear out everything under config/dlm/cluster/comms/ */
444  	
445  	static void clear_configfs_comms(void)
446  	{
447  		char path[PATH_MAX];
448  		int i, rv;
449  	
450  		rv = update_comms_nodes();
451  		if (rv < 0)
452  			return;
453  	
454  		for (i = 0; i < comms_nodes_count; i++) {
455  			memset(path, 0, PATH_MAX);
456  			snprintf(path, PATH_MAX, "%s/%d", COMMS_DIR, comms_nodes[i]);
457  	
458  			log_debug("clear_configfs_nodes rmdir \"%s\"", path);
459  	
460  			rv = rmdir(path);
461  			if (rv)
462  				log_error("%s: rmdir failed: %d", path, errno);
463  		}
464  	}
465  	
466  	static void clear_configfs_space_nodes(char *name)
467  	{
468  		char path[PATH_MAX];
469  		int i, rv;
470  	
471  		rv = update_dir_members(name);
472  		if (rv < 0)
473  			return;
474  	
475  		for (i = 0; i < dir_members_count; i++) {
476  			memset(path, 0, PATH_MAX);
477  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d",
478  				 SPACES_DIR, name, dir_members[i]);
479  	
480  			log_debug("clear_configfs_space_nodes rmdir \"%s\"", path);
481  	
482  			rv = rmdir(path);
483  			if (rv)
484  				log_error("%s: rmdir failed: %d", path, errno);
485  		}
486  	}
487  	
488  	/* clear out everything under config/dlm/cluster/spaces/ */
489  	
490  	static void clear_configfs_spaces(void)
491  	{
492  		char path[PATH_MAX];
493  		DIR *d;
494  		struct dirent *de;
495  		int rv;
496  	
497  		memset(path, 0, PATH_MAX);
498  		snprintf(path, PATH_MAX, "%s", SPACES_DIR);
499  	
500  		d = opendir(path);
501  		if (!d) {
502  			log_debug("%s: opendir failed: %d", path, errno);
503  			return;
504  		}
505  	
506  		while ((de = readdir(d))) {
507  			if (de->d_name[0] == '.')
508  				continue;
509  	
510  			clear_configfs_space_nodes(de->d_name);
511  	
512  			memset(path, 0, PATH_MAX);
513  			snprintf(path, PATH_MAX, "%s/%s", SPACES_DIR, de->d_name);
514  			
515  			log_debug("clear_configfs_spaces rmdir \"%s\"", path);
516  	
517  			rv = rmdir(path);
518  			if (rv)
519  				log_error("%s: rmdir failed: %d", path, errno);
520  		}
521  		closedir(d);
522  	}
523  	
524  	static int add_configfs_base(void)
525  	{
526  		int rv = 0;
527  	
528  		if (!path_exists("/sys/kernel/config")) {
529  			log_error("No /sys/kernel/config, is configfs loaded?");
530  			return -1;
531  		}
532  	
533  		if (!path_exists("/sys/kernel/config/dlm")) {
534  			log_error("No /sys/kernel/config/dlm, is the dlm loaded?");
535  			return -1;
536  		}
537  	
538  		if (!path_exists("/sys/kernel/config/dlm/cluster"))
539  			rv = create_path("/sys/kernel/config/dlm/cluster");
540  	
541  		return rv;
542  	}
543  	
544  	int add_configfs_node(int nodeid, char *addr, int addrlen, int local,
545  			      uint32_t mark)
546  	{
547  		char path[PATH_MAX];
548  		char padded_addr[sizeof(struct sockaddr_storage)];
549  		char buf[32];
550  		int rv, fd;
551  	
552  		log_debug("set_configfs_node %d %s local %d mark %" PRIu32,
553  			  nodeid, str_ip(addr), local, mark);
554  	
555  		/*
556  		 * create comm dir for this node
557  		 */
558  	
559  		memset(path, 0, PATH_MAX);
560  		snprintf(path, PATH_MAX, "%s/%d", COMMS_DIR, nodeid);
561  	
562  		rv = create_path(path);
563  		if (rv)
564  			return -1;
565  	
566  		/*
567  		 * set the nodeid
568  		 */
569  	
570  		memset(path, 0, PATH_MAX);
571  		snprintf(path, PATH_MAX, "%s/%d/nodeid", COMMS_DIR, nodeid);
572  	
573  		fd = open(path, O_WRONLY);
574  		if (fd < 0) {
575  			log_error("%s: open failed: %d", path, errno);
576  			return -1;
577  		}
578  	
579  		memset(buf, 0, sizeof(buf));
580  		snprintf(buf, 32, "%d", nodeid);
581  	
(6) Event example_assign: Example 1: Assigning: "rv" = return value from "do_write(fd, buf, strlen(buf))".
Also see events: [check_return][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked]
582  		rv = do_write(fd, buf, strlen(buf));
(7) Event example_checked: Example 1 (cont.): "rv" has its value checked in "rv < 0".
Also see events: [check_return][example_assign][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked]
583  		if (rv < 0) {
584  			log_error("%s: write failed: %d, %s", path, errno, buf);
585  			close(fd);
586  			return -1;
587  		}
588  		close(fd);
589  	
590  		/*
591  		 * set the address
592  		 */
593  	
594  		memset(padded_addr, 0, sizeof(padded_addr));
595  		memcpy(padded_addr, addr, addrlen);
596  	
597  		memset(path, 0, PATH_MAX);
598  		snprintf(path, PATH_MAX, "%s/%d/addr", COMMS_DIR, nodeid);
599  	
600  		fd = open(path, O_WRONLY);
601  		if (fd < 0) {
602  			log_error("%s: open failed: %d", path, errno);
603  			return -1;
604  		}
605  	
606  		rv = do_write(fd, padded_addr, sizeof(struct sockaddr_storage));
607  		if (rv < 0) {
608  			log_error("%s: write failed: %d %d", path, errno, rv);
609  			close(fd);
610  			return -1;
611  		}
612  		close(fd);
613  	
614  		/*
615  		 * set skb mark for nodeid
616  		 *
617  		 * If open() fails we skip it because kernel doesn't support it.
618  		 * It's not a required confiuration. It will show up in the log.
619  		 */
620  	
621  		memset(path, 0, PATH_MAX);
622  		snprintf(path, PATH_MAX, "%s/%d/mark", COMMS_DIR, nodeid);
623  	
624  		fd = open(path, O_WRONLY);
625  		if (fd < 0) {
626  			log_error("%s: open failed: %d", path, errno);
627  			goto skip_non_required;
628  		}
629  	
630  		memset(buf, 0, sizeof(buf));
631  		snprintf(buf, 32, "%" PRIu32, mark);
632  	
633  		rv = do_write(fd, buf, strlen(buf));
634  		if (rv < 0) {
635  			log_error("%s: write failed: %d, %s", path, errno, buf);
636  			close(fd);
637  			return -1;
638  		}
639  		close(fd);
640  	
641  	skip_non_required:
642  	
643  		/*
644  		 * set local
645  		 */
646  	
647  		if (!local)
648  			goto out;
649  	
650  		memset(path, 0, PATH_MAX);
651  		snprintf(path, PATH_MAX, "%s/%d/local", COMMS_DIR, nodeid);
652  	
653  		fd = open(path, O_WRONLY);
654  		if (fd < 0) {
655  			log_error("%s: open failed: %d", path, errno);
656  			return -1;
657  		}
658  	
659  		rv = do_write(fd, (void *)"1", strlen("1"));
660  		if (rv < 0) {
661  			log_error("%s: write failed: %d", path, errno);
662  			close(fd);
663  			return -1;
664  		}
665  		close(fd);
666  	 out:
667  		return 0;
668  	}
669  	
670  	void del_configfs_node(int nodeid)
671  	{
672  		char path[PATH_MAX];
673  		int rv;
674  	
675  		memset(path, 0, PATH_MAX);
676  		snprintf(path, PATH_MAX, "%s/%d", COMMS_DIR, nodeid);
677  	
678  		log_debug("del_configfs_node rmdir \"%s\"", path);
679  	
680  		rv = rmdir(path);
681  		if (rv)
682  			log_error("%s: rmdir failed: %d", path, errno);
683  	}
684  	
685  	/* num may be 0, str won't be NULL */
686  	
687  	static int set_configfs_cluster(const char *name, char *str, int num)
688  	{
689  		char path[PATH_MAX];
690  		char buf[32];
691  		char *wbuf;
692  		int fd, rv;
693  	
694  		memset(path, 0, PATH_MAX);
695  		snprintf(path, PATH_MAX, "%s/%s", CLUSTER_DIR, name);
696  	
697  		fd = open(path, O_WRONLY);
698  		if (fd < 0) {
699  			log_error("%s: open failed: %d", path, errno);
700  			return fd;
701  		}
702  	
703  		if (str) {
704  			wbuf = str;
705  		} else {
706  			memset(buf, 0, sizeof(buf));
707  			snprintf(buf, 32, "%d", num);
708  			wbuf = buf;
709  		}
710  	
(8) Event example_assign: Example 2: Assigning: "rv" = return value from "do_write(fd, wbuf, strlen(wbuf))".
Also see events: [check_return][example_assign][example_checked][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked]
711  		rv = do_write(fd, wbuf, strlen(wbuf));
(9) Event example_checked: Example 2 (cont.): "rv" has its value checked in "rv < 0".
Also see events: [check_return][example_assign][example_checked][example_assign][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked]
712  		if (rv < 0) {
713  			log_error("%s: write failed: %d", path, errno);
714  			return rv;
715  		}
716  		close(fd);
717  		log_debug("set %s %s", name, wbuf);
718  		return 0;
719  	}
720  	
721  	int set_configfs_opt(const char *name, char *str, int num)
722  	{
723  		return set_configfs_cluster(name, str, num);
724  	}
725  	
726  	#define NET_RMEM_DEFAULT 4194304
727  	#define NET_RMEM_MAX 4194304
728  	
729  	static int set_proc_rmem(void)
730  	{
731  		char path[PATH_MAX];
732  		char buf[32];
733  		int fd, rv;
734  	
735  		memset(path, 0, PATH_MAX);
736  		snprintf(path, PATH_MAX, "/proc/sys/net/core/rmem_default");
737  	
738  		fd = open(path, O_RDWR);
739  		if (fd < 0) {
740  			log_error("%s: open failed: %d", path, errno);
741  			return fd;
742  		}
743  	
744  		memset(buf, 0, sizeof(buf));
745  	
746  		rv = read(fd, buf, sizeof(buf));
747  		if (rv < 0) {
748  			log_error("%s: read failed: %d", path, errno);
749  			close(fd);
750  			return rv;
751  		}
752  	
753  		if (atoi(buf) >= NET_RMEM_DEFAULT) {
754  			close(fd);
755  			goto next;
756  		}
757  	
758  		memset(buf, 0, sizeof(buf));
759  		snprintf(buf, 32, "%d", NET_RMEM_DEFAULT);
760  	
(12) Event example_assign: Example 4: Assigning: "rv" = return value from "do_write(fd, buf, strlen(buf))".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_checked][example_assign][example_checked]
761  		rv = do_write(fd, buf, strlen(buf));
(13) Event example_checked: Example 4 (cont.): "rv" has its value checked in "rv < 0".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_assign][example_checked]
762  		if (rv < 0) {
763  			log_error("%s: write failed: %d", path, errno);
764  			close(fd);
765  			return rv;
766  		}
767  	
768  		close(fd);
769  		log_debug("set %s %s", path, buf);
770  	
771  	 next:
772  		memset(path, 0, PATH_MAX);
773  		snprintf(path, PATH_MAX, "/proc/sys/net/core/rmem_max");
774  	
775  		fd = open(path, O_RDWR);
776  		if (fd < 0) {
777  			log_error("%s: open failed: %d", path, errno);
778  			return fd;
779  		}
780  	
781  		memset(buf, 0, sizeof(buf));
782  	
783  		rv = read(fd, buf, sizeof(buf));
784  		if (rv < 0) {
785  			log_error("%s: read failed: %d", path, errno);
786  			close(fd);
787  			return rv;
788  		}
789  	
790  		if (atoi(buf) >= NET_RMEM_MAX) {
791  			close(fd);
792  			goto out;
793  		}
794  	
795  		memset(buf, 0, sizeof(buf));
796  		snprintf(buf, 32, "%d", NET_RMEM_MAX);
797  	
(14) Event example_assign: Example 5: Assigning: "rv" = return value from "do_write(fd, buf, strlen(buf))".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_checked]
798  		rv = do_write(fd, buf, strlen(buf));
(15) Event example_checked: Example 5 (cont.): "rv" has its value checked in "rv < 0".
Also see events: [check_return][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign][example_checked][example_assign]
799  		if (rv < 0) {
800  			log_error("%s: write failed: %d", path, errno);
801  			close(fd);
802  			return rv;
803  		}
804  	
805  		close(fd);
806  		log_debug("set %s %s", path, buf);
807  	 out:
808  		return 0;
809  	}
810  	
811  	void clear_configfs(void)
812  	{
813  		clear_configfs_comms();
814  		clear_configfs_spaces();
815  		rmdir("/sys/kernel/config/dlm/cluster");
816  	}
817  	
818  	int setup_configfs_options(void)
819  	{
820  		char *proto_name;
821  		int rv, proto_num;
822  	
823  		clear_configfs();
824  	
825  		rv = add_configfs_base();
826  		if (rv < 0)
827  			return rv;
828  	
829  		/* the kernel has its own defaults for these values which we
830  		   don't want to change unless these have been set explicitly
831  		   on cli or config file */
832  	
833  		if (dlm_options[log_debug_ind].cli_set ||
834  		    dlm_options[log_debug_ind].file_set)
835  			set_configfs_cluster("log_debug", NULL, opt(log_debug_ind));
836  	
837  		if (dlm_options[port_ind].cli_set ||
838  		    dlm_options[port_ind].file_set)
839  			set_configfs_cluster("tcp_port", NULL, optu(port_ind));
840  	
841  		set_configfs_cluster("mark", NULL, optu(mark_ind));
842  	
843  		proto_name = opts(protocol_ind);
844  		proto_num = 0; /* default is tcp */
845  	
846  		if (!strcasecmp(proto_name, "detect") || !strcmp(proto_name, "2")) {
847  			log_error("'detect' mode is not supported anymore, will use default mode (TCP).");
848  			log_error("see dlm_conf(5) for details.");
849  		}
850  	
851  		if (!strcasecmp(proto_name, "tcp") || !strcmp(proto_name, "0"))
852  			proto_num = PROTO_TCP;
853  	
854  		else if (!strcasecmp(proto_name, "sctp") || !strcmp(proto_name, "1"))
855  			proto_num = PROTO_SCTP;
856  	
857  		if (proto_num == PROTO_TCP || proto_num == PROTO_SCTP)
858  			set_configfs_cluster("protocol", NULL, proto_num);
859  	
860  		if (proto_num == PROTO_SCTP)
861  			set_proc_rmem();
862  	
863  		/* 
864  		 * set clustername, recover_callbacks
865  		 *
866  		 * we can't set our nodeid here, though, it must be set *after*
867  		 * setup_monitor, because the kernel assumes if the nodeid
868  		 * is set, but monitor is not opened, that it's an old,
869  		 * pre-monitor version of dlm_controld and allows it to
870  		 * go ahead without the monitor being open
871  		 */
872  	
873  		if (opt(enable_fscontrol_ind)) {
874  			/* deprecated */
875  			set_configfs_cluster("recover_callbacks", NULL, 0);
876  		} else {
877  			set_configfs_cluster("recover_callbacks", NULL, 1);
878  	
879  			detect_cluster_name();
880  	
881  			if (cluster_name[0]) {
882  				set_configfs_cluster("cluster_name", cluster_name, 0);
883  			} else {
884  				log_error("no cluster name");
885  				return -1;
886  			}
887  		}
888  		return 0;
889  	}
890  	
891  	/* see comment above re why setup_monitor needs to come between
892  	   setup_configfs_options and setup_configfs_members */
893  	
894  	int setup_configfs_members(void)
895  	{
896  		/* add configfs entries for existing nodes */
897  		update_cluster();
898  		return 0;
899  	}
900  	
901  	static void find_minors(void)
902  	{
903  		FILE *fl;
904  		char name[256];
905  		uint32_t number;
906  		int found = 0;
907  		int c;
908  	
909  		control_minor = 0;
910  		monitor_minor = 0;
911  		plock_minor = 0;
912  	
913  		if (!(fl = fopen("/proc/misc", "r"))) {
914  			log_error("/proc/misc fopen failed: %s", strerror(errno));
915  			return;
916  		}
917  	
918  		while (!feof(fl)) {
919  			if (fscanf(fl, "%d %255s\n", &number, &name[0]) == 2) {
920  	
921  				if (!strcmp(name, "dlm-control")) {
922  					control_minor = number;
923  					found++;
924  				} else if (!strcmp(name, "dlm-monitor")) {
925  					monitor_minor = number;
926  					found++;
927  				} else if (!strcmp(name, "dlm_plock")) {
928  					plock_minor = number;
929  					found++;
930  				}
931  	
932  			} else do {
933  				c = fgetc(fl);
934  			} while (c != EOF && c != '\n');
935  	
936  			if (found == 3)
937  				break;
938  		}
939  		fclose(fl);
940  	
941  		if (!found)
942  			log_error("Is dlm missing from kernel? No misc devices found.");
943  	}
944  	
945  	static int find_udev_device(const char *path, uint32_t minor)
946  	{
947  		struct stat st;
948  		int i;
949  	
950  		for (i = 0; i < 10; i++) {
951  			if (stat(path, &st) == 0 && minor(st.st_rdev) == minor)
952  				return 0;
953  			sleep(1);
954  		}
955  	
956  		log_error("cannot find device %s with minor %d", path, minor);
957  		return -1;
958  	}
959  	
960  	int setup_misc_devices(void)
961  	{
962  		int rv;
963  	
964  		find_minors();
965  	
966  		if (control_minor) {
967  			rv = find_udev_device("/dev/misc/dlm-control", control_minor);
968  			if (rv < 0)
969  				return rv;
970  			log_debug("found /dev/misc/dlm-control minor %u",
971  				  control_minor);
972  		}
973  	
974  		if (monitor_minor) {
975  			rv = find_udev_device("/dev/misc/dlm-monitor", monitor_minor);
976  			if (rv < 0)
977  				return rv;
978  			log_debug("found /dev/misc/dlm-monitor minor %u",
979  				  monitor_minor);
980  		}
981  	
982  		if (plock_minor) {
983  			rv = find_udev_device("/dev/misc/dlm_plock", plock_minor);
984  			if (rv < 0)
985  				return rv;
986  			log_debug("found /dev/misc/dlm_plock minor %u",
987  				  plock_minor);
988  		}
989  	
990  		return 0;
991  	}
992  	
993