#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-
+
#include <qb/qbdefs.h>
#include <qb/qbutil.h>
#include <qb/qblog.h>
#define DBFILENAME VARLIBDIR "/config.db"
#define LOCKFILE VARLIBDIR "/.pmxcfs.lockfile"
+#define RESTART_FLAG_FILE RUNDIR "/cfs-restart-flag"
-#define CFSDIR "/etc/pve"
+#define CFSDIR "/etc/pve"
cfs_t cfs = {
.debug = 0,
cfs_debug("find_plug end %s = %p (%s)", path, plug, subpath);
- if (subpath && subpath[0])
+ if (subpath && subpath[0])
*sub = g_strdup(subpath);
g_free(tmppath);
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
+
if (plug && plug->ops && plug->ops->getattr) {
ret = plug->ops->getattr(plug, subpath ? subpath : "", stbuf);
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
+
if (!plug)
goto ret;
ret = plug->ops->readdir(plug, subpath ? subpath : "", buf, filler, 0, fi);
ret:
cfs_debug("leave cfs_fuse_readdir %s (%d)", path, ret);
-
+
if (subpath)
g_free(subpath);
-
+
+ return ret;
+}
+
+static int cfs_fuse_chmod(const char *path, mode_t mode)
+{
+ int ret = -EPERM;
+
+ cfs_debug("enter cfs_fuse_chmod %s", path);
+
+ mode_t allowed_mode = (S_IRUSR | S_IWUSR);
+ if (!path_is_private(path))
+ allowed_mode |= (S_IRGRP);
+
+ // allow only setting our supported modes (0600 for priv, 0640 for rest)
+ // mode has additional bits set, which we ignore; see stat(2)
+ if ((mode & ALLPERMS) == allowed_mode)
+ ret = 0;
+
+ cfs_debug("leave cfs_fuse_chmod %s (%d) mode: %o", path, ret, (int)mode);
+
+ return ret;
+}
+
+static int cfs_fuse_chown(const char *path, uid_t user, gid_t group)
+{
+ int ret = -EPERM;
+
+ cfs_debug("enter cfs_fuse_chown %s", path);
+
+ // we get -1 if no change should be made
+ if ((user == 0 || user == -1) && (group == cfs.gid || group == -1))
+ ret = 0;
+
+ cfs_debug("leave cfs_fuse_chown %s (%d) (uid: %d; gid: %d)", path, ret, user, group);
+
return ret;
}
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
+
if (!plug)
goto ret;
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
+
if (!plug)
goto ret;
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
- if (plug && plug->ops) {
+
+ if (plug && plug->ops) {
if ((subpath || !plug->ops->readdir) && plug->ops->open) {
ret = plug->ops->open(plug, subpath ? subpath : "", fi);
}
{
(void) fi;
- cfs_debug("enter cfs_fuse_read %s %lu %ld", path, size, offset);
+ cfs_debug("enter cfs_fuse_read %s %zu %jd", path, size, offset);
int ret = -EACCES;
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
- if (plug && plug->ops) {
+
+ if (plug && plug->ops) {
if ((subpath || !plug->ops->readdir) && plug->ops->read)
ret = plug->ops->read(plug, subpath ? subpath : "", buf, size, offset, fi);
}
{
(void) fi;
- cfs_debug("enter cfs_fuse_write %s %lu %ld", path, size, offset);
+ cfs_debug("enter cfs_fuse_write %s %zu %jd", path, size, offset);
int ret = -EACCES;
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
- if (plug && plug->ops) {
+
+ if (plug && plug->ops) {
if ((subpath || !plug->ops->readdir) && plug->ops->write)
- ret = plug->ops->write(plug, subpath ? subpath : "",
+ ret = plug->ops->write(plug, subpath ? subpath : "",
buf, size, offset, fi);
}
-
+
cfs_debug("leave cfs_fuse_write %s (%d)", path, ret);
if (subpath)
static int cfs_fuse_truncate(const char *path, off_t size)
{
- cfs_debug("enter cfs_fuse_truncate %s %ld", path, size);
+ cfs_debug("enter cfs_fuse_truncate %s %jd", path, size);
int ret = -EACCES;
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
- if (plug && plug->ops) {
+
+ if (plug && plug->ops) {
if ((subpath || !plug->ops->readdir) && plug->ops->truncate)
ret = plug->ops->truncate(plug, subpath ? subpath : "", size);
}
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
+
if (!plug)
goto ret;
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
+
if (!plug)
goto ret;
if (subpath)
g_free(subpath);
-
+
return ret;
}
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
+
if (!plug)
goto ret;
if (plug->ops && plug->ops->readlink)
ret = plug->ops->readlink(plug, subpath ? subpath : "", buf, max);
-
+
ret:
cfs_debug("leave cfs_fuse_readlink %s (%d)", path, ret);
char *subpath = NULL;
cfs_plug_t *plug = find_plug(path, &subpath);
-
+
if (!plug)
goto ret;
if (plug->ops && plug->ops->utimens)
ret = plug->ops->utimens(plug, subpath ? subpath : "", tv);
-
+
ret:
cfs_debug("leave cfs_fuse_utimens %s (%d)", path, ret);
.readlink = cfs_fuse_readlink,
.utimens = cfs_fuse_utimens,
.statfs = cfs_fuse_statfs,
- .init = cfs_fuse_init
+ .init = cfs_fuse_init,
+ .chown = cfs_fuse_chown,
+ .chmod = cfs_fuse_chmod
};
static char *
static char *
read_debug_setting_cb(cfs_plug_t *plug)
{
- return g_strdup_printf("%d\n", !!cfs.debug);
+ return g_strdup_printf("%d\n", !!cfs.debug);
}
static void
}
}
-static void
-update_qb_log_settings(void)
+static void
+update_qb_log_settings(void)
{
qb_log_filter_fn_set(my_qb_log_filter);
}
}
-static int
+static int
write_debug_setting_cb(
- cfs_plug_t *plug,
+ cfs_plug_t *plug,
const char *buf,
size_t size)
{
return res;
}
-static void
+static void
create_symlinks(cfs_plug_base_t *bplug, const char *nodename)
{
g_return_if_fail(bplug != NULL);
lnk = cfs_plug_link_new("qemu-server", lnktarget);
g_free(lnktarget);
cfs_plug_base_insert(bplug, (cfs_plug_t*)lnk);
-
+
lnktarget = g_strdup_printf("nodes/%s/openvz", nodename);
lnk = cfs_plug_link_new("openvz", lnktarget);
g_free(lnktarget);
cfs_plug_func_t *fplug = cfs_plug_func_new(".version", 0440, create_dot_version_cb, NULL);
cfs_plug_base_insert(bplug, (cfs_plug_t*)fplug);
-
+
fplug = cfs_plug_func_new(".members", 0440, create_dot_members_cb, NULL);
cfs_plug_base_insert(bplug, (cfs_plug_t*)fplug);
}
static char *
-lookup_node_ip(const char *nodename)
+lookup_node_ip(const char *nodename)
{
+ char buf[INET6_ADDRSTRLEN];
struct addrinfo *ainfo;
struct addrinfo ahints;
+ char *res = NULL;
memset(&ahints, 0, sizeof(ahints));
if (getaddrinfo(nodename, NULL, &ahints, &ainfo))
return NULL;
if (ainfo->ai_family == AF_INET) {
- char buf[INET6_ADDRSTRLEN];
struct sockaddr_in *sa = (struct sockaddr_in *)ainfo->ai_addr;
inet_ntop(ainfo->ai_family, &sa->sin_addr, buf, sizeof(buf));
if (strncmp(buf, "127.", 4) != 0) {
- return g_strdup(buf);
+ res = g_strdup(buf);
+ }
+ } else if (ainfo->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ainfo->ai_addr;
+ inet_ntop(ainfo->ai_family, &sa->sin6_addr, buf, sizeof(buf));
+ if (strcmp(buf, "::1") != 0) {
+ res = g_strdup(buf);
}
}
- // ipv6 support ?
+ freeaddrinfo(ainfo);
- return NULL;
+ return res;
}
-static const char*
+static const char*
log_tags_stringify(uint32_t tags) {
if (qb_bit_is_set(tags, QB_LOG_TAG_LIBQB_MSG_BIT)) {
return "libqb";
qb_log_init("pmxcfs", LOG_DAEMON, LOG_DEBUG);
/* remove default filter */
- qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_REMOVE,
+ qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_REMOVE,
QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
qb_log_tags_stringify_fn_set(log_tags_stringify);
GOptionEntry entries[] = {
{ "debug", 'd', 0, G_OPTION_ARG_NONE, &cfs.debug, "Turn on debug messages", NULL },
{ "foreground", 'f', 0, G_OPTION_ARG_NONE, &foreground, "Do not daemonize server", NULL },
- { "local", 'l', 0, G_OPTION_ARG_NONE, &force_local_mode,
+ { "local", 'l', 0, G_OPTION_ARG_NONE, &force_local_mode,
"Force local mode (ignore corosync.conf, force quorum)", NULL },
{ NULL },
};
qb_log_fini();
exit (-1);
}
-
- for (int i=0; i < sizeof(utsname.nodename); i++) {
- if (utsname.nodename[i] =='.') utsname.nodename[i] = 0;
- }
+
+ char *dot = strchr(utsname.nodename, '.');
+ if (dot)
+ *dot = 0;
cfs.nodename = g_strdup(utsname.nodename);
- if (!(cfs.ip = lookup_node_ip(cfs.nodename))) {
+ if (!(cfs.ip = lookup_node_ip(cfs.nodename))) {
cfs_critical("Unable to get local IP address");
qb_log_fini();
exit(-1);
umask(027);
mkdir(VARLIBDIR, 0755);
+ mkdir(RUNDIR, 0755);
- if ((lockfd = open(LOCKFILE, O_RDWR|O_CREAT|O_APPEND)) == -1) {
+ if ((lockfd = open(LOCKFILE, O_RDWR|O_CREAT|O_APPEND, 0600)) == -1) {
cfs_critical("unable to create lock '%s': %s", LOCKFILE, strerror (errno));
goto err;
}
int len = memdb_read(memdb, "corosync.conf", &conf_data);
if (len >= 0) {
if (force_local_mode) {
- cfs_message("forcing local mode (althought corosync.conf exists)");
+ cfs_message("forcing local mode (although corosync.conf exists)");
cfs_set_quorate(1, TRUE);
} else {
if (!(dcdb = dcdb_new(memdb)))
if (conf_data) g_free(conf_data);
cfs_plug_memdb_t *config = cfs_plug_memdb_new("memdb", memdb, dcdb);
-
+
cfs_plug_base_t *bplug = cfs_plug_base_new("", (cfs_plug_t *)config);
create_symlinks(bplug, cfs.nodename);
root_plug = (cfs_plug_t *)bplug;
- system("umount -f " CFSDIR " >/dev/null 2>&1");
+ umount2(CFSDIR, MNT_FORCE);
mkdir(CFSDIR, 0755);
-
+
char *fa[] = { "-f", "-odefault_permissions", "-oallow_other", NULL};
- struct fuse_args fuse_args = FUSE_ARGS_INIT(sizeof (fa)/sizeof(gpointer) - 1, fa);
-
+ struct fuse_args fuse_args = FUSE_ARGS_INIT(sizeof (fa)/sizeof(gpointer) - 1, fa);
+
struct fuse_chan *fuse_chan = fuse_mount(CFSDIR, &fuse_args);
if (!fuse_chan) {
cfs_critical("fuse_mount error: %s", strerror(errno));
server_start(memdb);
+ unlink(RESTART_FLAG_FILE);
+
ret = fuse_loop_mt(fuse);
+ open(RESTART_FLAG_FILE, O_CREAT|O_NOCTTY|O_NONBLOCK);
+
cfs_message("teardown filesystem");
server_stop();
if (service_status)
service_dfsm_destroy(service_status);
- sleep(1); /* do not restart too fast */
ret:
- if (status_fsm)
+ if (status_fsm)
dfsm_destroy(status_fsm);
if (dcdb)
dfsm_destroy(dcdb);
- if (memdb)
+ if (memdb)
memdb_close(memdb);
if (wrote_pidfile)