[SCM] Socket Wrapper Repository - branch master updated

Andreas Schneider asn at samba.org
Thu Oct 20 08:52:47 UTC 2016


The branch, master has been updated
       via  b61f5df tests: Add a test for max_sockets
       via  f9fbda9 swrap: Introduce a freelist in the socket_info array
       via  69aee42 swrap: Replace linked list of socket_info with preallocated array of structures
       via  c3e5f78 swrap: Optimization in (commented out) check_addr_port_in_use()
       via  1e7528c swrap: Improve vfcntl to add the dup'd fd after the source fd
       via  d3d09e6 swrap: Improve dup2 to add the dup'd fd after the source fd
       via  ebe5f15 swrap: Improve dup to add the dup'd fd after the source fd
       via  97d2372 swrap: Add SWRAP_DLIST_ADD_AFTER macro
       via  087f9ae swrap: Untangle socket_info_fd from socket_info structure.
      from  f43d383 swrap: remove ununsed members from struct swrap.

https://git.samba.org/?p=socket_wrapper.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit b61f5df9f4a7c57cb9ad313a20d7dbe316f42072
Author: Michael Adam <obnox at samba.org>
Date:   Thu Sep 22 02:13:20 2016 +0200

    tests: Add a test for max_sockets
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit f9fbda9ef0f7b279e8e618a3888ab2e50884da1b
Author: Michael Adam <obnox at samba.org>
Date:   Wed Sep 14 13:24:47 2016 +0200

    swrap: Introduce a freelist in the socket_info array
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 69aee42f1d4a0e563b9e85e899dc8b4f18303af0
Author: Anoop C S <anoopcs at redhat.com>
Date:   Thu Aug 25 11:41:12 2016 +0530

    swrap: Replace linked list of socket_info with preallocated array of structures
    
    Pair-Programmed-With: Michael Adam <obnox at samba.org>
    
    Signed-off-by: Anoop C S <anoopcs at redhat.com>
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit c3e5f78016f4319fb22126163d0ddbcac0bdeed5
Author: Michael Adam <obnox at samba.org>
Date:   Tue Aug 16 13:38:50 2016 +0200

    swrap: Optimization in (commented out) check_addr_port_in_use()
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 1e7528c2b1a027538b54bd3576eba1206265ae8c
Author: Michael Adam <obnox at samba.org>
Date:   Tue Aug 16 11:04:43 2016 +0200

    swrap: Improve vfcntl to add the dup'd fd after the source fd
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit d3d09e631aa7f9b5ffe88a786ad21e7e51aee909
Author: Michael Adam <obnox at samba.org>
Date:   Tue Aug 16 11:04:12 2016 +0200

    swrap: Improve dup2 to add the dup'd fd after the source fd
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit ebe5f15854866c225febe73c952356873b958305
Author: Michael Adam <obnox at samba.org>
Date:   Tue Aug 16 11:03:27 2016 +0200

    swrap: Improve dup to add the dup'd fd after the source fd
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 97d23728cfc392fe5f2c33831f4c85aa31d083fc
Author: Michael Adam <obnox at samba.org>
Date:   Tue Aug 16 11:00:50 2016 +0200

    swrap: Add SWRAP_DLIST_ADD_AFTER macro
    
    Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
    
    Signed-off-by: Michael Adam <obnox at samba.org>
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 087f9aea821cceffd3ced15b576106cace8a2c9d
Author: Anoop C S <anoopcs at redhat.com>
Date:   Wed Aug 10 16:32:19 2016 +0530

    swrap: Untangle socket_info_fd from socket_info structure.
    
    This reverses the dependency of socket_info on socket_info_fd:
    Instead of maintaining the list of socket_info structures,
    and keeping a list of referencing fds (created by dup),
    we now maintain the list of fds with pointers to the
    corresponding socket_info structures, and count the
    references in the socket_info.
    
    This makes the treatment of the lists more obvious,
    especially seen in the removing part.
    
    This change is a preparatory step for implementing
    fd-passing in socket-wrapper.
    
    Pair-programmed-with: Michael Adam <obnox at samba.org>
    Signed-off-by: Anoop C S <anoopcs at redhat.com>
    Signed-off-by: Michael Adam <obnox at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 src/socket_wrapper.c     | 330 +++++++++++++++++++++++++++++++++++------------
 tests/CMakeLists.txt     |   3 +-
 tests/test_max_sockets.c | 110 ++++++++++++++++
 3 files changed, 358 insertions(+), 85 deletions(-)
 create mode 100644 tests/test_max_sockets.c


Changeset truncated at 500 lines:

diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c
index 6c4ae3b..84dfc07 100644
--- a/src/socket_wrapper.c
+++ b/src/socket_wrapper.c
@@ -184,6 +184,20 @@ enum swrap_dbglvl_e {
 	(item)->next	= NULL; \
 } while (0)
 
+#define SWRAP_DLIST_ADD_AFTER(list, item, el) \
+do { \
+	if ((list) != NULL || (el) != NULL) { \
+		SWRAP_DLIST_ADD(list, item); \
+	} else { \
+		(item)->prev = (el); \
+		(item)->next = (el)->next; \
+		(el)->next = (item); \
+		if ((item)->next != NULL) { \
+			(item)->next->prev = (item); \
+		} \
+	} \
+} while (0)
+
 #if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
 #else
@@ -212,6 +226,14 @@ enum swrap_dbglvl_e {
 
 #define SOCKET_MAX_SOCKETS 1024
 
+
+/*
+ * Maximum number of socket_info structures that can
+ * be used. Can be overriden by the environment variable
+ * SOCKET_WRAPPER_MAX_SOCKETS.
+ */
+#define SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT 65535
+
 /* This limit is to avoid broadcast sendto() needing to stat too many
  * files.  It may be raised (with a performance cost) to up to 254
  * without changing the format above */
@@ -233,11 +255,21 @@ struct swrap_address {
 struct socket_info_fd {
 	struct socket_info_fd *prev, *next;
 	int fd;
+
+	/*
+	 * Points to corresponding index in array of
+	 * socket_info structures
+	 */
+	int si_index;
 };
 
+int first_free;
+
 struct socket_info
 {
-	struct socket_info_fd *fds;
+	unsigned int refcount;
+
+	int next_free;
 
 	int family;
 	int type;
@@ -261,15 +293,17 @@ struct socket_info
 		unsigned long pck_snd;
 		unsigned long pck_rcv;
 	} io;
-
-	struct socket_info *prev, *next;
 };
 
+static struct socket_info *sockets;
+static size_t max_sockets = 0;
+
 /*
- * File descriptors are shared between threads so we should share socket
- * information too.
+ * While socket file descriptors are passed among different processes, the
+ * numerical value gets changed. So its better to store it locally to each
+ * process rather than including it within socket_info which will be shared.
  */
-struct socket_info *sockets;
+static struct socket_info_fd *socket_fds;
 
 /* Function prototypes */
 
@@ -970,11 +1004,73 @@ done:
 	return max_mtu;
 }
 
+static size_t socket_wrapper_max_sockets(void)
+{
+	const char *s;
+	unsigned long tmp;
+	char *endp;
+
+	if (max_sockets != 0) {
+		return max_sockets;
+	}
+
+	max_sockets = SOCKET_WRAPPER_MAX_SOCKETS_DEFAULT;
+
+	s = getenv("SOCKET_WRAPPER_MAX_SOCKETS");
+	if (s == NULL || s[0] == '\0') {
+		goto done;
+	}
+
+	tmp = strtoul(s, &endp, 10);
+	if (s == endp) {
+		goto done;
+	}
+
+	max_sockets = tmp;
+
+done:
+	return max_sockets;
+}
+
+static void socket_wrapper_init_sockets(void)
+{
+	size_t i;
+
+	if (sockets != NULL) {
+		return;
+	}
+
+	max_sockets = socket_wrapper_max_sockets();
+
+	sockets = (struct socket_info *)calloc(max_sockets,
+					       sizeof(struct socket_info));
+
+	if (sockets == NULL) {
+		SWRAP_LOG(SWRAP_LOG_ERROR,
+			  "Failed to allocate sockets array.\n");
+		exit(-1);
+	}
+
+	first_free = 0;
+
+	for (i = 0; i < max_sockets; i++) {
+		sockets[i].next_free = i+1;
+	}
+
+	sockets[max_sockets-1].next_free = -1;
+}
+
 bool socket_wrapper_enabled(void)
 {
 	const char *s = socket_wrapper_dir();
 
-	return s != NULL ? true : false;
+	if (s == NULL) {
+		return false;
+	}
+
+	socket_wrapper_init_sockets();
+
+	return true;
 }
 
 static unsigned int socket_wrapper_default_iface(void)
@@ -992,6 +1088,25 @@ static unsigned int socket_wrapper_default_iface(void)
 	return 1;/* 127.0.0.1 */
 }
 
