[sheepdog] [PATCH] sheep: add support for using unix domain socket

MORITA Kazutaka morita.kazutaka at lab.ntt.co.jp
Fri Nov 2 14:19:16 CET 2012


This patch adds support for a unix domain socket for a connection
between qemu and local gateway.  You can use this feature with the
following syntax:

 $ qemu sheepdog:unix:<socket file>:<vdi name>

On my environment, the IOPS is improved from 3700/s to 4100/s against
one local sheep with 4 KB buffer size.

Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
 include/net.h      |    2 ++
 lib/net.c          |   45 ++++++++++++++++++++++++++++++++++++++++++++-
 sheep/request.c    |   40 +++++++++++++++++++++++++++++-----------
 sheep/sheep.c      |    6 +++++-
 sheep/sheep_priv.h |    3 ++-
 5 files changed, 82 insertions(+), 14 deletions(-)

diff --git a/include/net.h b/include/net.h
index 5c28846..3665f5e 100644
--- a/include/net.h
+++ b/include/net.h
@@ -45,6 +45,8 @@ int send_req(int sockfd, struct sd_req *hdr, void *data, unsigned int wlen);
 int exec_req(int sockfd, struct sd_req *hdr, void *data);
 int create_listen_ports(const char *bindaddr, int port,
 			int (*callback)(int fd, void *), void *data);
+int create_unix_domain_socket(const char *unix_path,
+			      int (*callback)(int, void *), void *data);
 
 char *addr_to_str(char *str, int size, const uint8_t *addr, uint16_t port);
 uint8_t *str_to_addr(int af, const char *ipstr, uint8_t *addr);
diff --git a/lib/net.c b/lib/net.c
index 6d2fcaf..74c7df4 100644
--- a/lib/net.c
+++ b/lib/net.c
@@ -22,6 +22,7 @@
 #include <netinet/tcp.h>
 #include <sys/epoll.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
@@ -479,7 +480,7 @@ int set_keepalive(int fd)
 	}
 	val = 5;
 	if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
-		dprintf("%m\n");
+		panic("%m\n");
 		return -1;
 	}
 	val = 1;
@@ -537,3 +538,45 @@ out:
 	freeifaddrs(ifaddr);
 	return ret;
 }
+
+int create_unix_domain_socket(const char *unix_path,
+			      int (*callback)(int, void *), void *data)
+{
+	int fd = -1, ret;
+	struct sockaddr_un addr;
+
+	addr.sun_family = AF_UNIX;
+	pstrcpy(addr.sun_path, sizeof(addr.sun_path), unix_path);
+
+	fd = socket(addr.sun_family, SOCK_STREAM, 0);
+	if (fd < 0) {
+		eprintf("failed to create socket, %m\n");
+		return -1;
+	}
+
+	ret = bind(fd, &addr, sizeof(addr));
+	if (ret) {
+		eprintf("failed to bind socket: %m\n");
+		goto err;
+	}
+
+	ret = listen(fd, SOMAXCONN);
+	if (ret) {
+		eprintf("failed to listen on socket: %m\n");
+		goto err;
+	}
+
+	ret = set_nonblocking(fd);
+	if (ret < 0)
+		goto err;
+
+	ret = callback(fd, data);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	if (fd >= 0)
+		close(fd);
+	return -1;
+}
diff --git a/sheep/request.c b/sheep/request.c
index 01a9908..9c8f92b 100644
--- a/sheep/request.c
+++ b/sheep/request.c
@@ -826,6 +826,7 @@ static void listen_handler(int listen_fd, int events, void *data)
 	socklen_t namesize;
 	int fd, ret;
 	struct client_info *ci;
+	bool is_inet_socket = *(bool *)data;
 
 	if (sys->status == SD_STATUS_SHUTDOWN) {
 		dprintf("unregistering connection %d\n", listen_fd);
@@ -840,16 +841,18 @@ static void listen_handler(int listen_fd, int events, void *data)
 		return;
 	}
 
-	ret = set_keepalive(fd);
-	if (ret) {
-		close(fd);
-		return;
-	}
+	if (is_inet_socket) {
+		ret = set_keepalive(fd);
+		if (ret) {
+			close(fd);
+			return;
+		}
 
-	ret = set_nodelay(fd);
-	if (ret) {
-		close(fd);
-		return;
+		ret = set_nodelay(fd);
+		if (ret) {
+			close(fd);
+			return;
+		}
 	}
 
 	ret = set_nonblocking(fd);
@@ -878,9 +881,24 @@ static int create_listen_port_fn(int fd, void *data)
 	return register_event(fd, listen_handler, data);
 }
 
-int create_listen_port(char *bindaddr, int port, void *data)
+int create_listen_port(char *bindaddr, int port)
+{
+	static bool is_inet_socket = true;
+
+	return create_listen_ports(bindaddr, port, create_listen_port_fn,
+				   &is_inet_socket);
+}
+
+int init_unix_domain_socket(const char *dir)
 {
-	return create_listen_ports(bindaddr, port, create_listen_port_fn, data);
+	static bool is_inet_socket = false;
+	char unix_path[PATH_MAX];
+
+	snprintf(unix_path, sizeof(unix_path), "%s/sock", dir);
+	unlink(unix_path);
+
+	return create_unix_domain_socket(unix_path, create_listen_port_fn,
+					 &is_inet_socket);
 }
 
 static void req_handler(int listen_fd, int events, void *data)
diff --git a/sheep/sheep.c b/sheep/sheep.c
index 3ec2c4d..af8da4f 100644
--- a/sheep/sheep.c
+++ b/sheep/sheep.c
@@ -479,7 +479,11 @@ int main(int argc, char **argv)
 	if (ret)
 		exit(1);
 
-	ret = create_listen_port(bindaddr, port, sys);
+	ret = create_listen_port(bindaddr, port);
+	if (ret)
+		exit(1);
+
+	ret = init_unix_domain_socket(dir);
 	if (ret)
 		exit(1);
 
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index 0480e26..9bec91e 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -216,7 +216,8 @@ static inline uint32_t sys_epoch(void)
 	return uatomic_read(&sys->epoch);
 }
 
-int create_listen_port(char *bindaddr, int port, void *data);
+int create_listen_port(char *bindaddr, int port);
+int init_unix_domain_socket(const char *dir);
 
 int init_store(const char *dir);
 int init_base_path(const char *dir);
-- 
1.7.2.5




More information about the sheepdog mailing list