summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2014-11-03 17:20:46 +0000
committerbluhm <bluhm@openbsd.org>2014-11-03 17:20:46 +0000
commit68d360c0a8adac53b80c76cdbdbd5ecbd7eda6c2 (patch)
treeb3308e7d2d32f2f2d31826b271033ee2611ceebe /sys
parentminor cleanup of zlib code. DSO is gone. ok jsing. (diff)
downloadwireguard-openbsd-68d360c0a8adac53b80c76cdbdbd5ecbd7eda6c2.tar.xz
wireguard-openbsd-68d360c0a8adac53b80c76cdbdbd5ecbd7eda6c2.zip
Put the socket splicing fields into a seperate struct sosplice that
gets only allocated when needed. This way struct socket shrinks from 472 to 392 bytes on amd64. When splicing gets active, another 88 bytes are allocated for struct sosplice. OK dlg@
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_sysctl.c11
-rw-r--r--sys/kern/uipc_socket.c73
-rw-r--r--sys/sys/socketvar.h25
3 files changed, 73 insertions, 36 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index ed72b739188..acb46adc2cc 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sysctl.c,v 1.268 2014/11/01 23:58:28 tedu Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.269 2014/11/03 17:20:46 bluhm Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@@ -1062,11 +1062,12 @@ fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp,
kf->so_family = so->so_proto->pr_domain->dom_family;
kf->so_rcv_cc = so->so_rcv.sb_cc;
kf->so_snd_cc = so->so_snd.sb_cc;
- if (so->so_splice) {
+ if (isspliced(so)) {
if (show_pointers)
- kf->so_splice = PTRTOINT64(so->so_splice);
- kf->so_splicelen = so->so_splicelen;
- } else if (so->so_spliceback)
+ kf->so_splice =
+ PTRTOINT64(so->so_sp->ssp_socket);
+ kf->so_splicelen = so->so_sp->ssp_len;
+ } else if (issplicedback(so))
kf->so_splicelen = -1;
if (!so->so_pcb)
break;
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index fca6deef310..c848d3881a7 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket.c,v 1.133 2014/09/09 02:07:17 guenther Exp $ */
+/* $OpenBSD: uipc_socket.c,v 1.134 2014/11/03 17:20:46 bluhm Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@@ -80,12 +80,19 @@ int somaxconn = SOMAXCONN;
int sominconn = SOMINCONN;
struct pool socket_pool;
+#ifdef SOCKET_SPLICE
+struct pool sosplice_pool;
+#endif
void
soinit(void)
{
pool_init(&socket_pool, sizeof(struct socket), 0, 0, 0, "sockpl", NULL);
+#ifdef SOCKET_SPLICE
+ pool_init(&sosplice_pool, sizeof(struct sosplice), 0, 0, 0, "sosppl",
+ NULL);
+#endif
}
/*
@@ -157,7 +164,7 @@ solisten(struct socket *so, int backlog)
if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING))
return (EOPNOTSUPP);
#ifdef SOCKET_SPLICE
- if (so->so_splice || so->so_spliceback)
+ if (isspliced(so) || issplicedback(so))
return (EOPNOTSUPP);
#endif /* SOCKET_SPLICE */
s = splsoftnet();
@@ -199,10 +206,15 @@ sofree(struct socket *so)
return;
}
#ifdef SOCKET_SPLICE
- if (so->so_spliceback)
- sounsplice(so->so_spliceback, so, so->so_spliceback != so);
- if (so->so_splice)
- sounsplice(so, so->so_splice, 0);
+ if (so->so_sp) {
+ if (issplicedback(so))
+ sounsplice(so->so_sp->ssp_soback, so,
+ so->so_sp->ssp_soback != so);
+ if (isspliced(so))
+ sounsplice(so, so->so_sp->ssp_socket, 0);
+ pool_put(&sosplice_pool, so->so_sp);
+ so->so_sp = NULL;
+ }
#endif /* SOCKET_SPLICE */
sbrelease(&so->so_snd);
sorflush(so);
@@ -647,7 +659,7 @@ restart:
m = so->so_rcv.sb_mb;
#ifdef SOCKET_SPLICE
- if (so->so_splice)
+ if (isspliced(so))
m = NULL;
#endif /* SOCKET_SPLICE */
/*
@@ -669,7 +681,7 @@ restart:
#ifdef DIAGNOSTIC
if (m == NULL && so->so_rcv.sb_cc)
#ifdef SOCKET_SPLICE
- if (so->so_splice == NULL)
+ if (!isspliced(so))
#endif /* SOCKET_SPLICE */
panic("receive 1");
#endif
@@ -1021,6 +1033,12 @@ sorflush(struct socket *so)
}
#ifdef SOCKET_SPLICE
+
+#define so_splicelen so_sp->ssp_len
+#define so_splicemax so_sp->ssp_max
+#define so_idletv so_sp->ssp_idletv
+#define so_idleto so_sp->ssp_idleto
+
int
sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
{
@@ -1035,6 +1053,8 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
(so->so_proto->pr_flags & PR_CONNREQUIRED))
return (ENOTCONN);
+ if (so->so_sp == NULL)
+ so->so_sp = pool_get(&sosplice_pool, PR_WAITOK | PR_ZERO);
/* If no fd is given, unsplice by removing existing link. */
if (fd < 0) {
@@ -1043,8 +1063,8 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
(so->so_state & SS_NBIO) ? M_NOWAIT : M_WAITOK)) != 0)
return (error);
s = splsoftnet();
- if (so->so_splice)
- sounsplice(so, so->so_splice, 1);
+ if (so->so_sp->ssp_socket)
+ sounsplice(so, so->so_sp->ssp_socket, 1);
splx(s);
sbunlock(&so->so_rcv);
return (0);
@@ -1060,6 +1080,8 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
if ((error = getsock(curproc->p_fd, fd, &fp)) != 0)
return (error);
sosp = fp->f_data;
+ if (sosp->so_sp == NULL)
+ sosp->so_sp = pool_get(&sosplice_pool, PR_WAITOK | PR_ZERO);
/* Lock both receive and send buffer. */
if ((error = sblock(&so->so_rcv,
@@ -1074,7 +1096,7 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
}
s = splsoftnet();
- if (so->so_splice || sosp->so_spliceback) {
+ if (so->so_sp->ssp_socket || sosp->so_sp->ssp_soback) {
error = EBUSY;
goto release;
}
@@ -1092,8 +1114,8 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
}
/* Splice so and sosp together. */
- so->so_splice = sosp;
- sosp->so_spliceback = so;
+ so->so_sp->ssp_socket = sosp;
+ sosp->so_sp->ssp_soback = so;
so->so_splicelen = 0;
so->so_splicemax = max;
if (tv)
@@ -1127,7 +1149,7 @@ sounsplice(struct socket *so, struct socket *sosp, int wakeup)
timeout_del(&so->so_idleto);
sosp->so_snd.sb_flagsintr &= ~SB_SPLICE;
so->so_rcv.sb_flagsintr &= ~SB_SPLICE;
- so->so_splice = sosp->so_spliceback = NULL;
+ so->so_sp->ssp_socket = sosp->so_sp->ssp_soback = NULL;
if (wakeup && soreadable(so))
sorwakeup(so);
}
@@ -1139,9 +1161,9 @@ soidle(void *arg)
int s;
s = splsoftnet();
- if (so->so_splice) {
+ if (so->so_rcv.sb_flagsintr & SB_SPLICE) {
so->so_error = ETIMEDOUT;
- sounsplice(so, so->so_splice, 1);
+ sounsplice(so, so->so_sp->ssp_socket, 1);
}
splx(s);
}
@@ -1155,7 +1177,7 @@ soidle(void *arg)
int
somove(struct socket *so, int wait)
{
- struct socket *sosp = so->so_splice;
+ struct socket *sosp = so->so_sp->ssp_socket;
struct mbuf *m, **mp, *nextrecord;
u_long len, off, oobmark;
long space;
@@ -1408,6 +1430,12 @@ somove(struct socket *so, int wait)
timeout_add_tv(&so->so_idleto, &so->so_idletv);
return (1);
}
+
+#undef so_splicelen
+#undef so_splicemax
+#undef so_idletv
+#undef so_idleto
+
#endif /* SOCKET_SPLICE */
void
@@ -1416,7 +1444,7 @@ sorwakeup(struct socket *so)
#ifdef SOCKET_SPLICE
if (so->so_rcv.sb_flagsintr & SB_SPLICE)
(void) somove(so, M_DONTWAIT);
- if (so->so_splice)
+ if (isspliced(so))
return;
#endif
sowakeup(so, &so->so_rcv);
@@ -1429,7 +1457,7 @@ sowwakeup(struct socket *so)
{
#ifdef SOCKET_SPLICE
if (so->so_snd.sb_flagsintr & SB_SPLICE)
- (void) somove(so->so_spliceback, M_DONTWAIT);
+ (void) somove(so->so_sp->ssp_soback, M_DONTWAIT);
#endif
sowakeup(so, &so->so_snd);
}
@@ -1722,11 +1750,12 @@ sogetopt(struct socket *so, int level, int optname, struct mbuf **mp)
#ifdef SOCKET_SPLICE
case SO_SPLICE:
{
+ off_t len;
int s = splsoftnet();
m->m_len = sizeof(off_t);
- memcpy(mtod(m, off_t *), &so->so_splicelen,
- sizeof(off_t));
+ len = so->so_sp ? so->so_sp->ssp_len : 0;
+ memcpy(mtod(m, off_t *), &len, sizeof(off_t));
splx(s);
break;
}
@@ -1815,7 +1844,7 @@ filt_soread(struct knote *kn, long hint)
kn->kn_data = so->so_rcv.sb_cc;
#ifdef SOCKET_SPLICE
- if (so->so_splice)
+ if (isspliced(so))
return (0);
#endif /* SOCKET_SPLICE */
if (so->so_state & SS_CANTRCVMORE) {
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 922dd5f772f..2ad83b1fbeb 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: socketvar.h,v 1.56 2014/09/09 02:07:17 guenther Exp $ */
+/* $OpenBSD: socketvar.h,v 1.57 2014/11/03 17:20:46 bluhm Exp $ */
/* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */
/*-
@@ -81,13 +81,17 @@ struct socket {
uid_t so_siguid; /* uid of process who set so_pgid */
uid_t so_sigeuid; /* euid of process who set so_pgid */
u_long so_oobmark; /* chars to oob mark */
-
- struct socket *so_splice; /* send data to drain socket */
- struct socket *so_spliceback; /* back ref for notify and cleanup */
- off_t so_splicelen; /* number of bytes spliced so far */
- off_t so_splicemax; /* maximum number of bytes to splice */
- struct timeval so_idletv; /* idle timeout */
- struct timeout so_idleto;
+/*
+ * Variables for socket splicing, allocated only when needed.
+ */
+ struct sosplice {
+ struct socket *ssp_socket; /* send data to drain socket */
+ struct socket *ssp_soback; /* back ref to source socket */
+ off_t ssp_len; /* number of bytes spliced */
+ off_t ssp_max; /* maximum number of bytes */
+ struct timeval ssp_idletv; /* idle timeout */
+ struct timeout ssp_idleto;
+ } *so_sp;
/*
* Variables for socket buffering.
*/
@@ -148,6 +152,9 @@ struct socket {
* Macros for sockets and socket buffering.
*/
+#define isspliced(so) ((so)->so_sp && (so)->so_sp->ssp_socket)
+#define issplicedback(so) ((so)->so_sp && (so)->so_sp->ssp_soback)
+
/*
* Do we need to notify the other side when I/O is possible?
*/
@@ -173,7 +180,7 @@ struct socket {
/* can we read something from so? */
#define soreadable(so) \
- ((so)->so_splice == NULL && \
+ (!isspliced(so) && \
((so)->so_rcv.sb_cc >= (so)->so_rcv.sb_lowat || \
((so)->so_state & SS_CANTRCVMORE) || \
(so)->so_qlen || (so)->so_error))