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  	int set_configfs_member_release_recover(struct lockspace *ls, int id,
215  						uint32_t release_recover)
216  	{
217  		char path[PATH_MAX];
218  		char buf[32];
219  		int fd, rv;
220  	
221  		memset(path, 0, PATH_MAX);
222  		snprintf(path, PATH_MAX, "%s/%s/nodes/%d/release_recover",
223  			 SPACES_DIR, ls->name, id);
224  	
225  		rv = fd = open(path, O_WRONLY);
226  		if (rv < 0) {
227  			log_error("%s: open failed: %d", path, errno);
228  			goto out;
229  		}
230  	
231  		memset(buf, 0, 32);
232  		snprintf(buf, 32, "%u", release_recover);
233  	
(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]
234  		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]
235  		if (rv < 0) {
236  			log_error("%s: write failed: %d, %s", path, errno, buf);
237  			close(fd);
238  			goto out;
239  		}
240  		close(fd);
241  		rv = 0;
242  	
243  	out:
244  		return rv;
245  	}
246  	
247  	/* The "renew" nodes are those that have left and rejoined since the last
248  	   call to set_members().  We rmdir/mkdir for these nodes so dlm-kernel
249  	   can notice they've left and rejoined. */
250  	
251  	int set_configfs_members(struct lockspace *ls, char *name,
252  				 int new_count, int *new_members,
253  				 int renew_count, int *renew_members)
254  	{
255  		char path[PATH_MAX];
256  		char buf[32];
257  		int i, w, fd, rv, id, old_count, *old_members;
258  		int do_renew;
259  	
260  		/*
261  		 * create lockspace dir if it doesn't exist yet
262  		 */
263  	
264  		memset(path, 0, PATH_MAX);
265  		snprintf(path, PATH_MAX, "%s/%s", SPACES_DIR, name);
266  	
267  		if (!path_exists(path)) {
268  			if (create_path(path))
269  				return -1;
270  		}
271  	
272  		/*
273  		 * remove/add lockspace members
274  		 */
275  	
276  		rv = update_dir_members(name);
277  		if (rv)
278  			return rv;
279  	
280  		old_members = dir_members;
281  		old_count = dir_members_count;
282  	
283  		for (i = 0; i < old_count; i++) {
284  			id = old_members[i];
285  			if (id_exists(id, new_count, new_members))
286  				continue;
287  	
288  			memset(path, 0, PATH_MAX);
289  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d",
290  				 SPACES_DIR, name, id);
291  	
292  			log_debug("set_members rmdir \"%s\"", path);
293  	
294  			rv = rmdir(path);
295  			if (rv) {
296  				log_error("%s: rmdir failed: %d", path, errno);
297  				goto out;
298  			}
299  		}
300  	
301  		/*
302  		 * remove lockspace dir after we've removed all the nodes
303  		 * (when we're shutting down and adding no new nodes)
304  		 */
305  	
306  		if (!new_count) {
307  			memset(path, 0, PATH_MAX);
308  			snprintf(path, PATH_MAX, "%s/%s", SPACES_DIR, name);
309  	
310  			log_debug("set_members lockspace rmdir \"%s\"", path);
311  	
312  			rv = rmdir(path);
313  			if (rv)
314  				log_error("%s: rmdir failed: %d", path, errno);
315  		}
316  	
317  		for (i = 0; i < new_count; i++) {
318  			id = new_members[i];
319  	
320  			do_renew = 0;
321  	
322  			if (id_exists(id, renew_count, renew_members))
323  				do_renew = 1;
324  			else if (id_exists(id, old_count, old_members))
325  				continue;
326  	
327  			if (!is_cluster_member(id))
328  				update_cluster();
329  			/*
330  			 * create node's dir
331  			 */
332  	
333  			memset(path, 0, PATH_MAX);
334  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d",
335  				 SPACES_DIR, name, id);
336  	
337  			if (do_renew) {
338  				log_debug("set_members renew rmdir \"%s\"", path);
339  				rv = rmdir(path);
340  				if (rv) {
341  					log_error("%s: renew rmdir failed: %d",
342  						  path, errno);
343  	
344  					/* don't quit here, there's a case where
345  					 * this can happen, where a node identified
346  					 * for renewal was not really added
347  					 * previously */
348  				}
349  			}
350  	
351  			log_debug("set_members mkdir \"%s\"", path);
352  	
353  			rv = create_path(path);
354  			if (rv)
355  				goto out;
356  	
357  			/*
358  			 * set node's nodeid
359  			 */
360  	
361  			memset(path, 0, PATH_MAX);
362  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d/nodeid",
363  				 SPACES_DIR, name, id);
364  	
365  			rv = fd = open(path, O_WRONLY);
366  			if (rv < 0) {
367  				log_error("%s: open failed: %d", path, errno);
368  				goto out;
369  			}
370  	
371  			memset(buf, 0, 32);
372  			snprintf(buf, 32, "%d", id);
373  	
(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]
374  			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]
375  			if (rv < 0) {
376  				log_error("%s: write failed: %d, %s", path, errno, buf);
377  				close(fd);
378  				goto out;
379  			}
380  			close(fd);
381  	
382  			/*
383  			 * set node's weight
384  			 */
385  	
386  			w = get_weight(ls, id);
387  	
388  			memset(path, 0, PATH_MAX);
389  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d/weight",
390  				 SPACES_DIR, name, id);
391  	
392  			rv = fd = open(path, O_WRONLY);
393  			if (rv < 0) {
394  				log_error("%s: open failed: %d", path, errno);
395  				goto out;
396  			}
397  	
398  			memset(buf, 0, 32);
399  			snprintf(buf, 32, "%d", w);
400  	
401  			rv = do_write(fd, buf, strlen(buf));
402  			if (rv < 0) {
403  				log_error("%s: write failed: %d, %s", path, errno, buf);
404  				close(fd);
405  				goto out;
406  			}
407  			close(fd);
408  		}
409  	
410  		rv = 0;
411  	 out:
412  		return rv;
413  	}
414  	
415  	#if 0
416  	char *str_ip(char *addr)
417  	{
418  		static char ip[256];
419  		struct sockaddr_in *sin = (struct sockaddr_in *) addr;
420  		memset(ip, 0, sizeof(ip));
421  		inet_ntop(AF_INET, &sin->sin_addr, ip, 256);
422  		return ip;
423  	}
424  	#endif
425  	
426  	static char *str_ip(char *addr)
427  	{
428  		static char str_ip_buf[INET6_ADDRSTRLEN];
429  		struct sockaddr_storage *ss = (struct sockaddr_storage *)addr;
430  		struct sockaddr_in *sin = (struct sockaddr_in *)addr;
431  		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
432  		void *saddr;
433  	
434  		if (ss->ss_family == AF_INET6)
435  			saddr = &sin6->sin6_addr;
436  		else
437  			saddr = &sin->sin_addr;
438  	
439  		inet_ntop(ss->ss_family, saddr, str_ip_buf, sizeof(str_ip_buf));
440  		return str_ip_buf;
441  	}
442  	
443  	/* record the nodeids that are currently listed under
444  	   config/dlm/cluster/comms/ so that we can remove all of them */
445  	
446  	static int update_comms_nodes(void)
447  	{
448  		char path[PATH_MAX];
449  		DIR *d;
450  		struct dirent *de;
451  		int i = 0;
452  	
453  		memset(path, 0, PATH_MAX);
454  		snprintf(path, PATH_MAX, COMMS_DIR);
455  	
456  		d = opendir(path);
457  		if (!d) {
458  			log_debug("%s: opendir failed: %d", path, errno);
459  			return -1;
460  		}
461  	
462  		memset(comms_nodes, 0, sizeof(comms_nodes));
463  		comms_nodes_count = 0;
464  	
465  		while ((de = readdir(d))) {
466  			if (de->d_name[0] == '.')
467  				continue;
468  			comms_nodes[i++] = atoi(de->d_name);
469  		}
470  		closedir(d);
471  	
472  		comms_nodes_count = i;
473  		return 0;
474  	}
475  	
476  	/* clear out everything under config/dlm/cluster/comms/ */
477  	
478  	static void clear_configfs_comms(void)
479  	{
480  		char path[PATH_MAX];
481  		int i, rv;
482  	
483  		rv = update_comms_nodes();
484  		if (rv < 0)
485  			return;
486  	
487  		for (i = 0; i < comms_nodes_count; i++) {
488  			memset(path, 0, PATH_MAX);
489  			snprintf(path, PATH_MAX, "%s/%d", COMMS_DIR, comms_nodes[i]);
490  	
491  			log_debug("clear_configfs_nodes rmdir \"%s\"", path);
492  	
493  			rv = rmdir(path);
494  			if (rv)
495  				log_error("%s: rmdir failed: %d", path, errno);
496  		}
497  	}
498  	
499  	static void clear_configfs_space_nodes(char *name)
500  	{
501  		char path[PATH_MAX];
502  		int i, rv;
503  	
504  		rv = update_dir_members(name);
505  		if (rv < 0)
506  			return;
507  	
508  		for (i = 0; i < dir_members_count; i++) {
509  			memset(path, 0, PATH_MAX);
510  			snprintf(path, PATH_MAX, "%s/%s/nodes/%d",
511  				 SPACES_DIR, name, dir_members[i]);
512  	
513  			log_debug("clear_configfs_space_nodes rmdir \"%s\"", path);
514  	
515  			rv = rmdir(path);
516  			if (rv)
517  				log_error("%s: rmdir failed: %d", path, errno);
518  		}
519  	}
520  	
521  	/* clear out everything under config/dlm/cluster/spaces/ */
522  	
523  	static void clear_configfs_spaces(void)
524  	{
525  		char path[PATH_MAX];
526  		DIR *d;
527  		struct dirent *de;
528  		int rv;
529  	
530  		memset(path, 0, PATH_MAX);
531  		snprintf(path, PATH_MAX, "%s", SPACES_DIR);
532  	
533  		d = opendir(path);
534  		if (!d) {
535  			log_debug("%s: opendir failed: %d", path, errno);
536  			return;
537  		}
538  	
539  		while ((de = readdir(d))) {
540  			if (de->d_name[0] == '.')
541  				continue;
542  	
543  			clear_configfs_space_nodes(de->d_name);
544  	
545  			memset(path, 0, PATH_MAX);
546  			snprintf(path, PATH_MAX, "%s/%s", SPACES_DIR, de->d_name);
547  			
548  			log_debug("clear_configfs_spaces rmdir \"%s\"", path);
549  	
550  			rv = rmdir(path);
551  			if (rv)
552  				log_error("%s: rmdir failed: %d", path, errno);
553  		}
554  		closedir(d);
555  	}
556  	
557  	static int add_configfs_base(void)
558  	{
559  		int rv = 0;
560  	
561  		if (!path_exists("/sys/kernel/config")) {
562  			log_error("No /sys/kernel/config, is configfs loaded?");
563  			return -1;
564  		}
565  	
566  		if (!path_exists("/sys/kernel/config/dlm")) {
567  			log_error("No /sys/kernel/config/dlm, is the dlm loaded?");
568  			return -1;
569  		}
570  	
571  		if (!path_exists("/sys/kernel/config/dlm/cluster"))
572  			rv = create_path("/sys/kernel/config/dlm/cluster");
573  	
574  		return rv;
575  	}
576  	
577  	int add_configfs_node(int nodeid, char *addr, int addrlen, int local,
578  			      uint32_t mark)
579  	{
580  		char path[PATH_MAX];
581  		char padded_addr[sizeof(struct sockaddr_storage)];
582  		char buf[32];
583  		int rv, fd;
584  	
585  		log_debug("set_configfs_node %d %s local %d mark %" PRIu32,
586  			  nodeid, str_ip(addr), local, mark);
587  	
588  		/*
589  		 * create comm dir for this node
590  		 */
591  	
592  		memset(path, 0, PATH_MAX);
593  		snprintf(path, PATH_MAX, "%s/%d", COMMS_DIR, nodeid);
594  	
595  		rv = create_path(path);
596  		if (rv)
597  			return -1;
598  	
599  		/*
600  		 * set the nodeid
601  		 */
602  	
603  		memset(path, 0, PATH_MAX);
604  		snprintf(path, PATH_MAX, "%s/%d/nodeid", COMMS_DIR, nodeid);
605  	
606  		fd = open(path, O_WRONLY);
607  		if (fd < 0) {
608  			log_error("%s: open failed: %d", path, errno);
609  			return -1;
610  		}
611  	
612  		memset(buf, 0, sizeof(buf));
613  		snprintf(buf, 32, "%d", nodeid);
614  	
(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]
615  		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]
616  		if (rv < 0) {
617  			log_error("%s: write failed: %d, %s", path, errno, buf);
618  			close(fd);
619  			return -1;
620  		}
621  		close(fd);
622  	
623  		/*
624  		 * set the address
625  		 */
626  	
627  		memset(padded_addr, 0, sizeof(padded_addr));
628  		memcpy(padded_addr, addr, addrlen);
629  	
630  		memset(path, 0, PATH_MAX);
631  		snprintf(path, PATH_MAX, "%s/%d/addr", COMMS_DIR, nodeid);
632  	
633  		fd = open(path, O_WRONLY);
634  		if (fd < 0) {
635  			log_error("%s: open failed: %d", path, errno);
636  			return -1;
637  		}
638  	
639  		rv = do_write(fd, padded_addr, sizeof(struct sockaddr_storage));
640  		if (rv < 0) {
641  			log_error("%s: write failed: %d %d", path, errno, rv);
642  			close(fd);
643  			return -1;
644  		}
645  		close(fd);
646  	
647  		/*
648  		 * set skb mark for nodeid
649  		 *
650  		 * If open() fails we skip it because kernel doesn't support it.
651  		 * It's not a required confiuration. It will show up in the log.
652  		 */
653  	
654  		memset(path, 0, PATH_MAX);
655  		snprintf(path, PATH_MAX, "%s/%d/mark", COMMS_DIR, nodeid);
656  	
657  		fd = open(path, O_WRONLY);
658  		if (fd < 0) {
659  			log_error("%s: open failed: %d", path, errno);
660  			goto skip_non_required;
661  		}
662  	
663  		memset(buf, 0, sizeof(buf));
664  		snprintf(buf, 32, "%" PRIu32, mark);
665  	
666  		rv = do_write(fd, buf, strlen(buf));
667  		if (rv < 0) {
668  			log_error("%s: write failed: %d, %s", path, errno, buf);
669  			close(fd);
670  			return -1;
671  		}
672  		close(fd);
673  	
674  	skip_non_required:
675  	
676  		/*
677  		 * set local
678  		 */
679  	
680  		if (!local)
681  			goto out;
682  	
683  		memset(path, 0, PATH_MAX);
684  		snprintf(path, PATH_MAX, "%s/%d/local", COMMS_DIR, nodeid);
685  	
686  		fd = open(path, O_WRONLY);
687  		if (fd < 0) {
688  			log_error("%s: open failed: %d", path, errno);
689  			return -1;
690  		}
691  	
692  		rv = do_write(fd, (void *)"1", strlen("1"));
693  		if (rv < 0) {
694  			log_error("%s: write failed: %d", path, errno);
695  			close(fd);
696  			return -1;
697  		}
698  		close(fd);
699  	 out:
700  		return 0;
701  	}
702  	
703  	void del_configfs_node(int nodeid)
704  	{
705  		char path[PATH_MAX];
706  		int rv;
707  	
708  		memset(path, 0, PATH_MAX);
709  		snprintf(path, PATH_MAX, "%s/%d", COMMS_DIR, nodeid);
710  	
711  		log_debug("del_configfs_node rmdir \"%s\"", path);
712  	
713  		rv = rmdir(path);
714  		if (rv)
715  			log_error("%s: rmdir failed: %d", path, errno);
716  	}
717  	
718  	/* num may be 0, str won't be NULL */
719  	
720  	static int set_configfs_cluster(const char *name, char *str, int num)
721  	{
722  		char path[PATH_MAX];
723  		char buf[32];
724  		char *wbuf;
725  		int fd, rv;
726  	
727  		memset(path, 0, PATH_MAX);
728  		snprintf(path, PATH_MAX, "%s/%s", CLUSTER_DIR, name);
729  	
730  		fd = open(path, O_WRONLY);
731  		if (fd < 0) {
732  			log_error("%s: open failed: %d", path, errno);
733  			return fd;
734  		}
735  	
736  		if (str) {
737  			wbuf = str;
738  		} else {
739  			memset(buf, 0, sizeof(buf));
740  			snprintf(buf, 32, "%d", num);
741  			wbuf = buf;
742  		}
743  	
(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]
744  		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]
745  		if (rv < 0) {
746  			log_error("%s: write failed: %d", path, errno);
747  			return rv;
748  		}
749  		close(fd);
750  		log_debug("set %s %s", name, wbuf);
751  		return 0;
752  	}
753  	
754  	int set_configfs_opt(const char *name, char *str, int num)
755  	{
756  		return set_configfs_cluster(name, str, num);
757  	}
758  	
759  	#define NET_RMEM_DEFAULT 4194304
760  	#define NET_RMEM_MAX 4194304
761  	
762  	static int set_proc_rmem(void)
763  	{
764  		char path[PATH_MAX];
765  		char buf[32];
766  		int fd, rv;
767  	
768  		memset(path, 0, PATH_MAX);
769  		snprintf(path, PATH_MAX, "/proc/sys/net/core/rmem_default");
770  	
771  		fd = open(path, O_RDWR);
772  		if (fd < 0) {
773  			log_error("%s: open failed: %d", path, errno);
774  			return fd;
775  		}
776  	
777  		memset(buf, 0, sizeof(buf));
778  	
779  		rv = read(fd, buf, sizeof(buf));
780  		if (rv < 0) {
781  			log_error("%s: read failed: %d", path, errno);
782  			close(fd);
783  			return rv;
784  		}
785  	
786  		if (atoi(buf) >= NET_RMEM_DEFAULT) {
787  			close(fd);
788  			goto next;
789  		}
790  	
791  		memset(buf, 0, sizeof(buf));
792  		snprintf(buf, 32, "%d", NET_RMEM_DEFAULT);
793  	
(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]
794  		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]
795  		if (rv < 0) {
796  			log_error("%s: write failed: %d", path, errno);
797  			close(fd);
798  			return rv;
799  		}
800  	
801  		close(fd);
802  		log_debug("set %s %s", path, buf);
803  	
804  	 next:
805  		memset(path, 0, PATH_MAX);
806  		snprintf(path, PATH_MAX, "/proc/sys/net/core/rmem_max");
807  	
808  		fd = open(path, O_RDWR);
809  		if (fd < 0) {
810  			log_error("%s: open failed: %d", path, errno);
811  			return fd;
812  		}
813  	
814  		memset(buf, 0, sizeof(buf));
815  	
816  		rv = read(fd, buf, sizeof(buf));
817  		if (rv < 0) {
818  			log_error("%s: read failed: %d", path, errno);
819  			close(fd);
820  			return rv;
821  		}
822  	
823  		if (atoi(buf) >= NET_RMEM_MAX) {
824  			close(fd);
825  			goto out;
826  		}
827  	
828  		memset(buf, 0, sizeof(buf));
829  		snprintf(buf, 32, "%d", NET_RMEM_MAX);
830  	
831  		rv = do_write(fd, buf, strlen(buf));
832  		if (rv < 0) {
833  			log_error("%s: write failed: %d", path, errno);
834  			close(fd);
835  			return rv;
836  		}
837  	
838  		close(fd);
839  		log_debug("set %s %s", path, buf);
840  	 out:
841  		return 0;
842  	}
843  	
844  	void clear_configfs(void)
845  	{
846  		clear_configfs_comms();
847  		clear_configfs_spaces();
848  		rmdir("/sys/kernel/config/dlm/cluster");
849  	}
850  	
851  	int setup_configfs_options(void)
852  	{
853  		char *proto_name;
854  		int rv, proto_num;
855  	
856  		clear_configfs();
857  	
858  		rv = add_configfs_base();
859  		if (rv < 0)
860  			return rv;
861  	
862  		/* the kernel has its own defaults for these values which we
863  		   don't want to change unless these have been set explicitly
864  		   on cli or config file */
865  	
866  		if (dlm_options[log_debug_ind].cli_set ||
867  		    dlm_options[log_debug_ind].file_set)
868  			set_configfs_cluster("log_debug", NULL, opt(log_debug_ind));
869  	
870  		if (dlm_options[port_ind].cli_set ||
871  		    dlm_options[port_ind].file_set)
872  			set_configfs_cluster("tcp_port", NULL, optu(port_ind));
873  	
874  		set_configfs_cluster("mark", NULL, optu(mark_ind));
875  	
876  		proto_name = opts(protocol_ind);
877  		proto_num = 0; /* default is tcp */
878  	
879  		if (!strcasecmp(proto_name, "detect") || !strcmp(proto_name, "2")) {
880  			log_error("'detect' mode is not supported anymore, will use default mode (TCP).");
881  			log_error("see dlm_conf(5) for details.");
882  		}
883  	
884  		if (!strcasecmp(proto_name, "tcp") || !strcmp(proto_name, "0"))
885  			proto_num = PROTO_TCP;
886  	
887  		else if (!strcasecmp(proto_name, "sctp") || !strcmp(proto_name, "1"))
888  			proto_num = PROTO_SCTP;
889  	
890  		if (proto_num == PROTO_TCP || proto_num == PROTO_SCTP)
891  			set_configfs_cluster("protocol", NULL, proto_num);
892  	
893  		if (proto_num == PROTO_SCTP)
894  			set_proc_rmem();
895  	
896  		/* 
897  		 * set clustername, recover_callbacks
898  		 *
899  		 * we can't set our nodeid here, though, it must be set *after*
900  		 * setup_monitor, because the kernel assumes if the nodeid
901  		 * is set, but monitor is not opened, that it's an old,
902  		 * pre-monitor version of dlm_controld and allows it to
903  		 * go ahead without the monitor being open
904  		 */
905  	
906  		if (opt(enable_fscontrol_ind)) {
907  			/* deprecated */
908  			set_configfs_cluster("recover_callbacks", NULL, 0);
909  		} else {
910  			set_configfs_cluster("recover_callbacks", NULL, 1);
911  	
912  			detect_cluster_name();
913  	
914  			if (cluster_name[0]) {
915  				set_configfs_cluster("cluster_name", cluster_name, 0);
916  			} else {
917  				log_error("no cluster name");
918  				return -1;
919  			}
920  		}
921  		return 0;
922  	}
923  	
924  	/* see comment above re why setup_monitor needs to come between
925  	   setup_configfs_options and setup_configfs_members */
926  	
927  	int setup_configfs_members(void)
928  	{
929  		/* add configfs entries for existing nodes */
930  		update_cluster();
931  		return 0;
932  	}
933  	
934  	static void find_minors(void)
935  	{
936  		FILE *fl;
937  		char name[256];
938  		uint32_t number;
939  		int found = 0;
940  		int c;
941  	
942  		control_minor = 0;
943  		monitor_minor = 0;
944  		plock_minor = 0;
945  	
946  		if (!(fl = fopen("/proc/misc", "r"))) {
947  			log_error("/proc/misc fopen failed: %s", strerror(errno));
948  			return;
949  		}
950  	
951  		while (!feof(fl)) {
952  			if (fscanf(fl, "%d %255s\n", &number, &name[0]) == 2) {
953  	
954  				if (!strcmp(name, "dlm-control")) {
955  					control_minor = number;
956  					found++;
957  				} else if (!strcmp(name, "dlm-monitor")) {
958  					monitor_minor = number;
959  					found++;
960  				} else if (!strcmp(name, "dlm_plock")) {
961  					plock_minor = number;
962  					found++;
963  				}
964  	
965  			} else do {
966  				c = fgetc(fl);
967  			} while (c != EOF && c != '\n');
968  	
969  			if (found == 3)
970  				break;
971  		}
972  		fclose(fl);
973  	
974  		if (!found)
975  			log_error("Is dlm missing from kernel? No misc devices found.");
976  	}
977  	
978  	static int find_udev_device(const char *path, uint32_t minor)
979  	{
980  		struct stat st;
981  		int i;
982  	
983  		for (i = 0; i < 10; i++) {
984  			if (stat(path, &st) == 0 && minor(st.st_rdev) == minor)
985  				return 0;
986  			sleep(1);
987  		}
988  	
989  		log_error("cannot find device %s with minor %d", path, minor);
990  		return -1;
991  	}
992  	
993  	int setup_misc_devices(void)
994  	{
995  		int rv;
996  	
997  		find_minors();
998  	
999  		if (control_minor) {
1000 			rv = find_udev_device("/dev/misc/dlm-control", control_minor);
1001 			if (rv < 0)
1002 				return rv;
1003 			log_debug("found /dev/misc/dlm-control minor %u",
1004 				  control_minor);
1005 		}
1006 	
1007 		if (monitor_minor) {
1008 			rv = find_udev_device("/dev/misc/dlm-monitor", monitor_minor);
1009 			if (rv < 0)
1010 				return rv;
1011 			log_debug("found /dev/misc/dlm-monitor minor %u",
1012 				  monitor_minor);
1013 		}
1014 	
1015 		if (plock_minor) {
1016 			rv = find_udev_device("/dev/misc/dlm_plock", plock_minor);
1017 			if (rv < 0)
1018 				return rv;
1019 			log_debug("found /dev/misc/dlm_plock minor %u",
1020 				  plock_minor);
1021 		}
1022 	
1023 		return 0;
1024 	}
1025 	
1026