diff options
author | johansen <none@none> | 2005-08-08 17:49:52 -0700 |
---|---|---|
committer | johansen <none@none> | 2005-08-08 17:49:52 -0700 |
commit | 1574ae68edf276820812b92d6c9f22e8f4049860 (patch) | |
tree | cac3ee831e8239238b4cb4fd5cd2a5497a996f13 /usr/src/uts/common/syscall/sendfile.c | |
parent | b610f78eb3ffbdbc0436ad4f8646ed839b30dfe9 (diff) | |
download | illumos-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.c | 44 |
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); } |