+/*
+ * Return the first free entry (if any) and make
+ * it re-usable again (by nulling it out)
+ */
+static int socket_wrapper_first_free_index(void)
+{
+	int next_free;
+
+	if (first_free == -1) {
+		return -1;
+	}
+
+	next_free = sockets[first_free].next_free;
+	ZERO_STRUCT(sockets[first_free]);
+	sockets[first_free].next_free = next_free;
+
+	return first_free;
+}
+
 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
 {
 	unsigned int iface;
@@ -1359,26 +1474,46 @@ static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *in
 	return 0;
 }
 
-static struct socket_info *find_socket_info(int fd)
+static struct socket_info_fd *find_socket_info_fd(int fd)
 {
-	struct socket_info *i;
+	struct socket_info_fd *f;
 
-	for (i = sockets; i; i = i->next) {
-		struct socket_info_fd *f;
-		for (f = i->fds; f; f = f->next) {
-			if (f->fd == fd) {
-				return i;
-			}
+	for (f = socket_fds; f; f = f->next) {
+		if (f->fd == fd) {
+			return f;
 		}
 	}
 
 	return NULL;
 }
 
+static int find_socket_info_index(int fd)
+{
+	struct socket_info_fd *fi = find_socket_info_fd(fd);
+
+	if (fi == NULL) {
+		return -1;
+	}
+
+	return fi->si_index;
+}
+
+static struct socket_info *find_socket_info(int fd)
+{
+	int idx = find_socket_info_index(fd);
+
+	if (idx == -1) {
+		return NULL;
+	}
+
+	return &sockets[idx];
+}
+
 #if 0 /* FIXME */
 static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
 {
-	struct socket_info *s;
+	struct socket_info_fd *f;
+	const struct socket_info *last_s = NULL;
 
 	/* first catch invalid input */
 	switch (sa->sa_family) {
@@ -1399,7 +1534,14 @@ static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
 		break;
 	}
 
-	for (s = sockets; s != NULL; s = s->next) {
+	for (f = socket_fds; f; f = f->next) {
+		struct socket_info *s = &sockets[f->si_index];
+
+		if (s == last_s) {
+			continue;
+		}
+		last_s = s;
+
 		if (s->myname == NULL) {
 			continue;
 		}
@@ -1461,29 +1603,31 @@ static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
 
 static void swrap_remove_stale(int fd)
 {
-	struct socket_info *si = find_socket_info(fd);
-	struct socket_info_fd *fi;
+	struct socket_info_fd *fi = find_socket_info_fd(fd);
+	struct socket_info *si;
 
-	if (si == NULL) {
+	if (fi == NULL) {
 		return;
 	}
 
-	for (fi = si->fds; fi; fi = fi->next) {
-		if (fi->fd == fd) {
-			SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
-			SWRAP_DLIST_REMOVE(si->fds, fi);
-			free(fi);
-			break;
-		}
+	si = &sockets[fi->si_index];
+
+	SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
+	SWRAP_DLIST_REMOVE(socket_fds, fi);
+	free(fi);
+
+	si->refcount--;
+
+	if (si->refcount > 0) {
+		return;
 	}
 
-	if (si->fds == NULL) {
-		SWRAP_DLIST_REMOVE(sockets, si);
-		if (si->un_addr.sun_path[0] != '\0') {
-			unlink(si->un_addr.sun_path);
-		}
-		free(si);
+	if (si->un_addr.sun_path[0] != '\0') {
+		unlink(si->un_addr.sun_path);
 	}
+
+	si->next_free = first_free;
+	first_free = fi->si_index;
 }
 
 static int sockaddr_convert_to_un(struct socket_info *si,
@@ -2377,6 +2521,7 @@ static int swrap_socket(int family, int type, int protocol)
 	struct socket_info *si;
 	struct socket_info_fd *fi;
 	int fd;
+	int idx;
 	int real_type = type;
 
 	/*
@@ -2455,12 +2600,14 @@ static int swrap_socket(int family, int type, int protocol)
 	/* Check if we have a stale fd and remove it */
 	swrap_remove_stale(fd);
 
-	si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
-	if (si == NULL) {
+	idx = socket_wrapper_first_free_index();
+	if (idx == -1) {
 		errno = ENOMEM;
 		return -1;
 	}
 
+	si = &sockets[idx];
+
 	si->family = family;
 
 	/* however, the rest of the socket_wrapper code expects just
@@ -2492,22 +2639,24 @@ static int swrap_socket(int family, int type, int protocol)
 		break;
 	}
 	default:
-		free(si);
 		errno = EINVAL;
 		return -1;
 	}
 
 	fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
 	if (fi == NULL) {
-		free(si);
 		errno = ENOMEM;
 		return -1;
 	}
 
+	si->refcount = 1;
+	first_free = si->next_free;
+	si->next_free = 0;
+
 	fi->fd = fd;
+	fi->si_index = idx;
 
-	SWRAP_DLIST_ADD(si->fds, fi);
-	SWRAP_DLIST_ADD(sockets, si);
+	SWRAP_DLIST_ADD(socket_fds, fi);
 
 	SWRAP_LOG(SWRAP_LOG_TRACE,
 		  "Created %s socket for protocol %s",
@@ -2601,6 +2750,7 @@ static int swrap_accept(int s,
 	struct socket_info *parent_si, *child_si;
 	struct socket_info_fd *child_fi;
 	int fd;
+	int idx;
 	struct swrap_address un_addr = {
 		.sa_socklen = sizeof(struct sockaddr_un),
 	};
@@ -2660,16 +2810,16 @@ static int swrap_accept(int s,
 		return ret;
 	}
 
-	child_si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
-	if (child_si == NULL) {
-		close(fd);
+	idx = socket_wrapper_first_free_index();
+	if (idx == -1) {
 		errno = ENOMEM;
 		return -1;
 	}
 
+	child_si = &sockets[idx];
+
 	child_fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
 	if (child_fi == NULL) {
-		free(child_si);
 		close(fd);
 		errno = ENOMEM;
 		return -1;
@@ -2702,7 +2852,6 @@ static int swrap_accept(int s,
 			       &un_my_addr.sa_socklen);
 	if (ret == -1) {
 		free(child_fi);
-		free(child_si);
 		close(fd);
 		return ret;
 	}
@@ -2715,7 +2864,6 @@ static int swrap_accept(int s,
 				       &in_my_addr.sa_socklen);
 	if (ret == -1) {
 		free(child_fi);
-		free(child_si);
 		close(fd);
 		return ret;
 	}
@@ -2729,8 +2877,13 @@ static int swrap_accept(int s,
 	};
 	memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
 
-	SWRAP_DLIST_ADD(child_si->fds, child_fi);
-	SWRAP_DLIST_ADD(sockets, child_si);
+	child_si->refcount = 1;
+	first_free = child_si->next_free;
+	child_si->next_free = 0;
+
+	child_fi->si_index = idx;
+
+	SWRAP_DLIST_ADD(socket_fds, child_fi);
 
 	if (addr != NULL) {
 		swrap_pcap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
@@ -5078,29 +5231,26 @@ ssize_t writev(int s, const struct iovec *vector, int count)
 
 static int swrap_close(int fd)
 {
-	struct socket_info *si = find_socket_info(fd);
-	struct socket_info_fd *fi;
+	struct socket_info_fd *fi = find_socket_info_fd(fd);
+	struct socket_info *si = NULL;
 	int ret;
 
-	if (!si) {
+	if (fi == NULL) {
 		return libc_close(fd);
 	}
 
-	for (fi = si->fds; fi; fi = fi->next) {
-		if (fi->fd == fd) {
-			SWRAP_DLIST_REMOVE(si->fds, fi);
-			free(fi);
-			break;
-		}
-	}
+	si = &sockets[fi->si_index];
+
+	SWRAP_DLIST_REMOVE(socket_fds, fi);
+	free(fi);
+
+	si->refcount--;
 
-	if (si->fds) {
+	if (si->refcount > 0) {
 		/* there are still references left */
 		return libc_close(fd);
 	}
 
-	SWRAP_DLIST_REMOVE(sockets, si);
-
 	if (si->myname.sa_socklen > 0 && si->peername.sa_socklen > 0) {
 		swrap_pcap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
 	}
@@ -5115,7 +5265,9 @@ static int swrap_close(int fd)
 	if (si->un_addr.sun_path[0] != '\0') {
 		unlink(si->un_addr.sun_path);
 	}
-	free(si);
+
+	si->next_free = first_free;
+	first_free = fi->si_index;
 
 	return ret;
 }
@@ -5132,14 +5284,15 @@ int close(int fd)
 static int swrap_dup(int fd)
 {
 	struct socket_info *si;
-	struct socket_info_fd *fi;
-
-	si = find_socket_info(fd);
+	struct socket_info_fd *src_fi, *fi;
 
-	if (!si) {
+	src_fi = find_socket_info_fd(fd);
+	if (src_fi == NULL) {
 		return libc_dup(fd);
 	}
 
+	si = &sockets[src_fi->si_index];
+
 	fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
 	if (fi == NULL) {
 		errno = ENOMEM;
@@ -5154,10 +5307,13 @@ static int swrap_dup(int fd)
 		return -1;
 	}
 
+	si->refcount++;
+	fi->si_index = src_fi->si_index;
+


-- 
Socket Wrapper Repository



More information about the samba-cvs mailing list