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/kern_subr.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/kern_subr.c')
-rw-r--r-- | sys/kern/kern_subr.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index a078b11..69ce291 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -483,3 +483,45 @@ copyinstrfrom(const void * __restrict src, void * __restrict dst, size_t len, } return (error); } + +int +iov_to_uio(struct iovec *iovp, u_int iovcnt, struct uio *auio) +{ + int error = 0, i; + u_int iovlen; + struct iovec *iov = NULL; + + if (iovcnt < 0) + panic("iovcnt < 0!\n"); + + /* note: can't use iovlen until iovcnt is validated */ + iovlen = iovcnt * sizeof (struct iovec); + if (iovcnt > UIO_MAXIOV) { + error = EINVAL; + goto done; + } + MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); + auio->uio_iov = iov; + auio->uio_iovcnt = iovcnt; + auio->uio_segflg = UIO_USERSPACE; + auio->uio_offset = -1; + if ((error = copyin(iovp, iov, iovlen))) + goto done; + auio->uio_resid = 0; + for (i = 0; i < iovcnt; i++) { + if (iov->iov_len > INT_MAX - auio->uio_resid) { + error = EINVAL; + goto done; + } + auio->uio_resid += iov->iov_len; + iov++; + } + +done: + if (error && auio->uio_iov) { + FREE(auio->uio_iov, M_IOV); + auio->uio_iov = NULL; + } + return (error); + +} |