summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sendfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_sendfile.c')
-rw-r--r--sys/kern/kern_sendfile.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c
index a2e1311..7ee7780 100644
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -516,7 +516,7 @@ sendfile_getsock(struct thread *td, int s, struct file **sock_fp,
int
vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
- int kflags, struct thread *td)
+ struct thread *td)
{
struct file *sock_fp;
struct vnode *vp;
@@ -534,7 +534,7 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
so = NULL;
m = mh = NULL;
sfs = NULL;
- sbytes = 0;
+ hdrlen = sbytes = 0;
softerr = 0;
error = sendfile_getobj(td, fp, &obj, &vp, &shmfd, &obj_size, &bsize);
@@ -560,26 +560,6 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
cv_init(&sfs->cv, "sendfile");
}
- /* If headers are specified copy them into mbufs. */
- if (hdr_uio != NULL && hdr_uio->uio_resid > 0) {
- hdr_uio->uio_td = td;
- hdr_uio->uio_rw = UIO_WRITE;
- /*
- * In FBSD < 5.0 the nbytes to send also included
- * the header. If compat is specified subtract the
- * header size from nbytes.
- */
- if (kflags & SFK_COMPAT) {
- if (nbytes > hdr_uio->uio_resid)
- nbytes -= hdr_uio->uio_resid;
- else
- nbytes = 0;
- }
- mh = m_uiotombuf(hdr_uio, M_WAITOK, 0, 0, 0);
- hdrlen = m_length(mh, &mhtail);
- } else
- hdrlen = 0;
-
rem = nbytes ? omin(nbytes, obj_size - offset) : obj_size - offset;
/*
@@ -668,11 +648,20 @@ retry_space:
SOCKBUF_UNLOCK(&so->so_snd);
/*
- * Reduce space in the socket buffer by the size of
- * the header mbuf chain.
- * hdrlen is set to 0 after the first loop.
+ * At the beginning of the first loop check if any headers
+ * are specified and copy them into mbufs. Reduce space in
+ * the socket buffer by the size of the header mbuf chain.
+ * Clear hdr_uio here and hdrlen at the end of the first loop.
*/
- space -= hdrlen;
+ if (hdr_uio != NULL && hdr_uio->uio_resid > 0) {
+ hdr_uio->uio_td = td;
+ hdr_uio->uio_rw = UIO_WRITE;
+ hdr_uio->uio_resid = min(hdr_uio->uio_resid, space);
+ mh = m_uiotombuf(hdr_uio, M_WAITOK, 0, 0, 0);
+ hdrlen = m_length(mh, &mhtail);
+ space -= hdrlen;
+ hdr_uio = NULL;
+ }
if (vp != NULL) {
error = vn_lock(vp, LK_SHARED);
@@ -944,6 +933,19 @@ sendfile(struct thread *td, struct sendfile_args *uap, int compat)
&hdr_uio);
if (error != 0)
goto out;
+#ifdef COMPAT_FREEBSD4
+ /*
+ * In FreeBSD < 5.0 the nbytes to send also included
+ * the header. If compat is specified subtract the
+ * header size from nbytes.
+ */
+ if (compat) {
+ if (uap->nbytes > hdr_uio->uio_resid)
+ uap->nbytes -= hdr_uio->uio_resid;
+ else
+ uap->nbytes = 0;
+ }
+#endif
}
if (hdtr.trailers != NULL) {
error = copyinuio(hdtr.trailers, hdtr.trl_cnt,
@@ -965,7 +967,7 @@ sendfile(struct thread *td, struct sendfile_args *uap, int compat)
}
error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, uap->offset,
- uap->nbytes, &sbytes, uap->flags, compat ? SFK_COMPAT : 0, td);
+ uap->nbytes, &sbytes, uap->flags, td);
fdrop(fp, td);
if (uap->sbytes != NULL)
OpenPOWER on IntegriCloud