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:
parent
e9023155ad
commit
25bef3c837
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue