From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 12 Feb 2025 20:27:18 +0100 Subject: [PATCH] multipathd: allow receiving two socket fds from systemd Add another ListenStream directive in multipathd.socket for a Unix pathname socket. In multipathd, read both socket fds from systemd, and open both when they are defined. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski Signed-off-by: Benjamin Marzinski --- Makefile.inc | 3 ++- multipathd/main.c | 18 ++++++++++++------ multipathd/multipathd.socket.in | 3 ++- multipathd/uxlsnr.c | 33 ++++++++++++++++++++++----------- 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/Makefile.inc b/Makefile.inc index 1ef3f7f8..07c0ae80 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -76,6 +76,7 @@ libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr kernel_incdir := /usr/include abstract_socket := @/org/kernel/linux/storage/multipathd +pathname_socket := /run/multipathd.socket ifeq ($(V),) Q := @ @@ -166,4 +167,4 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version) %: %.in @echo creating $@ - $(Q)sed 's:@CONFIGFILE@:'$(TGTDIR)$(configfile)':g;s:@CONFIGDIR@:'$(TGTDIR)$(configdir)':g;s:@STATE_DIR@:'$(TGTDIR)$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g;s/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g;s:@BINDIR@:'$(bindir)':g;s,@MPATH_SOCKET@,'$(abstract_socket)',g' $< >$@ + $(Q)sed 's:@CONFIGFILE@:'$(TGTDIR)$(configfile)':g;s:@CONFIGDIR@:'$(TGTDIR)$(configdir)':g;s:@STATE_DIR@:'$(TGTDIR)$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g;s/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g;s:@BINDIR@:'$(bindir)':g;s,@ABSTRACT_SOCKET@,'$(abstract_socket)',g;s,@PATHNAME_SOCKET@,'$(pathname_socket)',g' $< >$@ diff --git a/multipathd/main.c b/multipathd/main.c index 9f15d2f7..2fef0c64 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -1865,9 +1865,13 @@ static int get_systemd_sockets(long *ux_sock) { int num = sd_listen_fds(0); - if (num > 1) { + if (num > 2) { condlog(3, "sd_listen_fds returned %d fds", num); return -1; + } else if (num == 2) { + ux_sock[0] = SD_LISTEN_FDS_START + 0; + ux_sock[1] = SD_LISTEN_FDS_START + 1; + condlog(3, "using fd %ld and %ld from sd_listen_fds", ux_sock[0], ux_sock[1]); } else if (num == 1) { ux_sock[0] = SD_LISTEN_FDS_START + 0; condlog(3, "using fd %ld from sd_listen_fds", ux_sock[0]); @@ -1885,16 +1889,18 @@ static int get_systemd_sockets(long *ux_sock __attribute__((unused))) static void * uxlsnrloop (void * ap) { - long ux_sock; + long ux_sock[2] = {-1, -1}; int num; pthread_cleanup_push(rcu_unregister, NULL); rcu_register_thread(); num = get_systemd_sockets(&ux_sock); - if (num < 1) - ux_sock = ux_socket_listen(DEFAULT_SOCKET); - if (ux_sock == -1) { + if (num < 1) { + ux_sock[0] = ux_socket_listen(DEFAULT_SOCKET); + num = 1; + } + if (ux_sock[0] == -1) { condlog(1, "could not create uxsock: %d", errno); exit_daemon(); goto out; @@ -1920,7 +1926,7 @@ uxlsnrloop (void * ap) == DAEMON_CONFIGURE) handle_signals(false); - uxsock_listen(1, &ux_sock, ap); + uxsock_listen(num, ux_sock, ap); out_sock: pthread_cleanup_pop(1); /* uxsock_cleanup */ diff --git a/multipathd/multipathd.socket.in b/multipathd/multipathd.socket.in index 4ed9c1ff..5ed24757 100644 --- a/multipathd/multipathd.socket.in +++ b/multipathd/multipathd.socket.in @@ -8,7 +8,8 @@ ConditionVirtualization=!container Before=sockets.target [Socket] -ListenStream=@MPATH_SOCKET@ +ListenStream=@ABSTRACT_SOCKET@ +ListenStream=@PATHNAME_SOCKET@ [Install] # Socket activation for multipathd is disabled by default. diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c index 51b5e51d..bbf891ba 100644 --- a/multipathd/uxlsnr.c +++ b/multipathd/uxlsnr.c @@ -69,7 +69,8 @@ struct client { /* Indices for array of poll fds */ enum { - POLLFD_UX = 0, + POLLFD_UX1 = 0, + POLLFD_UX2, POLLFD_NOTIFY, POLLFD_IDLE, POLLFDS_BASE, @@ -164,9 +165,10 @@ void uxsock_cleanup(void *arg) { struct client *client_loop; struct client *client_tmp; - long ux_sock = (long)arg; + long *ux_sock = (long *)arg; - close(ux_sock); + close(ux_sock[0]); + close(ux_sock[1]); close(notify_fd); list_for_each_entry_safe(client_loop, client_tmp, &clients, node) { @@ -614,20 +616,24 @@ static void handle_client(struct client *c, struct vectors *vecs, short revents) /* * entry point */ -void *uxsock_listen(int n_socks, long *ux_sock, void *trigger_data) +void *uxsock_listen(int n_socks, long *ux_sock_in, void *trigger_data) { sigset_t mask; int max_pfds = MIN_POLLS + POLLFDS_BASE; + long ux_sock[2] = {-1, -1}; /* conf->sequence_nr will be 1 when uxsock_listen is first called */ unsigned int sequence_nr = 0; struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1, .mp_wd = -1, }; struct vectors *vecs = trigger_data; - if (n_socks != 1) { - condlog(0, "uxsock: no socket fds"); + if (n_socks < 1 || n_socks > 2) { + condlog(0, "uxsock: unsupported number of socket fds"); exit_daemon(); return NULL; - } + } else if (n_socks == 2) + ux_sock[1] = ux_sock_in[1]; + ux_sock[0] = ux_sock_in[0]; + condlog(3, "uxsock: startup listener"); polls = calloc(1, max_pfds * sizeof(*polls)); if (!polls) { @@ -678,8 +684,10 @@ void *uxsock_listen(int n_socks, long *ux_sock, void *trigger_data) } } if (num_clients < MAX_CLIENTS) { - polls[POLLFD_UX].fd = ux_sock[0]; - polls[POLLFD_UX].events = POLLIN; + polls[POLLFD_UX1].fd = ux_sock[0]; + polls[POLLFD_UX1].events = POLLIN; + polls[POLLFD_UX2].fd = ux_sock[1]; + polls[POLLFD_UX2].events = POLLIN; } else { /* * New clients can't connect, num_clients won't grow @@ -687,7 +695,7 @@ void *uxsock_listen(int n_socks, long *ux_sock, void *trigger_data) */ condlog(1, "%s: max client connections reached, pausing polling", __func__); - polls[POLLFD_UX].fd = -1; + polls[POLLFD_UX1].fd = polls[POLLFD_UX2].fd = -1; } reset_watch(notify_fd, &wds, &sequence_nr); @@ -771,9 +779,12 @@ void *uxsock_listen(int n_socks, long *ux_sock, void *trigger_data) handle_signals(true); /* see if we got a new client */ - if (polls[POLLFD_UX].revents & POLLIN) { + if (polls[POLLFD_UX1].revents & POLLIN) { new_client(ux_sock[0]); } + if (polls[POLLFD_UX2].revents & POLLIN) { + new_client(ux_sock[1]); + } /* handle inotify events on config files */ if (polls[POLLFD_NOTIFY].revents & POLLIN)