[sheepdog] [PATCH] sheep: bind TCP ports as soon as possible

Hitoshi Mitake mitake.hitoshi at gmail.com
Sun Mar 31 18:23:58 CEST 2013


Current binding of TCP ports is done after some parts of
initialization e.g. log_init(). Because of this behaviour, confusing
logs can be created. These logs would contain interleaving messages
from different sheep processes (e.g. sudden "failed to bind server
socket: Address already in use").

This patch forbids such a problem by making a part of binding TCP
sockets independent. This patch splits create_listen_port() into two
functions: create_listen_fds() and create_listen_events(). main() of
sheep calls create_listen_fds(), the function for creating bind()ed
fds, direct after calling early_log_init(). The latter
create_listen_events(), the function for registering events based on
fds created by create_listen_fds(), is called after init_event().

Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
 include/net.h      |    4 ++--
 lib/net.c          |   22 ++++++++++++----------
 sheep/request.c    |   29 ++++++++++++++++++++++++++---
 sheep/sheep.c      |   31 ++++++++++++++++++++++++++++---
 sheep/sheep_priv.h |    1 +
 5 files changed, 69 insertions(+), 18 deletions(-)

diff --git a/include/net.h b/include/net.h
index a68c880..3f8663f 100644
--- a/include/net.h
+++ b/include/net.h
@@ -57,8 +57,8 @@ int send_req(int sockfd, struct sd_req *hdr, void *data, unsigned int wlen,
 	     bool (*need_retry)(uint32_t), uint32_t);
 int exec_req(int sockfd, struct sd_req *hdr, void *,
 	     bool (*need_retry)(uint32_t), uint32_t);
-int create_listen_ports(const char *bindaddr, int port,
-			int (*callback)(int fd, void *), void *data);
+int create_listen_fds(const char *bindaddr, int port,
+		int **fds, int *nr_fds_res);
 int create_unix_domain_socket(const char *unix_path,
 			      int (*callback)(int, void *), void *data);
 
diff --git a/lib/net.c b/lib/net.c
index ff0c150..0f2c36f 100644
--- a/lib/net.c
+++ b/lib/net.c
@@ -113,13 +113,14 @@ notrace int tx(struct connection *conn, enum conn_state next_state)
 	return ret;
 }
 
-int create_listen_ports(const char *bindaddr, int port,
-		int (*callback)(int fd, void *), void *data)
+int create_listen_fds(const char *bindaddr, int port,
+		int **fds_res, int *nr_fds_res)
 {
 	char servname[64];
-	int fd, ret, opt;
+	int fd, ret, opt, nr_fds;
 	int success = 0;
 	struct addrinfo hints, *res, *res0;
+	int *fds;
 
 	memset(servname, 0, sizeof(servname));
 	snprintf(servname, sizeof(servname), "%d", port);
@@ -134,6 +135,11 @@ int create_listen_ports(const char *bindaddr, int port,
 		return 1;
 	}
 
+	nr_fds = 0;
+	for (res = res0; res; res = res->ai_next)
+		nr_fds++;
+	fds = xcalloc(nr_fds, sizeof(int));
+
 	for (res = res0; res; res = res->ai_next) {
 		fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 		if (fd < 0)
@@ -175,13 +181,7 @@ int create_listen_ports(const char *bindaddr, int port,
 			continue;
 		}
 
-		ret = callback(fd, data);
-		if (ret) {
-			close(fd);
-			continue;
-		}
-
-		success++;
+		fds[success++] = fd;
 	}
 
 	freeaddrinfo(res0);
@@ -189,6 +189,8 @@ int create_listen_ports(const char *bindaddr, int port,
 	if (!success)
 		sd_eprintf("failed to create a listening port");
 
+	*fds_res = fds;
+	*nr_fds_res = success;
 	return !success;
 }
 
diff --git a/sheep/request.c b/sheep/request.c
index bd0f170..3a05604 100644
--- a/sheep/request.c
+++ b/sheep/request.c
@@ -877,10 +877,33 @@ static int create_listen_port_fn(int fd, void *data)
 
 int create_listen_port(char *bindaddr, int port)
 {
-	static bool is_inet_socket = true;
+	int *fds, nr_fds;
+	int ret;
+
+	ret = create_listen_fds(bindaddr, port, &fds, &nr_fds);
+	if (ret)
+		exit(1);
+
+	ret = create_listen_events(fds, nr_fds);
+	if (ret)
+		exit(1);
+	free(fds);
+
+	return ret;
+}
 
-	return create_listen_ports(bindaddr, port, create_listen_port_fn,
-				   &is_inet_socket);
+int create_listen_events(int *fds, int nr_fds)
+{
+	int i, ret;
+	static bool is_inet = true;
+
+	for (i = 0; i < nr_fds; i++) {
+		ret = register_event(fds[i], listen_handler, &is_inet);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 int init_unix_domain_socket(const char *dir)
diff --git a/sheep/sheep.c b/sheep/sheep.c
index 4fa7d58..1445061 100644
--- a/sheep/sheep.c
+++ b/sheep/sheep.c
@@ -402,6 +402,9 @@ int main(int argc, char **argv)
 	const char *log_format = "default";
 	static struct logger_user_info sheep_info;
 
+	int *bind_fds, nr_bind_fds;
+	int *io_bind_fds, nr_io_bind_fds;
+
 	install_crash_handler(crash_handler);
 	signal(SIGPIPE, SIG_IGN);
 
@@ -556,6 +559,23 @@ int main(int argc, char **argv)
 	sheep_info.port = port;
 	early_log_init(log_format, &sheep_info);
 
+	/*
+	 * These create_listen_fds() must be called before writing anything on
+	 * log files.
+	 * Because there is a possibility that another sheep process is already
+	 * using the port. If the conflict rises, it should be reported ASAP.
+	 */
+	ret = create_listen_fds(bindaddr, port, &bind_fds, &nr_bind_fds);
+	if (ret)
+		exit(1);
+
+	if (io_addr) {
+		ret = create_listen_fds(io_addr, io_port, &io_bind_fds,
+					&nr_io_bind_fds);
+		if (ret)
+			exit(1);
+	}
+
 	if (nr_vnodes == 0) {
 		sys->gateway_only = true;
 		sys->disk_space = 0;
@@ -597,12 +617,17 @@ int main(int argc, char **argv)
 	if (ret)
 		exit(1);
 
-	ret = create_listen_port(bindaddr, port);
+	ret = create_listen_events(bind_fds, nr_bind_fds);
 	if (ret)
 		exit(1);
+	free(bind_fds);
 
-	if (io_addr && create_listen_port(io_addr, io_port))
-		exit(1);
+	if (io_addr) {
+		ret = create_listen_events(io_bind_fds, nr_io_bind_fds);
+		if (ret)
+			exit(1);
+		free(io_bind_fds);
+	}
 
 	ret = init_unix_domain_socket(dir);
 	if (ret)
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index 652fd3a..534e1e1 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -220,6 +220,7 @@ static inline uint32_t sys_epoch(void)
 
 int create_listen_port(char *bindaddr, int port);
 int init_unix_domain_socket(const char *dir);
+int create_listen_events(int *fds, int nr_fds);
 
 int init_store_driver(bool is_gateway);
 int init_global_pathnames(const char *d, char *);
-- 
1.7.5.1




More information about the sheepdog mailing list