summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_mbuf.c
diff options
context:
space:
mode:
authorsilby <silby@FreeBSD.org>2004-02-01 07:56:44 +0000
committersilby <silby@FreeBSD.org>2004-02-01 07:56:44 +0000
commita4c32edec5d4168f026935747d80ffd7e14b341e (patch)
tree756eb5d016933d260c886eb87ddce614194e5d5f /sys/kern/uipc_mbuf.c
parent371f8838d17c51a366148891b8df059a38604325 (diff)
downloadFreeBSD-src-a4c32edec5d4168f026935747d80ffd7e14b341e.zip
FreeBSD-src-a4c32edec5d4168f026935747d80ffd7e14b341e.tar.gz
Rewrite sendfile's header support so that headers are now sent in the first
packet along with data, instead of in their own packet. When serving files of size (packetsize - headersize) or smaller, this will result in one less packet crossing the network. Quick testing with thttpd and http_load has shown a noticeable performance improvement in this case (350 vs 330 fetches per second.) Included in this commit are two support routines, iov_to_uio, and m_uiotombuf; these routines are used by sendfile to construct the header mbuf chain that will be linked to the rest of the data in the socket buffer.
Diffstat (limited to 'sys/kern/uipc_mbuf.c')
-rw-r--r--sys/kern/uipc_mbuf.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 1af7f2c..4a53f17 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/mac.h>
#include <sys/malloc.h>
@@ -50,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/domain.h>
#include <sys/protosw.h>
+#include <sys/uio.h>
int max_linkhdr;
int max_protohdr;
@@ -1028,3 +1030,57 @@ nospace:
}
#endif
+
+struct mbuf *
+m_uiotombuf(struct uio *uio, int how, int len)
+{
+ struct mbuf *m_new = NULL, *m_final = NULL;
+ int progress = 0, error = 0, length, total;
+
+ if (len > 0)
+ total = min(uio->uio_resid, len);
+ else
+ total = uio->uio_resid;
+
+ if (total > MHLEN)
+ m_final = m_getcl(how, MT_DATA, M_PKTHDR);
+ else
+ m_final = m_gethdr(how, MT_DATA);
+
+ if (m_final == NULL)
+ goto nospace;
+
+ m_new = m_final;
+
+ while (progress < total) {
+ length = total - progress;
+ if (length > MCLBYTES)
+ length = MCLBYTES;
+
+ if (m_new == NULL) {
+ if (length > MLEN)
+ m_new = m_getcl(how, MT_DATA, 0);
+ else
+ m_new = m_get(how, MT_DATA);
+ if (m_new == NULL)
+ goto nospace;
+ }
+
+ error = uiomove(mtod(m_new, void *), length, uio);
+ if (error)
+ goto nospace;
+ progress += length;
+ m_new->m_len = length;
+ if (m_new != m_final)
+ m_cat(m_final, m_new);
+ m_new = NULL;
+ }
+ m_fixhdr(m_final);
+ return (m_final);
+nospace:
+ if (m_new)
+ m_free(m_new);
+ if (m_final)
+ m_freem(m_final);
+ return (NULL);
+}
OpenPOWER on IntegriCloud