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
341 rv = do_write(fd, buf, strlen(buf));
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
582 rv = do_write(fd, buf, strlen(buf));
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
|
(1) Event open_fn: |
Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] |
|
(2) Event var_assign: |
Assigning: "fd" = handle returned from "open(path, 1)". |
| Also see events: |
[noescape][leaked_handle] |
697 fd = open(path, O_WRONLY);
|
(3) Event cond_false: |
Condition "fd < 0", taking false branch. |
698 if (fd < 0) {
699 log_error("%s: open failed: %d", path, errno);
700 return fd;
|
(4) Event if_end: |
End of if statement. |
701 }
702
|
(5) Event cond_true: |
Condition "str", taking true branch. |
703 if (str) {
704 wbuf = str;
|
(6) Event if_fallthrough: |
Falling through to end of if statement. |
705 } else {
706 memset(buf, 0, sizeof(buf));
707 snprintf(buf, 32, "%d", num);
708 wbuf = buf;
|
(7) Event if_end: |
End of if statement. |
709 }
710
711 rv = do_write(fd, wbuf, strlen(wbuf));
|
(9) Event cond_true: |
Condition "rv < 0", taking true branch. |
712 if (rv < 0) {
713 log_error("%s: write failed: %d", path, errno);
|
(10) Event leaked_handle: |
Handle variable "fd" going out of scope leaks the handle. |
| Also see events: |
[open_fn][var_assign][noescape] |
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
761 rv = do_write(fd, buf, strlen(buf));
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
798 rv = do_write(fd, buf, strlen(buf));
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