diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index 47f0722967..7f72f68da9 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -40,6 +40,7 @@ #include #include #include +#include #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 +#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;