summaryrefslogtreecommitdiff
path: root/sys/miscfs
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-02-24 03:56:07 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-02-24 03:56:07 +0000
commitb897eb2158e1fffb5f71d142ac086f0dfa725fca (patch)
tree8cd75e686b1307fee8971ec7eb305af08ddefcce /sys/miscfs
parentfbff7ee7ee20b56406603fb14c7c7a2bb3ce5f91 (diff)
FIFO fixes adapted from FreeBSD:
o use different wchan string for reading and writing o make O_RDWR not block forever o remove some useless casts o reorganize the normal, blocking code path (ie: O_NONBLOCK not set) o fix select/poll semantics wrt EOF. With these changes we pass the FIFO regress. OK tedu@
Diffstat (limited to 'sys/miscfs')
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c109
1 files changed, 53 insertions, 56 deletions
diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c
index 0fecb45b806..74e9eb51a64 100644
--- a/sys/miscfs/fifofs/fifo_vnops.c
+++ b/sys/miscfs/fifofs/fifo_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fifo_vnops.c,v 1.17 2004/01/28 23:53:57 millert Exp $ */
+/* $OpenBSD: fifo_vnops.c,v 1.18 2004/02/24 03:56:06 millert Exp $ */
/* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */
/*
@@ -162,7 +162,6 @@ fifo_open(v)
struct proc *p = ap->a_p;
struct socket *rso, *wso;
int error;
- static char openstr[] = "fifo";
if ((fip = vp->v_fifoinfo) == NULL) {
MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
@@ -188,49 +187,43 @@ fifo_open(v)
return (error);
}
fip->fi_readers = fip->fi_writers = 0;
- wso->so_state |= SS_CANTRCVMORE;
- rso->so_state |= SS_CANTSENDMORE;
+ wso->so_snd.sb_lowat = PIPE_BUF;
+ rso->so_state |= SS_CANTRCVMORE;
}
if (ap->a_mode & FREAD) {
if (fip->fi_readers++ == 0) {
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
if (fip->fi_writers > 0)
- wakeup((caddr_t)&fip->fi_writers);
+ wakeup(&fip->fi_writers);
+ }
+ }
+ if (ap->a_mode & FWRITE) {
+ if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
+ error = ENXIO;
+ goto bad;
}
- } else if (ap->a_mode & FWRITE) {
if (fip->fi_writers++ == 0) {
fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
if (fip->fi_readers > 0)
- wakeup((caddr_t)&fip->fi_readers);
+ wakeup(&fip->fi_readers);
}
}
- if (ap->a_mode & FREAD) {
- if (ap->a_mode & O_NONBLOCK) {
- } else {
- while (fip->fi_writers == 0) {
- VOP_UNLOCK(vp, 0, p);
- error = tsleep((caddr_t)&fip->fi_readers,
- PCATCH | PSOCK, openstr, 0);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- if (error)
- goto bad;
- }
+ if ((ap->a_mode & O_NONBLOCK) == 0) {
+ if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
+ VOP_UNLOCK(vp, 0, p);
+ error = tsleep(&fip->fi_readers,
+ PCATCH | PSOCK, "fifor", 0);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (error)
+ goto bad;
}
- } else if (ap->a_mode & FWRITE) {
- if (ap->a_mode & O_NONBLOCK) {
- if (fip->fi_readers == 0) {
- error = ENXIO;
+ if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
+ VOP_UNLOCK(vp, 0, p);
+ error = tsleep(&fip->fi_writers,
+ PCATCH | PSOCK, "fifow", 0);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (error)
goto bad;
- }
- } else {
- while (fip->fi_readers == 0) {
- VOP_UNLOCK(vp, 0, p);
- error = tsleep((caddr_t)&fip->fi_writers,
- PCATCH | PSOCK, openstr, 0);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- if (error)
- goto bad;
- }
}
}
return (0);
@@ -256,7 +249,7 @@ fifo_read(v)
register struct uio *uio = ap->a_uio;
register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
struct proc *p = uio->uio_procp;
- int error, startresid;
+ int error;
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_READ)
@@ -266,21 +259,15 @@ fifo_read(v)
return (0);
if (ap->a_ioflag & IO_NDELAY)
rso->so_state |= SS_NBIO;
- startresid = uio->uio_resid;
VOP_UNLOCK(ap->a_vp, 0, p);
- error = soreceive(rso, (struct mbuf **)0, uio, (struct mbuf **)0,
- (struct mbuf **)0, (int *)0);
+ error = soreceive(rso, NULL, uio, NULL, NULL, NULL);
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
- /*
- * Clear EOF indication after first such return.
- */
- if (uio->uio_resid == startresid)
- rso->so_state &= ~SS_CANTRCVMORE;
- if (ap->a_ioflag & IO_NDELAY)
+ if (ap->a_ioflag & IO_NDELAY) {
rso->so_state &= ~SS_NBIO;
- if ((ap->a_ioflag & IO_NDELAY) && error == EWOULDBLOCK &&
- ap->a_vp->v_fifoinfo->fi_writers == 0)
- error = 0;
+ if (error == EWOULDBLOCK &&
+ ap->a_vp->v_fifoinfo->fi_writers == 0)
+ error = 0;
+ }
return (error);
}
@@ -309,7 +296,7 @@ fifo_write(v)
if (ap->a_ioflag & IO_NDELAY)
wso->so_state |= SS_NBIO;
VOP_UNLOCK(ap->a_vp, 0, p);
- error = sosend(wso, (struct mbuf *)0, ap->a_uio, 0, (struct mbuf *)0, 0);
+ error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0);
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
if (ap->a_ioflag & IO_NDELAY)
wso->so_state &= ~SS_NBIO;
@@ -363,12 +350,24 @@ fifo_poll(v)
struct proc *a_p;
} */ *ap = v;
struct file filetmp;
+ short ostate;
int revents = 0;
if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
+ /*
+ * Socket and FIFO poll(2) semantics differ wrt EOF on read.
+ * Unlike a normal socket, FIFOs don't care whether or not
+ * SS_CANTRCVMORE is set. To get the correct semantics we
+ * must clear SS_CANTRCVMORE from so_state temporarily.
+ */
+ ostate = ap->a_vp->v_fifoinfo->fi_readsock->so_state;
+ if (ap->a_events & (POLLIN | POLLRDNORM))
+ ap->a_vp->v_fifoinfo->fi_readsock->so_state &=
+ ~SS_CANTRCVMORE;
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
if (filetmp.f_data)
revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
+ ap->a_vp->v_fifoinfo->fi_readsock->so_state = ostate;
}
if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
@@ -429,7 +428,7 @@ fifo_close(v)
} */ *ap = v;
register struct vnode *vp = ap->a_vp;
register struct fifoinfo *fip = vp->v_fifoinfo;
- int error1, error2;
+ int error1 = 0, error2 = 0;
if (ap->a_fflag & FREAD) {
if (--fip->fi_readers == 0)
@@ -439,15 +438,13 @@ fifo_close(v)
if (--fip->fi_writers == 0)
socantrcvmore(fip->fi_readsock);
}
- if (fip->fi_readers != 0 || fip->fi_writers != 0)
- return (0);
- error1 = soclose(fip->fi_readsock);
- error2 = soclose(fip->fi_writesock);
- FREE(fip, M_VNODE);
- vp->v_fifoinfo = NULL;
- if (error1)
- return (error1);
- return (error2);
+ if (fip->fi_readers == 0 && fip->fi_writers == 0) {
+ error1 = soclose(fip->fi_readsock);
+ error2 = soclose(fip->fi_writesock);
+ FREE(fip, M_VNODE);
+ vp->v_fifoinfo = NULL;
+ }
+ return (error1 ? error1 : error2);
}
/*