2 Copyright (C) 2010 Proxmox Server Solutions GmbH
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Affero General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Affero General Public License for more details.
14 You should have received a copy of the GNU Affero General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 Author: Dietmar Maurer <dietmar@proxmox.com>
23 #endif /* HAVE_CONFIG_H */
30 #include <sys/types.h>
32 #include <sys/mount.h>
36 #include <sys/types.h>
38 #include <sys/utsname.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
45 #include <qb/qbdefs.h>
46 #include <qb/qbutil.h>
49 #include "cfs-utils.h"
51 #include "cfs-plug-memdb.h"
59 #define DBFILENAME VARLIBDIR "/config.db"
60 #define LOCKFILE VARLIBDIR "/.pmxcfs.lockfile"
61 #define RESTART_FLAG_FILE RUNDIR "/cfs-restart-flag"
63 #define CFSDIR "/etc/pve"
69 static struct fuse
*fuse
= NULL
;
71 static cfs_plug_t
*root_plug
;
73 static void glib_print_handler(const gchar
*string
)
78 static void glib_log_handler(const gchar
*log_domain
,
79 GLogLevelFlags log_level
,
84 cfs_log(log_domain
, log_level
, NULL
, 0, NULL
, "%s", message
);
87 static gboolean
write_pidfile(pid_t pid
)
89 char *strpid
= g_strdup_printf("%d\n", pid
);
90 gboolean res
= atomic_write_file(CFS_PID_FN
, strpid
, strlen(strpid
), 0644, getgid());
96 static cfs_plug_t
*find_plug(const char *path
, char **sub
)
98 g_return_val_if_fail(root_plug
!= NULL
, NULL
);
99 g_return_val_if_fail(path
!= NULL
, NULL
);
101 while(*path
== '/') path
++;
103 cfs_debug("find_plug start %s", path
);
105 char *tmppath
= g_strdup(path
);
106 char *subpath
= tmppath
;
108 cfs_plug_t
*plug
= root_plug
->lookup_plug(root_plug
, &subpath
);
110 cfs_debug("find_plug end %s = %p (%s)", path
, (void *) plug
, subpath
);
112 if (subpath
&& subpath
[0])
113 *sub
= g_strdup(subpath
);
120 void *cfs_fuse_init(struct fuse_conn_info
*conn
)
125 static int cfs_fuse_getattr(const char *path
, struct stat
*stbuf
)
127 cfs_debug("enter cfs_fuse_getattr %s", path
);
131 char *subpath
= NULL
;
132 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
134 if (plug
&& plug
->ops
&& plug
->ops
->getattr
) {
135 ret
= plug
->ops
->getattr(plug
, subpath
? subpath
: "", stbuf
);
137 stbuf
->st_gid
= cfs
.gid
;
139 if (path_is_private(path
)) {
140 stbuf
->st_mode
&= 0777700;
142 if (S_ISDIR(stbuf
->st_mode
) || S_ISLNK(stbuf
->st_mode
)) {
143 stbuf
->st_mode
&= 0777755; // access for other users
145 if (path_is_lxc_conf(path
)) {
146 stbuf
->st_mode
&= 0777755; // access for other users
148 stbuf
->st_mode
&= 0777750; // no access for other users
154 cfs_debug("leave cfs_fuse_getattr %s (%d)", path
, ret
);
163 static int cfs_fuse_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
164 off_t offset
, struct fuse_file_info
*fi
)
169 cfs_debug("enter cfs_fuse_readdir %s", path
);
173 char *subpath
= NULL
;
174 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
179 if (plug
->ops
&& plug
->ops
->readdir
)
180 ret
= plug
->ops
->readdir(plug
, subpath
? subpath
: "", buf
, filler
, 0, fi
);
182 cfs_debug("leave cfs_fuse_readdir %s (%d)", path
, ret
);
190 static int cfs_fuse_chmod(const char *path
, mode_t mode
)
194 cfs_debug("enter cfs_fuse_chmod %s", path
);
196 mode_t allowed_mode
= (S_IRUSR
| S_IWUSR
);
197 if (!path_is_private(path
))
198 allowed_mode
|= (S_IRGRP
);
200 // allow only setting our supported modes (0600 for priv, 0640 for rest)
201 // mode has additional bits set, which we ignore; see stat(2)
202 if ((mode
& ALLPERMS
) == allowed_mode
)
205 cfs_debug("leave cfs_fuse_chmod %s (%d) mode: %o", path
, ret
, (int)mode
);
210 static int cfs_fuse_chown(const char *path
, uid_t user
, gid_t group
)
214 cfs_debug("enter cfs_fuse_chown %s", path
);
216 // we get -1 if no change should be made
217 if ((user
== 0 || user
== -1) && (group
== cfs
.gid
|| group
== -1))
220 cfs_debug("leave cfs_fuse_chown %s (%d) (uid: %d; gid: %d)", path
, ret
, user
, group
);
225 static int cfs_fuse_mkdir(const char *path
, mode_t mode
)
227 cfs_debug("enter cfs_fuse_mkdir %s", path
);
231 char *subpath
= NULL
;
232 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
237 if (subpath
&& plug
->ops
&& plug
->ops
->mkdir
)
238 ret
= plug
->ops
->mkdir(plug
, subpath
, mode
);
241 cfs_debug("leave cfs_fuse_mkdir %s (%d)", path
, ret
);
249 static int cfs_fuse_rmdir(const char *path
)
251 cfs_debug("enter cfs_fuse_rmdir %s", path
);
255 char *subpath
= NULL
;
256 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
261 if (subpath
&& plug
->ops
&& plug
->ops
->rmdir
)
262 ret
= plug
->ops
->rmdir(plug
, subpath
);
265 cfs_debug("leave cfs_fuse_rmdir %s (%d)", path
, ret
);
273 static int cfs_fuse_rename(const char *from
, const char *to
)
275 cfs_debug("enter cfs_fuse_rename from %s to %s", from
, to
);
279 char *sub_from
= NULL
;
280 cfs_plug_t
*plug_from
= find_plug(from
, &sub_from
);
283 cfs_plug_t
*plug_to
= find_plug(to
, &sub_to
);
285 if (!plug_from
|| !plug_to
|| plug_from
!= plug_to
)
288 if (plug_from
->ops
&& plug_from
->ops
->rename
&& sub_from
&& sub_to
)
289 ret
= plug_from
->ops
->rename(plug_from
, sub_from
, sub_to
);
292 cfs_debug("leave cfs_fuse_rename from %s to %s (%d)", from
, to
, ret
);
303 static int cfs_fuse_open(const char *path
, struct fuse_file_info
*fi
)
305 cfs_debug("enter cfs_fuse_open %s", path
);
312 char *subpath
= NULL
;
313 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
315 if (plug
&& plug
->ops
) {
316 if ((subpath
|| !plug
->ops
->readdir
) && plug
->ops
->open
) {
317 ret
= plug
->ops
->open(plug
, subpath
? subpath
: "", fi
);
321 cfs_debug("leave cfs_fuse_open %s (%d)", path
, ret
);
329 static int cfs_fuse_read(const char *path
, char *buf
, size_t size
, off_t offset
,
330 struct fuse_file_info
*fi
)
334 cfs_debug("enter cfs_fuse_read %s %zu %jd", path
, size
, offset
);
338 char *subpath
= NULL
;
339 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
341 if (plug
&& plug
->ops
) {
342 if ((subpath
|| !plug
->ops
->readdir
) && plug
->ops
->read
)
343 ret
= plug
->ops
->read(plug
, subpath
? subpath
: "", buf
, size
, offset
, fi
);
346 cfs_debug("leave cfs_fuse_read %s (%d)", path
, ret
);
354 static int cfs_fuse_write(const char *path
, const char *buf
, size_t size
,
355 off_t offset
, struct fuse_file_info
*fi
)
359 cfs_debug("enter cfs_fuse_write %s %zu %jd", path
, size
, offset
);
363 char *subpath
= NULL
;
364 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
366 if (plug
&& plug
->ops
) {
367 if ((subpath
|| !plug
->ops
->readdir
) && plug
->ops
->write
)
368 ret
= plug
->ops
->write(plug
, subpath
? subpath
: "",
369 buf
, size
, offset
, fi
);
372 cfs_debug("leave cfs_fuse_write %s (%d)", path
, ret
);
380 static int cfs_fuse_truncate(const char *path
, off_t size
)
382 cfs_debug("enter cfs_fuse_truncate %s %jd", path
, size
);
386 char *subpath
= NULL
;
387 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
389 if (plug
&& plug
->ops
) {
390 if ((subpath
|| !plug
->ops
->readdir
) && plug
->ops
->truncate
)
391 ret
= plug
->ops
->truncate(plug
, subpath
? subpath
: "", size
);
394 cfs_debug("leave cfs_fuse_truncate %s (%d)", path
, ret
);
402 static int cfs_fuse_create(const char *path
, mode_t mode
, struct fuse_file_info
*fi
)
404 cfs_debug("enter cfs_fuse_create %s", path
);
408 char *subpath
= NULL
;
409 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
414 if (subpath
&& plug
->ops
&& plug
->ops
->create
)
415 ret
= plug
->ops
->create(plug
, subpath
, mode
, fi
);
418 cfs_debug("leave cfs_fuse_create %s (%d)", path
, ret
);
426 static int cfs_fuse_unlink(const char *path
)
428 cfs_debug("enter cfs_fuse_unlink %s", path
);
432 char *subpath
= NULL
;
433 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
438 if (subpath
&& plug
->ops
&& plug
->ops
->unlink
)
439 ret
= plug
->ops
->unlink(plug
, subpath
);
442 cfs_debug("leave cfs_fuse_unlink %s (%d)", path
, ret
);
450 static int cfs_fuse_readlink(const char *path
, char *buf
, size_t max
)
452 cfs_debug("enter cfs_fuse_readlink %s", path
);
456 char *subpath
= NULL
;
457 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
462 if (plug
->ops
&& plug
->ops
->readlink
)
463 ret
= plug
->ops
->readlink(plug
, subpath
? subpath
: "", buf
, max
);
466 cfs_debug("leave cfs_fuse_readlink %s (%d)", path
, ret
);
474 static int cfs_fuse_utimens(const char *path
, const struct timespec tv
[2])
476 cfs_debug("enter cfs_fuse_utimens %s", path
);
480 char *subpath
= NULL
;
481 cfs_plug_t
*plug
= find_plug(path
, &subpath
);
486 if (plug
->ops
&& plug
->ops
->utimens
)
487 ret
= plug
->ops
->utimens(plug
, subpath
? subpath
: "", tv
);
490 cfs_debug("leave cfs_fuse_utimens %s (%d)", path
, ret
);
498 static int cfs_fuse_statfs(const char *path
, struct statvfs
*stbuf
)
500 g_return_val_if_fail(root_plug
!= NULL
, PARAM_CHECK_ERRNO
);
502 cfs_debug("enter cfs_fuse_statfs %s", path
);
506 if (root_plug
&& root_plug
->ops
&& root_plug
->ops
->statfs
)
507 ret
= root_plug
->ops
->statfs(root_plug
, "", stbuf
);
512 static struct fuse_operations fuse_ops
= {
513 .getattr
= cfs_fuse_getattr
,
514 .readdir
= cfs_fuse_readdir
,
515 .mkdir
= cfs_fuse_mkdir
,
516 .rmdir
= cfs_fuse_rmdir
,
517 .rename
= cfs_fuse_rename
,
518 .open
= cfs_fuse_open
,
519 .read
= cfs_fuse_read
,
520 .write
= cfs_fuse_write
,
521 .truncate
= cfs_fuse_truncate
,
522 .create
= cfs_fuse_create
,
523 .unlink
= cfs_fuse_unlink
,
524 .readlink
= cfs_fuse_readlink
,
525 .utimens
= cfs_fuse_utimens
,
526 .statfs
= cfs_fuse_statfs
,
527 .init
= cfs_fuse_init
,
528 .chown
= cfs_fuse_chown
,
529 .chmod
= cfs_fuse_chmod
533 create_dot_version_cb(cfs_plug_t
*plug
)
535 GString
*outbuf
= g_string_new(NULL
);
538 if (cfs_create_version_msg(outbuf
) == 0) {
540 g_string_free(outbuf
, FALSE
);
542 g_string_free(outbuf
, TRUE
);
549 create_dot_members_cb(cfs_plug_t
*plug
)
551 GString
*outbuf
= g_string_new(NULL
);
554 if (cfs_create_memberlist_msg(outbuf
) == 0) {
556 g_string_free(outbuf
, FALSE
);
558 g_string_free(outbuf
, TRUE
);
565 create_dot_vmlist_cb(cfs_plug_t
*plug
)
567 GString
*outbuf
= g_string_new(NULL
);
570 if (cfs_create_vmlist_msg(outbuf
) == 0) {
572 g_string_free(outbuf
, FALSE
);
574 g_string_free(outbuf
, TRUE
);
581 create_dot_rrd_cb(cfs_plug_t
*plug
)
583 GString
*outbuf
= g_string_new(NULL
);
585 cfs_rrd_dump(outbuf
);
586 char *data
= outbuf
->str
;
587 g_string_free(outbuf
, FALSE
);
593 create_dot_clusterlog_cb(cfs_plug_t
*plug
)
595 GString
*outbuf
= g_string_new(NULL
);
597 cfs_cluster_log_dump(outbuf
, NULL
, 50);
598 char *data
= outbuf
->str
;
599 g_string_free(outbuf
, FALSE
);
605 read_debug_setting_cb(cfs_plug_t
*plug
)
607 return g_strdup_printf("%d\n", !!cfs
.debug
);
611 my_qb_log_filter(struct qb_log_callsite
*cs
)
613 int32_t priority
= cfs
.debug
? LOG_DEBUG
: LOG_INFO
;
615 if (qb_bit_is_set(cs
->tags
, QB_LOG_TAG_LIBQB_MSG_BIT
)) {
616 if (cs
->priority
<= (cfs
.debug
? priority
: LOG_WARNING
)) {
617 qb_bit_set(cs
->targets
, QB_LOG_SYSLOG
);
619 qb_bit_clear(cs
->targets
, QB_LOG_SYSLOG
);
621 if (cs
->priority
<= priority
) {
622 qb_bit_set(cs
->targets
, QB_LOG_STDERR
);
624 qb_bit_clear(cs
->targets
, QB_LOG_STDERR
);
627 if (cs
->priority
<= priority
) {
628 qb_bit_set(cs
->targets
, QB_LOG_SYSLOG
);
629 qb_bit_set(cs
->targets
, QB_LOG_STDERR
);
631 qb_bit_clear(cs
->targets
, QB_LOG_SYSLOG
);
632 qb_bit_clear(cs
->targets
, QB_LOG_STDERR
);
638 update_qb_log_settings(void)
640 qb_log_filter_fn_set(my_qb_log_filter
);
643 qb_log_format_set(QB_LOG_SYSLOG
, "[%g] %p: %b (%f:%l:%n)");
644 qb_log_format_set(QB_LOG_STDERR
, "[%g] %p: %b (%f:%l:%n)");
646 qb_log_format_set(QB_LOG_SYSLOG
, "[%g] %p: %b");
647 qb_log_format_set(QB_LOG_STDERR
, "[%g] %p: %b");
652 write_debug_setting_cb(
662 if (strncmp(buf
, "0\n", 2) == 0) {
664 cfs_message("disable debug mode");
666 update_qb_log_settings();
669 } else if (strncmp(buf
, "1\n", 2) == 0) {
672 update_qb_log_settings();
673 cfs_message("enable debug mode");
682 create_symlinks(cfs_plug_base_t
*bplug
, const char *nodename
)
684 g_return_if_fail(bplug
!= NULL
);
685 g_return_if_fail(nodename
!= NULL
);
687 char *lnktarget
= g_strdup_printf("nodes/%s", nodename
);
688 cfs_plug_link_t
*lnk
= cfs_plug_link_new("local", lnktarget
);
690 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)lnk
);
692 lnktarget
= g_strdup_printf("nodes/%s/qemu-server", nodename
);
693 lnk
= cfs_plug_link_new("qemu-server", lnktarget
);
695 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)lnk
);
697 lnktarget
= g_strdup_printf("nodes/%s/openvz", nodename
);
698 lnk
= cfs_plug_link_new("openvz", lnktarget
);
700 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)lnk
);
702 lnktarget
= g_strdup_printf("nodes/%s/lxc", nodename
);
703 lnk
= cfs_plug_link_new("lxc", lnktarget
);
705 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)lnk
);
707 cfs_plug_func_t
*fplug
= cfs_plug_func_new(".version", 0440, create_dot_version_cb
, NULL
);
708 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)fplug
);
710 fplug
= cfs_plug_func_new(".members", 0440, create_dot_members_cb
, NULL
);
711 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)fplug
);
713 fplug
= cfs_plug_func_new(".vmlist", 0440, create_dot_vmlist_cb
, NULL
);
714 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)fplug
);
716 fplug
= cfs_plug_func_new(".rrd", 0440, create_dot_rrd_cb
, NULL
);
717 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)fplug
);
719 fplug
= cfs_plug_func_new(".clusterlog", 0440, create_dot_clusterlog_cb
, NULL
);
720 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)fplug
);
722 fplug
= cfs_plug_func_new(".debug", 0640, read_debug_setting_cb
, write_debug_setting_cb
);
723 cfs_plug_base_insert(bplug
, (cfs_plug_t
*)fplug
);
729 lookup_node_ip(const char *nodename
)
731 char buf
[INET6_ADDRSTRLEN
];
732 struct addrinfo
*ainfo
;
733 struct addrinfo ahints
;
735 memset(&ahints
, 0, sizeof(ahints
));
737 if (getaddrinfo(nodename
, NULL
, &ahints
, &ainfo
))
740 if (ainfo
->ai_family
== AF_INET
) {
741 struct sockaddr_in
*sa
= (struct sockaddr_in
*)ainfo
->ai_addr
;
742 inet_ntop(ainfo
->ai_family
, &sa
->sin_addr
, buf
, sizeof(buf
));
743 if (strncmp(buf
, "127.", 4) != 0) {
746 } else if (ainfo
->ai_family
== AF_INET6
) {
747 struct sockaddr_in6
*sa
= (struct sockaddr_in6
*)ainfo
->ai_addr
;
748 inet_ntop(ainfo
->ai_family
, &sa
->sin6_addr
, buf
, sizeof(buf
));
749 if (strcmp(buf
, "::1") != 0) {
760 log_tags_stringify(uint32_t tags
) {
761 if (qb_bit_is_set(tags
, QB_LOG_TAG_LIBQB_MSG_BIT
)) {
765 const char *domain
= g_quark_to_string(quark
);
766 if (domain
!= NULL
) {
774 int main(int argc
, char *argv
[])
780 gboolean foreground
= FALSE
;
781 gboolean force_local_mode
= FALSE
;
782 gboolean wrote_pidfile
= FALSE
;
783 memdb_t
*memdb
= NULL
;
785 dfsm_t
*status_fsm
= NULL
;
787 qb_log_init("pmxcfs", LOG_DAEMON
, LOG_DEBUG
);
788 /* remove default filter */
789 qb_log_filter_ctl(QB_LOG_SYSLOG
, QB_LOG_FILTER_REMOVE
,
790 QB_LOG_FILTER_FILE
, "*", LOG_DEBUG
);
792 qb_log_tags_stringify_fn_set(log_tags_stringify
);
794 qb_log_ctl(QB_LOG_STDERR
, QB_LOG_CONF_ENABLED
, QB_TRUE
);
796 update_qb_log_settings();
798 g_set_print_handler(glib_print_handler
);
799 g_set_printerr_handler(glib_print_handler
);
800 g_log_set_default_handler(glib_log_handler
, NULL
);
802 GOptionContext
*context
;
804 GOptionEntry entries
[] = {
805 { "debug", 'd', 0, G_OPTION_ARG_NONE
, &cfs
.debug
, "Turn on debug messages", NULL
},
806 { "foreground", 'f', 0, G_OPTION_ARG_NONE
, &foreground
, "Do not daemonize server", NULL
},
807 { "local", 'l', 0, G_OPTION_ARG_NONE
, &force_local_mode
,
808 "Force local mode (ignore corosync.conf, force quorum)", NULL
},
812 context
= g_option_context_new ("");
813 g_option_context_add_main_entries (context
, entries
, NULL
);
816 if (!g_option_context_parse (context
, &argc
, &argv
, &err
))
818 cfs_critical("option parsing failed: %s", err
->message
);
823 g_option_context_free(context
);
826 cfs_critical("too many arguments");
832 update_qb_log_settings();
835 struct utsname utsname
;
836 if (uname(&utsname
) != 0) {
837 cfs_critical("Unable to read local node name");
842 char *dot
= strchr(utsname
.nodename
, '.');
846 cfs
.nodename
= g_strdup(utsname
.nodename
);
848 if (!(cfs
.ip
= lookup_node_ip(cfs
.nodename
))) {
849 cfs_critical("Unable to get local IP address");
854 struct group
*www_data
= getgrnam("www-data");
856 cfs_critical("Unable to get www-data group ID");
860 cfs
.gid
= www_data
->gr_gid
;
864 mkdir(VARLIBDIR
, 0755);
866 chown(RUNDIR
, 0, cfs
.gid
);
868 if ((lockfd
= open(LOCKFILE
, O_RDWR
|O_CREAT
|O_APPEND
, 0600)) == -1) {
869 cfs_critical("unable to create lock '%s': %s", LOCKFILE
, strerror (errno
));
873 for (int i
= 10; i
>= 0; i
--) {
874 if (flock(lockfd
, LOCK_EX
|LOCK_NB
) != 0) {
876 cfs_critical("unable to acquire pmxcfs lock: %s", strerror (errno
));
880 cfs_message("unable to acquire pmxcfs lock - trying again");
888 gboolean create
= !g_file_test(DBFILENAME
, G_FILE_TEST_EXISTS
);
890 if (!(memdb
= memdb_open (DBFILENAME
))) {
891 cfs_critical("memdb_open failed - unable to open database '%s'", DBFILENAME
);
895 // automatically import corosync.conf from host
896 if (create
&& !force_local_mode
) {
899 if (g_file_get_contents(HOST_CLUSTER_CONF_FN
, &cdata
, &clen
, NULL
)) {
901 guint32 mtime
= time(NULL
);
903 memdb_create(memdb
, "/corosync.conf", 0, mtime
);
904 if (memdb_write(memdb
, "/corosync.conf", 0, mtime
, cdata
, clen
, 0, 1) < 0) {
905 cfs_critical("memdb_write failed - unable to import corosync.conf");
911 // does corosync.conf exist?
912 gpointer conf_data
= NULL
;
913 int len
= memdb_read(memdb
, "corosync.conf", &conf_data
);
915 if (force_local_mode
) {
916 cfs_message("forcing local mode (although corosync.conf exists)");
917 cfs_set_quorate(1, TRUE
);
919 if (!(dcdb
= dcdb_new(memdb
)))
921 dcdb_sync_corosync_conf(memdb
, 1);
924 cfs_debug("using local mode (corosync.conf does not exist)");
925 cfs_set_quorate(1, TRUE
);
927 if (conf_data
) g_free(conf_data
);
929 cfs_plug_memdb_t
*config
= cfs_plug_memdb_new("memdb", memdb
, dcdb
);
931 cfs_plug_base_t
*bplug
= cfs_plug_base_new("", (cfs_plug_t
*)config
);
933 create_symlinks(bplug
, cfs
.nodename
);
935 root_plug
= (cfs_plug_t
*)bplug
;
937 umount2(CFSDIR
, MNT_FORCE
);
941 char *fa
[] = { "-f", "-odefault_permissions", "-oallow_other", NULL
};
943 struct fuse_args fuse_args
= FUSE_ARGS_INIT(sizeof (fa
)/sizeof(gpointer
) - 1, fa
);
945 struct fuse_chan
*fuse_chan
= fuse_mount(CFSDIR
, &fuse_args
);
947 cfs_critical("fuse_mount error: %s", strerror(errno
));
951 if (!(fuse
= fuse_new(fuse_chan
, &fuse_args
, &fuse_ops
, sizeof(fuse_ops
), NULL
))) {
952 cfs_critical("fuse_new error: %s", strerror(errno
));
956 fuse_set_signal_handlers(fuse_get_session(fuse
));
959 if (pipe(pipefd
) == -1) {
960 cfs_critical("pipe error: %s", strerror(errno
));
967 cfs_critical("failed to daemonize program - %s", strerror (errno
));
970 int readbytes
, errno_tmp
;
973 readbytes
= read(pipefd
[0], &readbuffer
, sizeof(readbuffer
));
976 if (readbytes
== -1) {
977 cfs_critical("read error: %s", strerror(errno_tmp
));
980 } else if (readbytes
!= 1 || readbuffer
!= '1') {
981 cfs_critical("child failed to send '1'");
985 /* child finished starting up */
995 if ((nullfd
= open("/dev/null", O_RDWR
, 0)) != -1) {
1003 // do not print to the console after this point
1004 qb_log_ctl(QB_LOG_STDERR
, QB_LOG_CONF_ENABLED
, QB_FALSE
);
1009 write_pidfile(getpid());
1012 wrote_pidfile
= TRUE
;
1014 cfs_loop_t
*corosync_loop
= cfs_loop_new(fuse
);
1016 cfs_service_t
*service_quorum
= NULL
;
1017 cfs_service_t
*service_confdb
= NULL
;
1018 cfs_service_t
*service_dcdb
= NULL
;
1019 cfs_service_t
*service_status
= NULL
;
1023 service_quorum
= service_quorum_new();
1025 cfs_loop_add_service(corosync_loop
, service_quorum
, QB_LOOP_HIGH
);
1027 service_confdb
= service_confdb_new();
1029 cfs_loop_add_service(corosync_loop
, service_confdb
, QB_LOOP_MED
);
1031 service_dcdb
= service_dfsm_new(dcdb
);
1032 cfs_service_set_timer(service_dcdb
, DCDB_VERIFY_TIME
);
1034 cfs_loop_add_service(corosync_loop
, service_dcdb
, QB_LOOP_MED
);
1036 status_fsm
= cfs_status_dfsm_new();
1037 service_status
= service_dfsm_new(status_fsm
);
1039 cfs_loop_add_service(corosync_loop
, service_status
, QB_LOOP_LOW
);
1043 cfs_loop_start_worker(corosync_loop
);
1045 server_start(memdb
);
1047 unlink(RESTART_FLAG_FILE
);
1050 /* finished starting up, signaling parent */
1051 write(pipefd
[1], "1", 1);
1055 ret
= fuse_loop_mt(fuse
);
1057 open(RESTART_FLAG_FILE
, O_CREAT
|O_NOCTTY
|O_NONBLOCK
, S_IRUSR
| S_IRGRP
);
1058 chown(RESTART_FLAG_FILE
, 0, cfs
.gid
);
1060 cfs_message("teardown filesystem");
1064 fuse_unmount(CFSDIR
, fuse_chan
);
1068 cfs_debug("set stop event loop flag");
1070 cfs_loop_stop_worker(corosync_loop
);
1072 cfs_loop_destroy(corosync_loop
);
1074 cfs_debug("worker finished");
1077 service_dfsm_destroy(service_dcdb
);
1080 service_confdb_destroy(service_confdb
);
1083 service_quorum_destroy(service_quorum
);
1086 service_dfsm_destroy(service_status
);
1091 dfsm_destroy(status_fsm
);
1102 cfs_message("exit proxmox configuration filesystem (%d)", ret
);
1104 cfs_status_cleanup();