summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/syscall/sendfile.c
diff options
context:
space:
mode:
authorjohansen <none@none>2005-08-08 17:49:52 -0700
committerjohansen <none@none>2005-08-08 17:49:52 -0700
commit1574ae68edf276820812b92d6c9f22e8f4049860 (patch)
treecac3ee831e8239238b4cb4fd5cd2a5497a996f13 /usr/src/uts/common/syscall/sendfile.c
parentb610f78eb3ffbdbc0436ad4f8646ed839b30dfe9 (diff)
downloadillumos-gate-1574ae68edf276820812b92d6c9f22e8f4049860.tar.gz
6303489 sendfile is wasteful when sending regular files
Diffstat (limited to 'usr/src/uts/common/syscall/sendfile.c')
-rw-r--r--usr/src/uts/common/syscall/sendfile.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/usr/src/uts/common/syscall/sendfile.c b/usr/src/uts/common/syscall/sendfile.c
index 2f504af827..2a3e29a859 100644
--- a/usr/src/uts/common/syscall/sendfile.c
+++ b/usr/src/uts/common/syscall/sendfile.c
@@ -668,7 +668,8 @@ sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
#else
const u_offset_t maxoff = MAXOFF32_T;
#endif
- mblk_t *dmp;
+ mblk_t *dmp = NULL;
+ char *buf = NULL;
fflag = fp->f_flag;
vp = fp->f_vnode;
@@ -835,18 +836,32 @@ sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
readvp->v_vfsp->vfs_bsize);
size = sfv_len < size ? sfv_len : size;
+ if (vp->v_type != VSOCK) {
+ buf = kmem_alloc(size, KM_NOSLEEP);
+ if (buf == NULL) {
+ VOP_RWUNLOCK(readvp, readflg, NULL);
+ releasef(sfv->sfv_fd);
+ return (ENOMEM);
+ }
+ }
+
while (sfv_len > 0) {
size_t iov_len;
iov_len = MIN(size, sfv_len);
- dmp = allocb(iov_len, BPRI_HI);
- if (dmp == NULL) {
- VOP_RWUNLOCK(readvp, readflg, NULL);
- releasef(sfv->sfv_fd);
- return (ENOMEM);
+ if (vp->v_type == VSOCK) {
+ dmp = allocb(iov_len, BPRI_HI);
+ if (dmp == NULL) {
+ VOP_RWUNLOCK(readvp, readflg,
+ NULL);
+ releasef(sfv->sfv_fd);
+ return (ENOMEM);
+ }
+ ptr = (caddr_t)dmp->b_rptr;
+ } else {
+ ptr = buf;
}
- ptr = (caddr_t)dmp->b_rptr;
aiov.iov_base = ptr;
aiov.iov_len = iov_len;
@@ -874,7 +889,10 @@ sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
* not implemented), we may now lose
* data.
*/
- freeb(dmp);
+ if (vp->v_type == VSOCK)
+ freeb(dmp);
+ else
+ kmem_free(buf, size);
VOP_RWUNLOCK(readvp, readflg, NULL);
releasef(sfv->sfv_fd);
return (error);
@@ -887,7 +905,10 @@ sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
*/
cnt = iov_len - auio.uio_resid;
if (cnt == 0) {
- freeb(dmp);
+ if (vp->v_type == VSOCK)
+ freeb(dmp);
+ else
+ kmem_free(buf, size);
VOP_RWUNLOCK(readvp, readflg, NULL);
releasef(sfv->sfv_fd);
return (EINVAL);
@@ -937,7 +958,6 @@ sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
(ulong_t)cnt;
*fileoff += cnt;
*count += cnt;
- freeb(dmp);
if (error != 0) {
VOP_RWUNLOCK(readvp, readflg,
NULL);
@@ -946,6 +966,10 @@ sendvec_chunk(file_t *fp, u_offset_t *fileoff, struct sendfilevec *sfv,
}
}
}
+ if (buf) {
+ kmem_free(buf, size);
+ buf = NULL;
+ }
VOP_RWUNLOCK(readvp, readflg, NULL);
releasef(sfv->sfv_fd);
}