cxenstored: add support for systemd active sockets

This adds systemd socket activation support for the C xenstored.
Active sockets enable xenstored to be loaded only if required by a system
onto which Xen is installed on. Socket activation is handled by
systemd, once a port for a service which claims a socket is used
systemd will start the required services for it, on demand. For more
details on socket activation refer to Lennart's socket-activation
post regarding this [0].

Right now this code adds a no-op for this functionality, leaving the
enablement to be done later once systemd is properly hooked into
the build system. The socket activation is ordered in aligment with
the socket activation order passed on to systemd.

[0] http://0pointer.de/blog/projects/socket-activation2.html

Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
Luis R. Rodriguez authored and Ian Campbell committed 2014-07-24 16:23:20 +01:00
1 parent d4b137f409
commit 5e82217e34
1 file changed
+103 -1
+103 -1
View File
@@ -40,6 +40,7 @@
#include <signal.h>
#include <assert.h>
#include <setjmp.h>
#include <config.h>
#include "utils.h"
#include "list.h"
@@ -54,6 +55,16 @@
#include "hashtable.h"
#ifndef NO_SOCKETS
#if defined(HAVE_SYSTEMD)
#define XEN_SYSTEMD_ENABLED 1
#endif
#endif
#if defined(XEN_SYSTEMD_ENABLED)
#include <systemd/sd-daemon.h>
#endif
extern xc_evtchn *xce_handle; /* in xenstored_domain.c */
static int xce_pollfd_idx = -1;
static struct pollfd *fds;
@@ -1714,6 +1725,75 @@ static int destroy_fd(void *_fd)
return 0;
}
#if defined(XEN_SYSTEMD_ENABLED)
/* Will work regardless of the order systemd gives them to us */
static int xs_get_sd_fd(const char *connect_to)
{
int fd = SD_LISTEN_FDS_START;
int r;
while (fd <= SD_LISTEN_FDS_START + 1) {
r = sd_is_socket_unix(fd, SOCK_STREAM, 1, connect_to, 0);
if (r > 0)
return fd;
fd++;
}
return -EBADR;
}
static int xs_validate_active_socket(const char *connect_to)
{
if ((strcmp("/var/run/xenstored/socket_ro", connect_to) != 0) &&
(strcmp("/var/run/xenstored/socket", connect_to) != 0)) {
sd_notifyf(0, "STATUS=unexpected socket: %s\n"
"ERRNO=%i",
connect_to,
EBADR);
return -EBADR;
}
return xs_get_sd_fd(connect_to);
}
static void xen_claim_active_sockets(int **psock, int **pro_sock)
{
int *sock, *ro_sock;
const char *soc_str = xs_daemon_socket();
const char *soc_str_ro = xs_daemon_socket_ro();
int n;
n = sd_listen_fds(0);
if (n <= 0) {
sd_notifyf(0, "STATUS=Failed to get any active sockets: %s\n"
"ERRNO=%i",
strerror(errno),
errno);
barf_perror("sd_listen_fds() failed\n");
} else if (n > 2) {
fprintf(stderr, SD_ERR "Expected 2 fds but given %d\n", n);
sd_notifyf(0, "STATUS=Mismatch on number (2): %s\n"
"ERRNO=%d",
strerror(EBADR),
EBADR);
barf_perror("sd_listen_fds() gave too many fds\n");
}
*psock = sock = talloc(talloc_autofree_context(), int);
*sock = xs_validate_active_socket(soc_str);
if (*sock <= 0)
barf_perror("%s", soc_str);
*pro_sock = ro_sock = talloc(talloc_autofree_context(), int);
*ro_sock = xs_validate_active_socket(soc_str_ro);
if (*ro_sock <= 0)
barf_perror("%s", soc_str_ro);
talloc_set_destructor(sock, destroy_fd);
talloc_set_destructor(ro_sock, destroy_fd);
}
#endif
static void init_sockets(int **psock, int **pro_sock)
{
struct sockaddr_un addr;
@@ -1884,6 +1964,15 @@ int main(int argc, char *argv[])
if (optind != argc)
barf("%s: No arguments desired", argv[0]);
#if defined(XEN_SYSTEMD_ENABLED)
if (sd_booted()) {
dofork = false;
if (pidfile)
barf("%s: PID file not needed on systemd", argv[0]);
pidfile = NULL;
}
#endif
reopen_log();
/* make sure xenstored directories exist */
@@ -1905,7 +1994,13 @@ int main(int argc, char *argv[])
/* Don't kill us with SIGPIPE. */
signal(SIGPIPE, SIG_IGN);
init_sockets(&sock, &ro_sock);
#if defined(XEN_SYSTEMD_ENABLED)
if (sd_booted())
xen_claim_active_sockets(&sock, &ro_sock);
else
#endif
init_sockets(&sock, &ro_sock);
init_pipe(reopen_log_pipe);
/* Setup the database */
@@ -1936,6 +2031,13 @@ int main(int argc, char *argv[])
/* Tell the kernel we're up and running. */
xenbus_notify_running();
#if defined(XEN_SYSTEMD_ENABLED)
if (sd_booted()) {
sd_notify(1, "READY=1");
fprintf(stderr, SD_NOTICE "xenstored is ready\n");
}
#endif
/* Main loop. */
for (;;) {
struct connection *conn, *next;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.