xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
To: xen-devel@lists.xenproject.org
Cc: "Luis R. Rodriguez" <mcgrof@suse.com>
Subject: [PATCH v5 02/14] libxenstore.so: add support for systemd
Date: Tue, 20 May 2014 05:31:23 -0700	[thread overview]
Message-ID: <1400589095-3872-3-git-send-email-mcgrof@do-not-panic.com> (raw)
In-Reply-To: <1400589095-3872-1-git-send-email-mcgrof@do-not-panic.com>

From: "Luis R. Rodriguez" <mcgrof@suse.com>

This adds support for systemd into libxenstore.so to enable usage
through cxenstored and oxenstored. The way we provide support for
systemd is to *not* compile systemd with -lsystemd-daemon but instead
to look for libsystemd-daemon.so at run time if the binary was compiled
with support for systemd. Before using systemd though we check if the
system was booted with systemd as the init process by using sd_booted()
and only if this is true will we assume that's the only mechanism
allowed. For systems that do not have systemd present or that have systemd
libraries present but did not boot with systemd the old init unix socket
creation mechanism will be used.

Systems that do not use unix sockets at all will continue to chug on as
they used to skipping all this unix socket actication and relying on the
kernel ring interface, used for exampl when CONFIG_STUBDOM=y which sets
CFLAGS += -DNO_SOCKETS=1 on tools/xenstore/Makefile and also by the
oxenstored --disable_socket run time flag.

This enables Linux distributions to ship and support one binary for both
systemd and non-systemd type of environments.

Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
---
 tools/xenstore/Makefile     |   7 +-
 tools/xenstore/xenstore.h   |  11 ++
 tools/xenstore/xs_systemd.c | 321 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 337 insertions(+), 2 deletions(-)
 create mode 100644 tools/xenstore/xs_systemd.c

diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index 55ca7a3..c361d84 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -9,10 +9,13 @@ CFLAGS += -I.
 CFLAGS += -I$(XEN_ROOT)/tools/
 CFLAGS += $(CFLAGS_libxenctrl)
 
+LDFLAGS += -ldl -rdynamic
+
 CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm xenstore-chmod
 CLIENTS += xenstore-write xenstore-ls xenstore-watch
 
 XENSTORED_OBJS = xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o tdb.o hashtable.o
+XENSTORED_OBJS += xs_systemd.o
 
 XENSTORED_OBJS_$(CONFIG_Linux) = xenstored_linux.o xenstored_posix.o
 XENSTORED_OBJS_$(CONFIG_SunOS) = xenstored_solaris.o xenstored_posix.o xenstored_probes.o
@@ -86,10 +89,10 @@ libxenstore.so.$(MAJOR): libxenstore.so.$(MAJOR).$(MINOR)
 
 xs.opic: CFLAGS += -DUSE_PTHREAD
 
-libxenstore.so.$(MAJOR).$(MINOR): xs.opic xs_lib.opic
+libxenstore.so.$(MAJOR).$(MINOR): xs.opic xs_lib.opic xs_systemd.opic
 	$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenstore.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(SOCKET_LIBS) -lpthread $(APPEND_LDFLAGS)
 
-libxenstore.a: xs.o xs_lib.o
+libxenstore.a: xs.o xs_lib.o xs_systemd.o
 	$(AR) rcs $@ $^
 
 .PHONY: clean
diff --git a/tools/xenstore/xenstore.h b/tools/xenstore/xenstore.h
index fdf5e76..11daee4 100644
--- a/tools/xenstore/xenstore.h
+++ b/tools/xenstore/xenstore.h
@@ -49,6 +49,7 @@
 #define XS_UNWATCH_FILTER     1UL<<2
 
 struct xs_handle;
