diff mbox

[rdma-core,4/4] ibacm: Allow systemd to also setup the RDMA_LS socket for ibacm

Message ID 1504022325-31039-5-git-send-email-jgunthorpe@obsidianresearch.com (mailing list archive)
State Accepted
Headers show

Commit Message

Jason Gunthorpe Aug. 29, 2017, 3:58 p.m. UTC
This makes sure that very early queries from the kernel can be
delivered to ibacm even before it starts.

Requires trivial systemd patch:
 5570d7f95612 ("Support 'rdma' as a ListenNetlink= argument (#6626)")
Which is present starting in systemd v235

Old systemd's just ignore the netlink listen.

Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
 ibacm/ibacm.socket |  4 +++
 ibacm/src/acm.c    | 79 ++++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 63 insertions(+), 20 deletions(-)
diff mbox

Patch

diff --git a/ibacm/ibacm.socket b/ibacm/ibacm.socket
index aa94c91d60daf1..bdf1f9f4e85fe1 100644
--- a/ibacm/ibacm.socket
+++ b/ibacm/ibacm.socket
@@ -10,6 +10,10 @@  Before=rdma-hw.target
 ListenStream=6125
 BindToDevice=lo
 
+# Bind to PF_NETLINK, NETLINK_RDMA, RDMA_NL_GROUP_LS
+# Supported in systemd > 234
+ListenNetlink=rdma 4
+
 [Install]
 # Standard for all sockets
 WantedBy=sockets.target
diff --git a/ibacm/src/acm.c b/ibacm/src/acm.c
index 08937345a0c112..367a43fe9ad1ea 100644
--- a/ibacm/src/acm.c
+++ b/ibacm/src/acm.c
@@ -604,29 +604,56 @@  static int acm_listen(void)
 /* Retrieve the listening socket from systemd. */
 static int acm_listen_systemd(void)
 {
+	int fd;
+
 	int rc = sd_listen_fds(1);
-	if (rc == 0) {
-		/* We are in systemd mode but no FDs were passed? Fall back to
-		 * normal mode
-		 */
-		return acm_listen();
-	}
 	if (rc == -1) {
 		fprintf(stderr, "sd_listen_fds failed %d\n", rc);
 		return rc;
 	}
 
-	if (rc != 1) {
-		fprintf(stderr, "sd_listen_fds returned %d fds, expected 1\n", rc);
+	if (rc > 2) {
+		fprintf(stderr,
+			"sd_listen_fds returned %d fds, expected <= 2\n", rc);
 		return -1;
 	}
 
-	if (!sd_is_socket(SD_LISTEN_FDS_START, AF_UNSPEC, SOCK_STREAM, 1)) {
-		fprintf(stderr, "sd_listen_fds socket is not a SOCK_STREAM listening socket\n");
-		return -1;
+	for (fd = SD_LISTEN_FDS_START; fd != SD_LISTEN_FDS_START + rc; fd++) {
+		if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, 0)) {
+			/* ListenNetlink for RDMA_NL_GROUP_LS multicast
+			 * messages from the kernel
+			 */
+			if (client_array[NL_CLIENT_INDEX].sock != -1) {
+				fprintf(stderr,
+					"sd_listen_fds returned more than one netlink socket\n");
+				return -1;
+			}
+			client_array[NL_CLIENT_INDEX].sock = fd;
+
+			/* systemd sets NONBLOCK on the netlink socket, while
+			 * we want blocking send to the kernel.
+			 */
+			if (set_fd_nonblock(fd, false)) {
+				fprintf(stderr,
+					"Unable to drop O_NOBLOCK on netlink socket");
+				return -1;
+			}
+		} else if (sd_is_socket(SD_LISTEN_FDS_START, AF_UNSPEC,
+					SOCK_STREAM, 1)) {
+			/* Socket for user space client communication */
+			if (listen_socket != -1) {
+				fprintf(stderr,
+					"sd_listen_fds returned more than one listening socket\n");
+				return -1;
+			}
+			listen_socket = fd;
+		} else {
+			fprintf(stderr,
+				"sd_listen_fds socket is not a SOCK_STREAM/SOCK_NETLINK listening socket\n");
+			return -1;
+		}
 	}
 
-	listen_socket = SD_LISTEN_FDS_START;
 	return 0;
 }
 
@@ -1708,18 +1735,30 @@  static void acm_server(bool systemd)
 
 	acm_log(0, "started\n");
 	acm_init_server();
-	if (systemd)
+
+	client_array[NL_CLIENT_INDEX].sock = -1;
+	listen_socket = -1;
+	if (systemd) {
 		ret = acm_listen_systemd();
-	else
+		if (ret) {
+			acm_log(0, "ERROR - systemd server listen failed\n");
+			return;
+		}
+	}
+
+	if (listen_socket == -1) {
 		ret = acm_listen();
-	if (ret) {
-		acm_log(0, "ERROR - server listen failed\n");
-		return;
+		if (ret) {
+			acm_log(0, "ERROR - server listen failed\n");
+			return;
+		}
 	}
 
-	ret = acm_init_nl();
-	if (ret)
-		acm_log(1, "Warn - Netlink init failed\n");
+	if (client_array[NL_CLIENT_INDEX].sock == -1) {
+		ret = acm_init_nl();
+		if (ret)
+			acm_log(1, "Warn - Netlink init failed\n");
+	}
 
 	if (systemd)
 		sd_notify(0, "READY=1");