summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAnoop C S <anoopcs@redhat.com>2016-08-25 11:41:12 +0530
committerAndreas Schneider <asn@samba.org>2016-10-20 10:51:59 +0200
commit69aee42f1d4a0e563b9e85e899dc8b4f18303af0 (patch)
tree9e6af333fc8aea93e21499040bdec06613128612 /src
parentc3e5f78016f4319fb22126163d0ddbcac0bdeed5 (diff)
downloadsocket_wrapper-69aee42f1d4a0e563b9e85e899dc8b4f18303af0.tar.gz
socket_wrapper-69aee42f1d4a0e563b9e85e899dc8b4f18303af0.tar.xz
socket_wrapper-69aee42f1d4a0e563b9e85e899dc8b4f18303af0.zip
swrap: Replace linked list of socket_info with preallocated array of structures
Pair-Programmed-With: Michael Adam <obnox@samba.org> Signed-off-by: Anoop C S <anoopcs@redhat.com> Signed-off-by: Michael Adam <obnox@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'src')
-rw-r--r--src/socket_wrapper.c148
1 files changed, 120 insertions, 28 deletions
diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c
index 51d22df..ad7f682 100644
--- a/src/socket_wrapper.c
+++ b/src/socket_wrapper.c
@@ -226,6 +226,14 @@ do { \
#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 */
@@ -248,8 +256,11 @@ struct socket_info_fd {
struct socket_info_fd *prev, *next;
int fd;
- /* Points to list of socket_info structures */
- struct socket_info *si;
+ /*
+ * Points to corresponding index in array of
+ * socket_info structures
+ */
+ int si_index;
};
struct socket_info
@@ -280,6 +291,9 @@ struct socket_info
} io;
};
+static struct socket_info *sockets;
+static size_t max_sockets = 0;
+
/*
* While socket file descriptors are passed among different processes, the
* numerical value gets changed. So its better to store it locally to each
@@ -986,11 +1000,64 @@ 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)
+{
+
+ 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);
+ }
+}
+
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)
@@ -1008,6 +1075,20 @@ static unsigned int socket_wrapper_default_iface(void)
return 1;/* 127.0.0.1 */
}
+static int socket_wrapper_first_free_index(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < max_sockets; ++i) {
+ if (sockets[i].refcount == 0) {
+ ZERO_STRUCT(sockets[i]);
+ return i;
+ }
+ }
+
+ return -1;
+}
+
static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
{
unsigned int iface;
@@ -1388,15 +1469,26 @@ static struct socket_info_fd *find_socket_info_fd(int fd)
return NULL;
}
-static struct socket_info *find_socket_info(int fd)
+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 fi->si;
+ return &sockets[idx];
}
#if 0 /* FIXME */
@@ -1425,7 +1517,7 @@ static bool check_addr_port_in_use(const struct sockaddr *sa, socklen_t len)
}
for (f = socket_fds; f; f = f->next) {
- struct socket_info *s = f->si;
+ struct socket_info *s = &sockets[f->si_index];
if (s == last_s) {
continue;
@@ -1500,7 +1592,7 @@ static void swrap_remove_stale(int fd)
return;
}
- si = fi->si;
+ si = &sockets[fi->si_index];
SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd);
SWRAP_DLIST_REMOVE(socket_fds, fi);
@@ -1515,7 +1607,6 @@ static void swrap_remove_stale(int fd)
if (si->un_addr.sun_path[0] != '\0') {
unlink(si->un_addr.sun_path);
}
- free(si);
}
static int sockaddr_convert_to_un(struct socket_info *si,
@@ -2409,6 +2500,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;
/*
@@ -2487,12 +2579,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
@@ -2524,21 +2618,19 @@ 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;
fi->fd = fd;
- fi->si = si;
+ fi->si_index = idx;
SWRAP_DLIST_ADD(socket_fds, fi);
@@ -2634,6 +2726,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),
};
@@ -2693,16 +2786,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;
@@ -2735,7 +2828,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;
}
@@ -2748,7 +2840,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;
}
@@ -2763,7 +2854,7 @@ static int swrap_accept(int s,
memcpy(&child_si->myname.sa.ss, &in_my_addr.sa.ss, in_my_addr.sa_socklen);
child_si->refcount = 1;
- child_fi->si = child_si;
+ child_fi->si_index = idx;
SWRAP_DLIST_ADD(socket_fds, child_fi);
@@ -5121,7 +5212,7 @@ static int swrap_close(int fd)
return libc_close(fd);
}
- si = fi->si;
+ si = &sockets[fi->si_index];
SWRAP_DLIST_REMOVE(socket_fds, fi);
free(fi);
@@ -5147,7 +5238,6 @@ static int swrap_close(int fd)
if (si->un_addr.sun_path[0] != '\0') {
unlink(si->un_addr.sun_path);
}
- free(si);
return ret;
}
@@ -5171,7 +5261,7 @@ static int swrap_dup(int fd)
return libc_dup(fd);
}
- si = src_fi->si;
+ si = &sockets[src_fi->si_index];
fi = (struct socket_info_fd *)calloc(1, sizeof(struct socket_info_fd));
if (fi == NULL) {
@@ -5188,7 +5278,7 @@ static int swrap_dup(int fd)
}
si->refcount++;
- fi->si = si;
+ fi->si_index = src_fi->si_index;
/* Make sure we don't have an entry for the fd */
swrap_remove_stale(fi->fd);
@@ -5216,7 +5306,7 @@ static int swrap_dup2(int fd, int newfd)
return libc_dup2(fd, newfd);
}
- si = src_fi->si;
+ si = &sockets[src_fi->si_index];
if (fd == newfd) {
/*
@@ -5249,7 +5339,7 @@ static int swrap_dup2(int fd, int newfd)
}
si->refcount++;
- fi->si = si;
+ fi->si_index = src_fi->si_index;
/* Make sure we don't have an entry for the fd */
swrap_remove_stale(fi->fd);
@@ -5278,7 +5368,7 @@ static int swrap_vfcntl(int fd, int cmd, va_list va)
return libc_vfcntl(fd, cmd, va);
}
- si = src_fi->si;
+ si = &sockets[src_fi->si_index];
switch (cmd) {
case F_DUPFD:
@@ -5297,7 +5387,7 @@ static int swrap_vfcntl(int fd, int cmd, va_list va)
}
si->refcount++;
- fi->si = si;
+ fi->si_index = src_fi->si_index;
/* Make sure we don't have an entry for the fd */
swrap_remove_stale(fi->fd);
@@ -5382,6 +5472,8 @@ void swrap_destructor(void)
s = socket_fds;
}
+ free(sockets);
+
if (swrap.libc_handle != NULL) {
dlclose(swrap.libc_handle);
}