On 11.12.2012 21:41, Daniel P. Berrange wrote: > From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> > > The virtlockd daemon will maintain locks on behalf of libvirtd. > There are two reasons for it to be separate > > - Avoid risk of other libvirtd threads accidentally > releasing fcntl() locks by opening + closing a file > that is locked > - Ensure locks can be preserved across libvirtd restarts. > virtlockd will need to be able to re-exec itself while > maintaining locks. This is simpler to achieve if its > sole job is maintaining locks > > Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> > --- > .gitignore | 2 + > cfg.mk | 6 +- > libvirt.spec.in | 7 + > po/POTFILES.in | 2 + > src/Makefile.am | 89 +++- > src/locking/lock_daemon.c | 850 +++++++++++++++++++++++++++++++++++++++ > src/locking/lock_daemon.h | 43 ++ > src/locking/lock_daemon_config.c | 193 +++++++++ > src/locking/lock_daemon_config.h | 50 +++ > src/locking/virtlockd.init.in | 93 +++++ > src/locking/virtlockd.sysconf | 3 + > 11 files changed, 1334 insertions(+), 4 deletions(-) > create mode 100644 src/locking/lock_daemon.c > create mode 100644 src/locking/lock_daemon.h > create mode 100644 src/locking/lock_daemon_config.c > create mode 100644 src/locking/lock_daemon_config.h > create mode 100644 src/locking/virtlockd.init.in > create mode 100644 src/locking/virtlockd.sysconf > > diff --git a/.gitignore b/.gitignore > index 0dadd21..1e3a624 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -123,6 +123,8 @@ > /src/test_libvirt*.aug > /src/util/virkeymaps.h > /src/virt-aa-helper > +/src/virtlockd > +/src/virtlockd.init > /tests/*.log > /tests/*.pid > /tests/*xml2*test > diff --git a/cfg.mk b/cfg.mk > index f218eb6..95a1d3a 100644 > --- a/cfg.mk > +++ b/cfg.mk > @@ -655,6 +655,8 @@ sc_prohibit_cross_inclusion: > @for dir in $(cross_dirs); do \ > case $$dir in \ > util/) safe="util";; \ > + locking/) \ > + safe="($$dir|util|conf|rpc)";; \ > cpu/ | locking/ | network/ | rpc/ | security/) \ > safe="($$dir|util|conf)";; \ > xenapi/ | xenxs/ ) safe="($$dir|util|conf|xen)";; \ > @@ -743,7 +745,7 @@ $(srcdir)/src/remote/remote_client_bodies.h: $(srcdir)/src/remote/remote_protoco > # List all syntax-check exemptions: > exclude_file_name_regexp--sc_avoid_strcase = ^tools/virsh\.h$$ > > -_src1=libvirt|fdstream|qemu/qemu_monitor|util/(command|util)|xen/xend_internal|rpc/virnetsocket|lxc/lxc_controller > +_src1=libvirt|fdstream|qemu/qemu_monitor|util/(command|util)|xen/xend_internal|rpc/virnetsocket|lxc/lxc_controller|locking/lock_daemon > exclude_file_name_regexp--sc_avoid_write = \ > ^(src/($(_src1))|daemon/libvirtd|tools/console|tests/(shunload|virnettlscontext)test)\.c$$ > > @@ -776,7 +778,7 @@ exclude_file_name_regexp--sc_prohibit_close = \ > exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \ > (^tests/(qemuhelp|nodeinfo)data/|\.(gif|ico|png|diff)$$) > > -_src2=src/(util/command|libvirt|lxc/lxc_controller) > +_src2=src/(util/command|libvirt|lxc/lxc_controller|locking/lock_daemon) > exclude_file_name_regexp--sc_prohibit_fork_wrappers = \ > (^($(_src2)|tests/testutils|daemon/libvirtd)\.c$$) > > diff --git a/libvirt.spec.in b/libvirt.spec.in > index d6e1fbe..e12fca4 100644 > --- a/libvirt.spec.in > +++ b/libvirt.spec.in > @@ -1661,9 +1661,11 @@ fi > %{_unitdir}/libvirtd.service > %else > %{_sysconfdir}/rc.d/init.d/libvirtd > +%{_sysconfdir}/rc.d/init.d/virtlockd > %endif > %doc daemon/libvirtd.upstart > %config(noreplace) %{_sysconfdir}/sysconfig/libvirtd > +%config(noreplace) %{_sysconfdir}/sysconfig/virtlockd > %config(noreplace) %{_sysconfdir}/libvirt/libvirtd.conf > %if 0%{?fedora} >= 14 || 0%{?rhel} >= 6 > %config(noreplace) %{_sysconfdir}/sysctl.d/libvirtd > @@ -1730,6 +1732,10 @@ rm -f $RPM_BUILD_ROOT%{_sysconfdir}/sysctl.d/libvirtd > %dir %attr(0755, root, root) %{_localstatedir}/lib/libvirt/dnsmasq/ > %endif > > +%if %{with_libvirtd} > +%dir %attr(0755, root, root) %{_libdir}/libvirt/lock-driver > +%endif > + > %if %{with_qemu} > %{_datadir}/augeas/lenses/libvirtd_qemu.aug > %{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug > @@ -1763,6 +1769,7 @@ rm -f $RPM_BUILD_ROOT%{_sysconfdir}/sysctl.d/libvirtd > > %attr(0755, root, root) %{_libexecdir}/libvirt_iohelper > %attr(0755, root, root) %{_sbindir}/libvirtd > +%attr(0755, root, root) %{_sbindir}/virtlockd > > %{_mandir}/man8/libvirtd.8* > > diff --git a/po/POTFILES.in b/po/POTFILES.in > index 51a1f5c..34c688c 100644 > --- a/po/POTFILES.in > +++ b/po/POTFILES.in > @@ -48,6 +48,8 @@ src/interface/interface_backend_udev.c > src/internal.h > src/libvirt.c > src/libvirt-qemu.c > +src/locking/lock_daemon.c > +src/locking/lock_daemon_config.c > src/locking/lock_driver_sanlock.c > src/locking/lock_manager.c > src/locking/sanlock_helper.c > diff --git a/src/Makefile.am b/src/Makefile.am > index 6d2816d..6a66efd 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -148,6 +148,13 @@ LOCK_DRIVER_SANLOCK_SOURCES = \ > LOCK_DRIVER_SANLOCK_HELPER_SOURCES = \ > locking/sanlock_helper.c > > +LOCK_DAEMON_SOURCES = \ > + locking/lock_daemon.h \ > + locking/lock_daemon.c \ > + locking/lock_daemon_config.h \ > + locking/lock_daemon_config.c \ > + $(NULL) > + > NETDEV_CONF_SOURCES = \ > conf/netdev_bandwidth_conf.h conf/netdev_bandwidth_conf.c \ > conf/netdev_vport_profile_conf.h conf/netdev_vport_profile_conf.c \ > @@ -1508,6 +1515,76 @@ libvirt_qemu_la_CFLAGS = $(AM_CFLAGS) > libvirt_qemu_la_LIBADD = libvirt.la $(CYGWIN_EXTRA_LIBADD) > EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE) > > +if WITH_LIBVIRTD > +sbin_PROGRAMS = virtlockd > + > +virtlockd_SOURCES = $(LOCK_DAEMON_SOURCES) > +virtlockd_CFLAGS = \ > + $(AM_CFLAGS) \ > + $(NULL) > +virtlockd_LDFLAGS = \ > + $(AM_LDFLAGS) \ > + $(CYGWIN_EXTRA_LDFLAGS) \ > + $(MINGW_EXTRA_LDFLAGS) \ > + $(NULL) > +virtlockd_LDADD = \ > + libvirt-net-rpc-server.la \ > + libvirt-net-rpc.la \ > + libvirt_util.la \ > + ../gnulib/lib/libgnu.la \ > + $(CYGWIN_EXTRA_LIBADD) \ > + $(NULL) > +if WITH_DTRACE_PROBES > +virtlockd_LDADD += libvirt_probes.lo > +endif > + > +else > +EXTRA_DIST += $(LOCK_DAEMON_SOURCES) > +endif > + > +EXTRA_DIST += locking/virtlockd.sysconf > + > +install-sysconfig: > + mkdir -p $(DESTDIR)$(sysconfdir)/sysconfig > + $(INSTALL_DATA) $(srcdir)/locking/virtlockd.sysconf \ > + $(DESTDIR)$(sysconfdir)/sysconfig/virtlockd > + > +uninstall-sysconfig: > + rm -f $(DESTDIR)$(sysconfdir)/sysconfig/virtlockd > + > +EXTRA_DIST += locking/virtlockd.init.in > + > +if WITH_LIBVIRTD > +if LIBVIRT_INIT_SCRIPT_RED_HAT > +install-init:: virtlockd.init install-sysconfig > + mkdir -p $(DESTDIR)$(sysconfdir)/rc.d/init.d > + $(INSTALL_SCRIPT) virtlockd.init \ > + $(DESTDIR)$(sysconfdir)/rc.d/init.d/virtlockd > + > +uninstall-init:: uninstall-sysconfig > + rm -f $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd > + > +BUILT_SOURCES += virtlockd.init > +else > +install-init:: > +uninstall-init:: > +endif > +else > +install-init:: > +uninstall-init:: > +endif > + > +virtlockd.init: locking/virtlockd.init.in $(top_builddir)/config.status > + $(AM_V_GEN)sed \ > + -e "s!::localstatedir::!$(localstatedir)!g" \ > + -e "s!::sbindir::!$(sbindir)!g" \ > + -e "s!::sysconfdir::!$(sysconfdir)!g" \ > + < $< > $@-t && \ > + chmod a+x $@-t && \ > + mv $@-t $@ > + > + > + > if HAVE_SANLOCK > lockdriverdir = $(libdir)/libvirt/lock-driver > lockdriver_LTLIBRARIES = sanlock.la > @@ -1745,7 +1822,11 @@ endif > endif > EXTRA_DIST += $(SECURITY_DRIVER_APPARMOR_HELPER_SOURCES) > > -install-data-local: > +install-data-local: install-init > +if WITH_LIBVIRTD > + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/lockd" > + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/lockd" > +endif > $(MKDIR_P) "$(DESTDIR)$(localstatedir)/cache/libvirt" > $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/images" > $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/filesystems" > @@ -1794,7 +1875,11 @@ if WITH_NETWORK > $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart/default.xml > endif > > -uninstall-local:: > +uninstall-local:: uninstall-init > +if WITH_LIBVIRTD > + rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/lockd" ||: > + rmdir "$(DESTDIR)$(localstatedir)/run/libvirt/lockd" ||: > +endif > rmdir "$(DESTDIR)$(localstatedir)/cache/libvirt" ||: > rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/images" ||: > rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt/filesystems" ||: > diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c > new file mode 100644 > index 0000000..f821d2e > --- /dev/null > +++ b/src/locking/lock_daemon.c > @@ -0,0 +1,850 @@ > +/* > + * lock_daemon.c: lock management daemon > + * > + * Copyright (C) 2006-2012 Red Hat, Inc. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; If not, see > + * <http://www.gnu.org/licenses/>. > + * > + * Author: Daniel P. Berrange <berrange@xxxxxxxxxx> > + */ > + > +#include <config.h> > + > +#include <unistd.h> > +#include <fcntl.h> > +#include <sys/wait.h> > +#include <sys/stat.h> > +#include <getopt.h> > +#include <stdlib.h> > +#include <locale.h> > + > + > +#include "lock_daemon.h" > +#include "lock_daemon_config.h" > +#include "util.h" > +#include "virfile.h" > +#include "virpidfile.h" > +#include "virterror_internal.h" > +#include "logging.h" > +#include "memory.h" > +#include "conf.h" > +#include "rpc/virnetserver.h" > +#include "virrandom.h" > +#include "virhash.h" You may want to sort these so we don't introduce yet another file which needs sorting - assuming we will stick to your idea of sorting header files include after the release. > + > +#include "configmake.h" > + > +#define VIR_FROM_THIS VIR_FROM_LOCKING > + > +struct _virLockDaemon { > + virMutex lock; > + virNetServerPtr srv; > +}; > + > +virLockDaemonPtr lockDaemon = NULL; > + > +enum { > + VIR_LOCK_DAEMON_ERR_NONE = 0, > + VIR_LOCK_DAEMON_ERR_PIDFILE, > + VIR_LOCK_DAEMON_ERR_RUNDIR, > + VIR_LOCK_DAEMON_ERR_INIT, > + VIR_LOCK_DAEMON_ERR_SIGNAL, > + VIR_LOCK_DAEMON_ERR_PRIVS, > + VIR_LOCK_DAEMON_ERR_NETWORK, > + VIR_LOCK_DAEMON_ERR_CONFIG, > + VIR_LOCK_DAEMON_ERR_HOOKS, > + > + VIR_LOCK_DAEMON_ERR_LAST > +}; > + > +VIR_ENUM_DECL(virDaemonErr) > +VIR_ENUM_IMPL(virDaemonErr, VIR_LOCK_DAEMON_ERR_LAST, > + "Initialization successful", > + "Unable to obtain pidfile", > + "Unable to create rundir", > + "Unable to initialize libvirt", > + "Unable to setup signal handlers", > + "Unable to drop privileges", > + "Unable to initialize network sockets", > + "Unable to load configuration file", > + "Unable to look for hook scripts"); > + > +static void * > +virLockDaemonClientNew(virNetServerClientPtr client, > + void *opaque); > +static void > +virLockDaemonClientFree(void *opaque); > + > +static void > +virLockDaemonFree(virLockDaemonPtr lockd) > +{ > + if (!lockd) > + return; > + > + virObjectUnref(lockd->srv); > + > + VIR_FREE(lockd); > +} > + > + > +static virLockDaemonPtr > +virLockDaemonNew(bool privileged) > +{ > + virLockDaemonPtr lockd; > + > + if (VIR_ALLOC(lockd) < 0) { > + virReportOOMError(); > + return NULL; > + } > + > + if (virMutexInit(&lockd->lock) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Unable to initialize mutex")); > + VIR_FREE(lockd); > + return NULL; > + } > + > + if (!(lockd->srv = virNetServerNew(1, 1, 0, 20, > + -1, 0, > + false, NULL, > + virLockDaemonClientNew, > + NULL, > + virLockDaemonClientFree, > + (void*)(intptr_t)(privileged ? 0x1 : 0x0)))) > + goto error; > + > + return lockd; > + > +error: > + virLockDaemonFree(lockd); > + return NULL; > +} > + > + > +static int > +virLockDaemonForkIntoBackground(const char *argv0) > +{ > + int statuspipe[2]; > + if (pipe(statuspipe) < 0) > + return -1; > + > + pid_t pid = fork(); > + switch (pid) { > + case 0: > + { > + int stdinfd = -1; > + int stdoutfd = -1; > + int nextpid; > + > + VIR_FORCE_CLOSE(statuspipe[0]); > + > + if ((stdinfd = open("/dev/null", O_RDONLY)) < 0) > + goto cleanup; > + if ((stdoutfd = open("/dev/null", O_WRONLY)) < 0) > + goto cleanup; > + if (dup2(stdinfd, STDIN_FILENO) != STDIN_FILENO) > + goto cleanup; > + if (dup2(stdoutfd, STDOUT_FILENO) != STDOUT_FILENO) > + goto cleanup; > + if (dup2(stdoutfd, STDERR_FILENO) != STDERR_FILENO) > + goto cleanup; > + if (VIR_CLOSE(stdinfd) < 0) > + goto cleanup; > + if (VIR_CLOSE(stdoutfd) < 0) > + goto cleanup; > + > + if (setsid() < 0) > + goto cleanup; > + > + nextpid = fork(); > + switch (nextpid) { > + case 0: > + return statuspipe[1]; > + case -1: > + return -1; > + default: > + _exit(0); > + } > + > + cleanup: > + VIR_FORCE_CLOSE(stdoutfd); > + VIR_FORCE_CLOSE(stdinfd); > + return -1; > + > + } > + > + case -1: > + return -1; > + > + default: > + { > + int got, exitstatus = 0; > + int ret; > + char status; > + > + VIR_FORCE_CLOSE(statuspipe[1]); > + > + /* We wait to make sure the first child forked successfully */ > + if ((got = waitpid(pid, &exitstatus, 0)) < 0 || > + got != pid || > + exitstatus != 0) { > + return -1; > + } > + > + /* Now block until the second child initializes successfully */ > + again: > + ret = read(statuspipe[0], &status, 1); > + if (ret == -1 && errno == EINTR) > + goto again; > + > + if (ret == 1 && status != 0) { > + fprintf(stderr, > + _("%s: error: %s. Check /var/log/messages or run without " > + "--daemon for more info.\n"), argv0, > + virDaemonErrTypeToString(status)); > + } > + _exit(ret == 1 && status == 0 ? 0 : 1); > + } > + } > +} This is basically a copy-paste of daemonForkIntoBackground(). I wonder if we can use (modified) version of it instead of this. > + > + > +static int > +virLockDaemonPidFilePath(bool privileged, > + char **pidfile) > +{ > + if (privileged) { > + if (!(*pidfile = strdup(LOCALSTATEDIR "/run/virtlockd.pid"))) > + goto no_memory; > + } else { > + char *rundir = NULL; > + mode_t old_umask; > + > + if (!(rundir = virGetUserRuntimeDirectory())) > + goto error; > + > + old_umask = umask(077); > + if (virFileMakePath(rundir) < 0) { > + umask(old_umask); > + goto error; > + } > + umask(old_umask); > + > + if (virAsprintf(pidfile, "%s/virtlockd.pid", rundir) < 0) { > + VIR_FREE(rundir); > + goto no_memory; > + } > + > + VIR_FREE(rundir); > + } > + > + return 0; > + > +no_memory: > + virReportOOMError(); > +error: > + return -1; > +} > + > + > +static int > +virLockDaemonUnixSocketPaths(bool privileged, > + char **sockfile) > +{ > + if (privileged) { > + if (!(*sockfile = strdup(LOCALSTATEDIR "/run/libvirt/virtlockd-sock"))) > + goto no_memory; > + } else { > + char *rundir = NULL; > + mode_t old_umask; > + > + if (!(rundir = virGetUserRuntimeDirectory())) > + goto error; > + > + old_umask = umask(077); > + if (virFileMakePath(rundir) < 0) { > + umask(old_umask); > + goto error; > + } > + umask(old_umask); > + > + if (virAsprintf(sockfile, "%s/virtlockd-sock", rundir) < 0) { > + VIR_FREE(rundir); > + goto no_memory; > + } > + > + VIR_FREE(rundir); > + } > + return 0; > + > +no_memory: > + virReportOOMError(); > +error: > + return -1; > +} > + > + > +static void > +virLockDaemonErrorHandler(void *opaque ATTRIBUTE_UNUSED, > + virErrorPtr err ATTRIBUTE_UNUSED) > +{ > + /* Don't do anything, since logging infrastructure already > + * took care of reporting the error */ > +} > + > + > +/* > + * Set up the logging environment > + * By default if daemonized all errors go to the logfile libvirtd.log, > + * but if verbose or error debugging is asked for then also output > + * informational and debug messages. Default size if 64 kB. > + */ > +static int > +virLockDaemonSetupLogging(virLockDaemonConfigPtr config, > + bool privileged, > + bool verbose, > + bool godaemon) > +{ > + virLogReset(); > + > + /* > + * Libvirtd's order of precedence is: > + * cmdline > environment > config > + * > + * In order to achieve this, we must process configuration in > + * different order for the log level versus the filters and > + * outputs. Because filters and outputs append, we have to look at > + * the environment first and then only check the config file if > + * there was no result from the environment. The default output is > + * then applied only if there was no setting from either of the > + * first two. Because we don't have a way to determine if the log > + * level has been set, we must process variables in the opposite > + * order, each one overriding the previous. > + */ > + if (config->log_level != 0) > + virLogSetDefaultPriority(config->log_level); > + > + virLogSetFromEnv(); > + > + virLogSetBufferSize(config->log_buffer_size); > + > + if (virLogGetNbFilters() == 0) > + virLogParseFilters(config->log_filters); > + > + if (virLogGetNbOutputs() == 0) > + virLogParseOutputs(config->log_outputs); > + > + /* > + * If no defined outputs, and either running > + * as daemon or not on a tty, then first try > + * to direct it to the systemd journal > + * (if it exists).... > + */ > + if (virLogGetNbOutputs() == 0 && > + (godaemon || !isatty(STDIN_FILENO))) { > + char *tmp; > + if (access("/run/systemd/journal/socket", W_OK) >= 0) { > + if (virAsprintf(&tmp, "%d:journald", virLogGetDefaultPriority()) < 0) > + goto no_memory; > + virLogParseOutputs(tmp); > + VIR_FREE(tmp); > + } > + } > + > + /* > + * otherwise direct to libvirtd.log when running > + * as daemon. Otherwise the default output is stderr. > + */ > + if (virLogGetNbOutputs() == 0) { > + char *tmp = NULL; > + > + if (godaemon) { > + if (privileged) { > + if (virAsprintf(&tmp, "%d:file:%s/log/libvirt/virtlockd.log", > + virLogGetDefaultPriority(), > + LOCALSTATEDIR) == -1) > + goto no_memory; > + } else { > + char *logdir = virGetUserCacheDirectory(); > + mode_t old_umask; > + > + if (!logdir) > + goto error; > + > + old_umask = umask(077); > + if (virFileMakePath(logdir) < 0) { > + umask(old_umask); > + goto error; > + } > + umask(old_umask); > + > + if (virAsprintf(&tmp, "%d:file:%s/virtlockd.log", > + virLogGetDefaultPriority(), logdir) == -1) { > + VIR_FREE(logdir); > + goto no_memory; > + } > + VIR_FREE(logdir); > + } > + } else { > + if (virAsprintf(&tmp, "%d:stderr", virLogGetDefaultPriority()) < 0) > + goto no_memory; > + } > + virLogParseOutputs(tmp); > + VIR_FREE(tmp); > + } > + > + /* > + * Command line override for --verbose > + */ > + if ((verbose) && (virLogGetDefaultPriority() > VIR_LOG_INFO)) > + virLogSetDefaultPriority(VIR_LOG_INFO); > + > + return 0; > + > +no_memory: > + virReportOOMError(); > +error: > + return -1; > +} Same here. This one is even closer to daemonSetupLogging() > + > + > + > +/* Display version information. */ > +static void > +virLockDaemonVersion(const char *argv0) > +{ > + printf("%s (%s) %s\n", argv0, PACKAGE_NAME, PACKAGE_VERSION); > +} > + > +static void > +virLockDaemonShutdownHandler(virNetServerPtr srv, > + siginfo_t *sig ATTRIBUTE_UNUSED, > + void *opaque ATTRIBUTE_UNUSED) > +{ > + virNetServerQuit(srv); > +} > + > +static int > +virLockDaemonSetupSignals(virNetServerPtr srv) > +{ > + if (virNetServerAddSignalHandler(srv, SIGINT, virLockDaemonShutdownHandler, NULL) < 0) > + return -1; > + if (virNetServerAddSignalHandler(srv, SIGQUIT, virLockDaemonShutdownHandler, NULL) < 0) > + return -1; > + if (virNetServerAddSignalHandler(srv, SIGTERM, virLockDaemonShutdownHandler, NULL) < 0) > + return -1; > + return 0; > +} > + > +static int > +virLockDaemonSetupNetworking(virNetServerPtr srv, const char *sock_path) > +{ > + virNetServerServicePtr svc; > + > + VIR_DEBUG("Setting up networking natively"); > + > + if (!(svc = virNetServerServiceNewUNIX(sock_path, 0700, 0, 0, false, 1, NULL))) > + return -1; > + > + if (virNetServerAddService(srv, svc, NULL) < 0) { > + virObjectUnref(svc); > + return -1; > + } > + return 0; > +} > + > + > +static void > +virLockDaemonClientFree(void *opaque) > +{ > + virLockDaemonClientPtr priv = opaque; > + > + if (!priv) > + return; > + > + VIR_DEBUG("priv=%p client=%lld", > + priv, > + (unsigned long long)priv->clientPid); > + > + virMutexDestroy(&priv->lock); > + VIR_FREE(priv); > +} > + > + > +static void * > +virLockDaemonClientNew(virNetServerClientPtr client, > + void *opaque) > +{ > + virLockDaemonClientPtr priv; > + uid_t clientuid; > + gid_t clientgid; > + bool privileged = opaque != NULL; > + > + if (VIR_ALLOC(priv) < 0) { > + virReportOOMError(); > + return NULL; > + } > + > + if (virMutexInit(&priv->lock) < 0) { > + VIR_FREE(priv); > + virReportOOMError(); > + return NULL; > + } > + > + if (virNetServerClientGetUNIXIdentity(client, > + &clientuid, > + &clientgid, > + &priv->clientPid) < 0) > + goto error; > + > + VIR_DEBUG("New client pid %llu uid %llu", > + (unsigned long long)priv->clientPid, > + (unsigned long long)clientuid); > + > + if (!privileged) { > + if (geteuid() != clientuid) { > + virReportError(VIR_ERR_OPERATION_DENIED, > + _("Disallowing client %llu with uid %llu"), > + (unsigned long long)priv->clientPid, > + (unsigned long long)clientuid); > + goto error; > + } > + } else { > + if (clientuid != 0) { > + virReportError(VIR_ERR_OPERATION_DENIED, > + _("Disallowing client %llu with uid %llu"), > + (unsigned long long)priv->clientPid, > + (unsigned long long)clientuid); > + goto error; > + } > + } > + > + return priv; > + > +error: > + virMutexDestroy(&priv->lock); > + VIR_FREE(priv); > + return NULL; > +} > + > + > +static void > +virLockDaemonUsage(const char *argv0, bool privileged) > +{ > + fprintf(stderr, > + _("\n" > + "Usage:\n" > + " %s [options]\n" > + "\n" > + "Options:\n" > + " -v | --verbose Verbose messages.\n" > + " -d | --daemon Run as a daemon & write PID file.\n" > + " -t | --timeout <secs> Exit after timeout period.\n" > + " -f | --config <file> Configuration file.\n" > + " | --version Display version information.\n" > + " -p | --pid-file <file> Change name of PID file.\n" > + "\n" > + "libvirt lock management daemon:\n"), argv0); > + > + if (privileged) { > + fprintf(stderr, > + _("\n" > + " Default paths:\n" > + "\n" > + " Configuration file (unless overridden by -f):\n" > + " %s/libvirt/virtlockd.conf\n" > + "\n" > + " Sockets:\n" > + " %s/run/libvirt/virtlockd-sock\n" > + "\n" > + " PID file (unless overridden by -p):\n" > + " %s/run/virtlockd.pid\n" > + "\n"), > + SYSCONFDIR, > + LOCALSTATEDIR, > + LOCALSTATEDIR); > + } else { > + fprintf(stderr, > + "%s", _("\n" > + " Default paths:\n" > + "\n" > + " Configuration file (unless overridden by -f):\n" > + " $XDG_CONFIG_HOME/libvirt/virtlockd.conf\n" > + "\n" > + " Sockets:\n" > + " $XDG_RUNTIME_DIR/libvirt/virtlockd-sock\n" > + "\n" > + " PID file:\n" > + " $XDG_RUNTIME_DIR/libvirt/virtlockd.pid\n" > + "\n")); just a small nit, if you'd move "%s" to the previous line, this and the previous blocks would be perfectly aligned. > + } > +} > + > +enum { > + OPT_VERSION = 129 > +}; > + > +#define MAX_LISTEN 5 > +int main(int argc, char **argv) { > + char *remote_config_file = NULL; > + int statuswrite = -1; > + int ret = 1; > + int verbose = 0; > + int godaemon = 0; > + int timeout = 0; timeout seems dummy to me. ACK if you either remove it or (more likely) implement it. -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list