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
234 rv = do_write(fd, buf, strlen(buf));
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
374 rv = do_write(fd, buf, strlen(buf));
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
615 rv = do_write(fd, buf, strlen(buf));
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
744 rv = do_write(fd, wbuf, strlen(wbuf));
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
794 rv = do_write(fd, buf, strlen(buf));
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