Take care to transfer whole buffer passed via write(2); write(2) should

not do short writes unless when using non-blocking I/O.
This fixes kern/13744 by Geoff C. Wing.

Note this partially undoes rev. 1.5 change. Upon closer examination,
it's been apparent that hbench-OS expectations were not actually justified.
This commit is contained in:
jdolecek 2001-09-25 19:01:21 +00:00
parent e9023155ad
commit 25bef3c837
1 changed files with 23 additions and 19 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_pipe.c,v 1.13 2001/09/22 05:58:04 jdolecek Exp $ */
/* $NetBSD: sys_pipe.c,v 1.14 2001/09/25 19:01:21 jdolecek Exp $ */
/*
* Copyright (c) 1996 John S. Dyson
@ -1013,14 +1013,12 @@ retry:
}
/*
* Handle first iovec, first PIPE_CHUNK_SIZE bytes. Expect caller
* to deal with short write.
*
* Note: need to deal with buffers not aligned to PAGE_SIZE.
* Handle first PIPE_CHUNK_SIZE bytes of buffer. Deal with buffers
* not aligned to PAGE_SIZE.
*/
bbase = (vaddr_t)uio->uio_iov[0].iov_base;
bbase = (vaddr_t)uio->uio_iov->iov_base;
base = trunc_page(bbase);
bend = round_page(bbase + uio->uio_iov[0].iov_len);
bend = round_page(bbase + uio->uio_iov->iov_len);
blen = bend - base;
bpos = bbase - base;
@ -1029,7 +1027,7 @@ retry:
bend = base + blen;
bcnt = PIPE_DIRECT_CHUNK - bpos;
} else
bcnt = uio->uio_iov[0].iov_len;
bcnt = uio->uio_iov->iov_len;
npages = blen / PAGE_SIZE;
@ -1109,6 +1107,12 @@ retry:
uio->uio_resid -= bcnt;
/* uio_offset not updated, not set/used for write(2) */
(char *) uio->uio_iov->iov_base += bcnt;
uio->uio_iov->iov_len -= bcnt;
if (uio->uio_iov->iov_len == 0) {
uio->uio_iov++;
uio->uio_iovcnt--;
}
return (0);
}
@ -1135,7 +1139,6 @@ pipe_write(fp, offset, uio, cred, flags)
#endif
{
int error = 0;
int orig_resid;
struct pipe *wpipe, *rpipe;
rpipe = (struct pipe *) fp->f_data;
@ -1186,7 +1189,6 @@ pipe_write(fp, offset, uio, cred, flags)
KASSERT(wpipe->pipe_buffer.buffer != NULL, ("pipe buffer gone"));
#endif
orig_resid = uio->uio_resid;
while (uio->uio_resid) {
int space;
@ -1200,19 +1202,21 @@ pipe_write(fp, offset, uio, cred, flags)
* The direct write mechanism will detect the reader going
* away on us.
*/
if ((uio->uio_iov[0].iov_len >= PIPE_MINDIRECT) &&
(uio->uio_resid == orig_resid) &&
if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) &&
(fp->f_flag & FNONBLOCK) == 0 &&
(wpipe->pipe_map.kva || (amountpipekva < limitpipekva))) {
error = pipe_direct_write(wpipe, uio);
/*
* We either errorred, wrote whole buffer, or
* wrote part of buffer. If the error is ENOMEM,
* we failed to allocate some resources for direct
* write and fall back to ordinary write. Otherwise,
* break out now.
* Break out if error occured, unless it's ENOMEM.
* ENOMEM means we failed to allocate some resources
* for direct write, so we just fallback to ordinary
* write. If the direct write was successful,
* process rest of data via ordinary write.
*/
if (!error)
continue;
if (error != ENOMEM)
break;
}
@ -1245,7 +1249,7 @@ pipe_write(fp, offset, uio, cred, flags)
space = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
/* Writes of size <= PIPE_BUF must be atomic. */
if ((space < uio->uio_resid) && (orig_resid <= PIPE_BUF))
if ((space < uio->uio_resid) && (uio->uio_resid <= PIPE_BUF))
space = 0;
if (space > 0 && (wpipe->pipe_buffer.cnt < PIPE_SIZE)) {
@ -1404,7 +1408,7 @@ pipe_write(fp, offset, uio, cred, flags)
/*
* We have something to offer, wake up select/poll.
* wpipe->pipe_map.cnt is always 0 in this point (direct write
* is only done synchronously), so check wpipe->only pipe_buffer.cnt
* is only done synchronously), so check only wpipe->pipe_buffer.cnt
*/
if (wpipe->pipe_buffer.cnt)
pipeselwakeup(wpipe, wpipe);