[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