+struct xs_sd_ctx;
 typedef uint32_t xs_transaction_t;
 
 /* IMPORTANT: For details on xenstore protocol limits, see
@@ -244,6 +245,16 @@ char *xs_debug_command(struct xs_handle *h, const char *cmd,
 		       void *data, unsigned int len);
 
 int xs_suspend_evtchn_port(int domid);
+
+struct xs_sd_ctx *xs_get_sd_ctx(void);
+void xs_free_sd_ctx(struct xs_sd_ctx *ctx);
+
+bool xs_load_sd_required(struct xs_sd_ctx *ctx);
+
+int xs_claim_active_socket(struct xs_sd_ctx *ctx, const char *connect_to);
+
+int xs_sd_notify_ready(struct xs_sd_ctx *ctx);
+
 #endif /* XENSTORE_H */
 
 /*
diff --git a/tools/xenstore/xs_systemd.c b/tools/xenstore/xs_systemd.c
new file mode 100644
index 0000000..814e0fc
--- /dev/null
+++ b/tools/xenstore/xs_systemd.c
@@ -0,0 +1,321 @@
+/*
+    xenstored shared interface
+    Copyright (C) 2014 Luis R. Rodriguez <mcgrof@suse.com>
+
+    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, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <stdio.h>
+#include <errno.h>
+#include <config.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>
+#include <dlfcn.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(ar) (sizeof(ar)/sizeof(ar[0]))
+#endif
+
+/*
+ * Xen supports both systemd and old init style initialization. Xen supports
+ * distributions to ship only one binary to support both systemd and non
+ * systemd systems. We accomplish this by not requiring to link libxenstore.so
+ * with -lsystemd-daemon at compile time but instead having libxenstore.so
+ * ask for libsystemd-daemon.so through run time. Furthremore even if
+ * libsystemd-daemon.so is present it does not mean that a system was booted
+ * with systemd as its init system so we check sd_booted() before assuming
+ * the goal was to require systemd. In a system that did not boot with systemd
+ * as its init daemon but has libsystemd-daemon.so available we'll only require
+ * sd_booted() to verify if init is systemd. Below we explain a bit further how
+ * we accomplish runtime loading of systemd libraries in a portable way.
+ *
+ * dlsym() returns a void pointer, however a void pointer is not required
+ * to even have the same size as an object pointer, and therefore a valid
+ * conversion between type void* and a pointer to a function may not exist
+ * on all platforms. You also may end up with strict-aliasing complaints, so
+ * we use a union. For more details refer to:
+ *
+ * http://en.wikipedia.org/wiki/Dynamic_loading#UNIX_.28POSIX.29
+ *
+ * The strategy taken here is to use a builder for initial assignment
+ * to address issues with different systems with a range of known
+ * expected routines from the library, by usng a macro helper we with
+ * a builder we can enforce only assignment to expected routines from
+ * the library.
+ *
+ * In order to avoid a sloppy union access we upkeep on our own xen
+ * data structure the actual callbacks that we know exist, and leave
+ * the void union trick only for the builder, this requires defining the
+ * expected routines twice, on the builder and our own cached copy of
+ * the symbol dereferences.
+ */
+
+#define XEN_SYSTEMD_FUNCS										\
+	int (*sd_booted)(void);										\
+	int (*sd_listen_fds)(int unset_environment);							\
+	int (*sd_is_fifo)(int fd, const char *path);							\
+	int (*sd_is_socket)(int fd, int family, int type, int listening);				\
+	int (*sd_is_socket_inet)(int fd, int family, int type, int listening, uint16_t port);		\
+	int (*sd_is_socket_unix)(int fd, int type, int listening, const char* path, size_t length);	\
+	int (*sd_is_mq)(int fd, const char *path);							\
+	int (*sd_notify)(int unset_environment, const char *state);					\
+	int (*sd_notifyf)(int unset_environment, const char *format, ...);
+
+union u_sd_funcs {
+	void *f;
+	XEN_SYSTEMD_FUNCS
+};
+
+struct xs_sd_ctx {
+	void *handle;
+	XEN_SYSTEMD_FUNCS
+};
+
+#define xen_load_sd_func(__xs_sd_lib, __libfunc, __builder) do { 		\
+	__builder.f = NULL;						\
+	__builder.f = dlsym(__xs_sd_lib->handle, #__libfunc);		\
+	if (!__builder.f)						\
+		return false;						\
+	__xs_sd_lib->__libfunc = builder.__libfunc;			\
+} while (0)
+
+struct xs_sd_ctx *xs_get_sd_ctx(void)
+{
+	struct xs_sd_ctx *ctx;
+	ctx = malloc(sizeof(struct xs_sd_ctx));
+	if (!ctx)
+		return NULL;
+	memset(ctx, 0, sizeof(struct xs_sd_ctx));
+	return ctx;
+}
+
+void xs_free_sd_ctx(struct xs_sd_ctx *ctx)
+{
+	if (!ctx)
+		return;
+	free(ctx);
+}
+
+bool xs_load_sd_required(struct xs_sd_ctx *ctx)
+{
+	union u_sd_funcs builder;
+
+	if (!ctx)
+		return false;
+
+	memset(&builder, 0, sizeof(union u_sd_funcs));
+
+	ctx->handle = dlopen("libsystemd-daemon.so", RTLD_LAZY);
+	if (!ctx->handle)
+		return false;
+
+	xen_load_sd_func(ctx, sd_booted, builder);
+
+	if (!ctx->sd_booted())
+		return false;
+
+	xen_load_sd_func(ctx, sd_listen_fds, builder);
+	xen_load_sd_func(ctx, sd_is_socket_unix, builder);
+	xen_load_sd_func(ctx, sd_notify, builder);
+	xen_load_sd_func(ctx, sd_notifyf, builder);
+
+	return true;
+}
+
+/* Conforms to what we should send sd_is_socket_unix() but we add mode */
+struct xen_systemd_active_socket {
+	int fd;
+	int type;
+	int listening;
+	const char *path;
+	int mode;
+	size_t length;
+};
+
+/*
+ * We list stdin, stdout and stderr simply for documentation purposes
+ * and to help our array size fit the number of expected sockets we
+ * as sd_listen_fds() will return 5 for example if you set the socket
+ * service with 2 sockets.
+ */
+static const struct xen_systemd_active_socket xenstore_active_sockets[] = {
+	{
+		.fd = SD_LISTEN_FDS_START -3,
+		.type = 0,
+		.listening = 0,
+		.path = "stdin",
+		.mode = 0600,
+		.length = 0,
+	},
+	{
+		.fd = SD_LISTEN_FDS_START - 2,
+		.type = 0,
+		.listening = 0,
+		.path = "stderr",
+		.mode = 0600,
+		.length = 0,
+	},
+	{
+		.fd = SD_LISTEN_FDS_START - 1,
+		.type = 0,
+		.listening = 0,
+		.path = "stderr",
+		.mode = 0600,
+		.length = 0,
+	},
+	{
+		.fd = SD_LISTEN_FDS_START,
+		.type = SOCK_STREAM,
+		.listening = -1,
+		.path = "/var/run/xenstored/socket",
+		.mode = 0600,
+		.length = 0,
+	},
+	{
+		.fd = SD_LISTEN_FDS_START + 1,
+		.type = SOCK_STREAM,
+		.listening = -1,
+		.path = "/var/run/xenstored/socket_ro",
+		.mode = 0660,
+		.length = 0,
+	},
+};
+
+static const struct xen_systemd_active_socket *get_xen_active_socket(const char *connect_to)
+{
+	unsigned int i;
+
+	for (i=0; i<ARRAY_SIZE(xenstore_active_sockets); i++) {
+		if (!strcmp(connect_to, xenstore_active_sockets[i].path)) {
+			if (!xenstore_active_sockets[i].type)
+				return NULL;
+			return &xenstore_active_sockets[i];
+		}
+	}
+
+	return NULL;
+}
+
+int xs_claim_active_socket(struct xs_sd_ctx *ctx, const char *connect_to)
+{
+	int n, r;
+	const struct xen_systemd_active_socket *active_socket;
+
+	if (!ctx)
+		return -EINVAL;
+
+	if (!ctx->sd_listen_fds)
+		return -EINVAL;
+
+	if (!ctx->sd_is_socket_unix)
+		return -EINVAL;
+
+	active_socket = get_xen_active_socket(connect_to);
+	if (!active_socket)
+		return -EINVAL;
+
+	n = ctx->sd_listen_fds(0);
+	if (n <= 0) {
+		ctx->sd_notifyf(0, "STATUS=Failed to get any active sockets: %s\n"
+				"ERRNO=%i",
+				strerror(errno),
+				errno);
+		return -errno;
+	} else if (n >= (ARRAY_SIZE(xenstore_active_sockets))) {
+		fprintf(stderr, SD_ERR "Expected %d fds but given %d\n",
+			(int) ARRAY_SIZE(xenstore_active_sockets)-1,
+			n);
+		ctx->sd_notifyf(0, "STATUS=Mismatch on number (%d): %s\n"
+				"ERRNO=%d",
+				(int) ARRAY_SIZE(xenstore_active_sockets),
+				strerror(EBADR),
+				EBADR);
+		return -EBADR;
+	}
+
+	r = ctx->sd_is_socket_unix(active_socket->fd,
+				   active_socket->type,
+				   active_socket->listening,
+				   active_socket->path,
+				   active_socket->length);
+	if (r <= 0)
+		return -EBADR;
+
+	r = chmod(active_socket->path, active_socket->mode);
+	if (r != 0)
+		return -errno;
+
+	fprintf(stderr, SD_NOTICE "%s socket claimed\n", active_socket->path);
+
+	return active_socket->fd;
+}
+
+void xs_sd_notify_ready(struct xs_sd_ctx *ctx)
+{
+	if (!ctx)
+		return;
+
+	ctx->sd_notify(1, "READY=1");
+	fprintf(stderr, SD_NOTICE "xenstored is ready\n");
+}
+#else
+
+struct xs_sd_ctx {
+	void *handle;
+};
+
+struct xs_sd_ctx *xs_get_sd_ctx(void)
+{
+	return NULL;
+}
+
+void xs_free_sd_ctx(struct xs_sd_ctx *ctx)
+{
+	return;
+}
+
+int xs_claim_active_socket(struct xs_sd_ctx *ctx, const char *connect_to)
+{
+	return -1;
+}
+
+bool xs_load_sd_required(struct xs_sd_ctx *ctx)
+{
+	return false;
+}
+
+void xs_sd_notify_ready(struct xs_sd_ctx *ctx)
+{
+	return;
+}
+#endif /* XEN_SYSTEMD */
-- 
2.0.0.rc3.18.g00a5b79

  parent reply	other threads:[~2014-05-20 12:31 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-20 12:31 [PATCH v5 00/14] xen: add systemd support Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 01/14] xenstored: enable usage of config.h on both xenstored and oxenstored Luis R. Rodriguez
