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 <ob...@samba.org>
Date:   Thu Sep 22 02:13:20 2016 +0200

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

commit f9fbda9ef0f7b279e8e618a3888ab2e50884da1b
Author: Michael Adam <ob...@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 <ob...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit 69aee42f1d4a0e563b9e85e899dc8b4f18303af0
Author: Anoop C S <anoo...@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 <ob...@samba.org>
    
    Signed-off-by: Anoop C S <anoo...@redhat.com>
    Signed-off-by: Michael Adam <ob...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit c3e5f78016f4319fb22126163d0ddbcac0bdeed5
Author: Michael Adam <ob...@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 <me...@samba.org>
    
    Signed-off-by: Michael Adam <ob...@samba.org>
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit 1e7528c2b1a027538b54bd3576eba1206265ae8c
Author: Michael Adam <ob...@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 <me...@samba.org>
    
    Signed-off-by: Michael Adam <ob...@samba.org>
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit d3d09e631aa7f9b5ffe88a786ad21e7e51aee909
Author: Michael Adam <ob...@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 <me...@samba.org>
    
    Signed-off-by: Michael Adam <ob...@samba.org>
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit ebe5f15854866c225febe73c952356873b958305
Author: Michael Adam <ob...@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 <me...@samba.org>
    
    Signed-off-by: Michael Adam <ob...@samba.org>
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

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

    swrap: Add SWRAP_DLIST_ADD_AFTER macro
    
    Pair-Programmed-With: Stefan Metzmacher <me...@samba.org>
    
    Signed-off-by: Michael Adam <ob...@samba.org>
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>

commit 087f9aea821cceffd3ced15b576106cace8a2c9d
Author: Anoop C S <anoo...@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 <ob...@samba.org>
    Signed-off-by: Anoop C S <anoo...@redhat.com>
    Signed-off-by: Michael Adam <ob...@samba.org>
    Reviewed-by: Andreas Schneider <a...@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

Reply via email to