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 |