2014-05-20 12:31 ` Luis R. Rodriguez [this message]
2014-05-21 14:35   ` [PATCH v5 02/14] libxenstore.so: add support for systemd Ian Campbell
2014-05-21 14:56     ` Ian Campbell
2014-05-21 16:32       ` Luis R. Rodriguez
2014-05-21 16:48         ` Ian Campbell
2014-05-21 17:15           ` Luis R. Rodriguez
2014-05-22  9:36             ` Ian Campbell
2014-05-22  9:59               ` Luis R. Rodriguez
2014-05-21 16:24     ` Luis R. Rodriguez
2014-05-21 16:39       ` Ian Campbell
2014-05-21 17:29         ` Luis R. Rodriguez
2014-05-22  9:39           ` Ian Campbell
2014-05-22 10:01             ` Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 03/14] cxenstored: add support for systemd active sockets Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 04/14] oxenstored: " Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 05/14] oxenstored: force FD_CLOEXEC with Unix.set_close_on_exec on LSB init Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 06/14] tools/xendomains: make xl the default Luis R. Rodriguez
2014-05-21 15:05   ` Ian Campbell
2014-05-21 17:29     ` Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 07/14] tools/xendomains: do space cleanups Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 08/14] tools/xendomains: move to libexec and use a smaller init helper Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 09/14] autoconf: xen: force a refresh with autoconf Luis R. Rodriguez
2014-05-21 15:07   ` Ian Campbell
2014-05-21 17:35     ` Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 10/14] autoconf: update m4/pkg.m4 Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 11/14] autoconf: xen: move standard variables to a generic place Luis R. Rodriguez
2014-05-20 13:37   ` Jan Beulich
     [not found]   ` <537B76D1020000780001422C@suse.com>
2014-05-20 17:54     ` Luis R. Rodriguez
2014-05-21  7:32       ` Jan Beulich
2014-05-21  8:03         ` Luis R. Rodriguez
2014-05-21  8:11           ` Jan Beulich
2014-05-21  8:27             ` Luis R. Rodriguez
2014-05-21 10:33             ` Ian Campbell
2014-05-21 13:54               ` Jan Beulich
2014-05-21 15:14               ` Ian Campbell
2014-05-21 15:20                 ` Jan Beulich
2014-05-21 15:26   ` Ian Campbell
2014-05-21 21:54     ` Luis R. Rodriguez
2014-05-22  9:46       ` Ian Campbell
2014-05-20 12:31 ` [PATCH v5 12/14] autoconf: xen: enable explicit preference option for xenstored preference Luis R. Rodriguez
2014-05-21 15:44   ` Ian Campbell
2014-05-21 23:02     ` Luis R. Rodriguez
2014-05-22 10:05       ` Ian Campbell
2014-05-23 23:20         ` Luis R. Rodriguez
2014-05-28  9:30           ` Ian Campbell
2014-05-29 16:09             ` Don Koch
2014-05-29 23:29             ` Luis R. Rodriguez
     [not found]             ` <20140529232918.GG26450@wotan.suse.de>
2014-06-01  6:15               ` [systemd-devel] " Lennart Poettering
     [not found]               ` <20140601061547.GC16257@tango.0pointer.de>
2014-06-05  0:31                 ` Luis R. Rodriguez
     [not found]                 ` <20140605003103.GB22052@wotan.suse.de>
2014-06-05  2:52                   ` Cameron Norman
2014-06-05 11:22                   ` Lennart Poettering
     [not found]                   ` <20140605112213.GA17673@tango.0pointer.de>
2014-06-05 18:01                     ` Luis R. Rodriguez
     [not found]                     ` <20140605180137.GD22052@wotan.suse.de>
2014-06-05 19:24                       ` Lennart Poettering
     [not found]                       ` <20140605192421.GA6248@tango.0pointer.de>
2014-06-05 19:26                         ` Andrew Lutomirski
     [not found]                   ` <CALZWFR+LQ3XK4RQ335CNqjr8zucWw4GieKwZS3N5m0w4yJXuBA@mail.gmail.com>
2014-06-10  1:15                     ` Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 13/14] xencommons: move module list into a generic place Luis R. Rodriguez
2014-05-20 13:40   ` Jan Beulich
     [not found]   ` <537B776D020000780001425E@suse.com>
2014-05-20 18:03     ` Luis R. Rodriguez
2014-05-20 12:31 ` [PATCH v5 14/14] systemd: add xen systemd service and module files Luis R. Rodriguez
2014-05-20 12:48   ` Luis R. Rodriguez

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1400589095-3872-3-git-send-email-mcgrof@do-not-panic.com \
    --to=mcgrof@do-not-panic.com \
    --cc=mcgrof@suse.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).