diff options
author | silby <silby@FreeBSD.org> | 2004-02-01 07:56:44 +0000 |
---|---|---|
committer | silby <silby@FreeBSD.org> | 2004-02-01 07:56:44 +0000 |
commit | a4c32edec5d4168f026935747d80ffd7e14b341e (patch) | |
tree | 756eb5d016933d260c886eb87ddce614194e5d5f /sys/kern/uipc_mbuf.c | |
parent | 371f8838d17c51a366148891b8df059a38604325 (diff) | |
download | FreeBSD-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.c | 56 |
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); +} |