summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_subr.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/kern_subr.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/kern_subr.c')
-rw-r--r--sys/kern/kern_subr.c42
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);
+
+}
OpenPOWER on IntegriCloud