From 3bcb6e5e80cb05cecaddd866d4b15b428334b9aa Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Fri, 23 Sep 2011 14:23:53 +0800 Subject: [PATCH] kevent: Restore old EV_EOF semantics - EV_EOF should be set when the other side closed the connection, even if there are data pending in the read buffer (the old semantics). - EV_NODATA is added to indicate there are no more data pending in the buffer and EOF is detected (EV_EOF is also set in this situation). Kernel code now tests EV_NODATA instead of EV_EOF, since EV_NODATA delivers the information which was delivered by the EV_EOF before this commit. DragonFly-Bug: http://bugs.dragonflybsd.org/issue1998 --- sys/dev/misc/cmx/cmx.c | 2 +- sys/dev/misc/kbd/kbd.c | 3 ++- sys/dev/video/bktr/bktr_os.c | 2 +- sys/dev/video/cxm/cxm.c | 2 +- sys/kern/kern_event.c | 2 +- sys/kern/sys_generic.c | 8 ++++---- sys/kern/sys_pipe.c | 14 ++++++++------ sys/kern/tty.c | 2 +- sys/kern/tty_pty.c | 4 ++-- sys/kern/uipc_socket.c | 12 +++++++----- sys/sys/event.h | 1 + sys/vfs/devfs/devfs_core.c | 2 +- sys/vfs/fifofs/fifo_vnops.c | 10 ++++++---- sys/vfs/gnu/ext2fs/ext2_vnops.c | 6 +++--- sys/vfs/hammer/hammer_vnops.c | 6 +++--- sys/vfs/tmpfs/tmpfs_vnops.c | 6 +++--- sys/vfs/ufs/ufs_vnops.c | 6 +++--- 17 files changed, 48 insertions(+), 40 deletions(-) diff --git a/sys/dev/misc/cmx/cmx.c b/sys/dev/misc/cmx/cmx.c index 9174fae457..815590cedb 100644 --- a/sys/dev/misc/cmx/cmx.c +++ b/sys/dev/misc/cmx/cmx.c @@ -702,7 +702,7 @@ cmx_filter_read(struct knote *kn, long hint) uint8_t bsr = 0; if (sc == NULL || sc->dying) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); return (1); } diff --git a/sys/dev/misc/kbd/kbd.c b/sys/dev/misc/kbd/kbd.c index b39133ef42..3c9ecc57f4 100644 --- a/sys/dev/misc/kbd/kbd.c +++ b/sys/dev/misc/kbd/kbd.c @@ -924,7 +924,8 @@ genkbdfilter(struct knote *kn, long hint) sc = dev->si_drv1; kbd = kbd_get_keyboard(KBD_INDEX(dev)); if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { - kn->kn_flags |= EV_EOF; /* the keyboard has gone */ + /* The keyboard has gone */ + kn->kn_flags |= (EV_EOF | EV_NODATA); ready = 1; } else { if (sc->gkb_q_length > 0) diff --git a/sys/dev/video/bktr/bktr_os.c b/sys/dev/video/bktr/bktr_os.c index 07240752db..710cedccf1 100644 --- a/sys/dev/video/bktr/bktr_os.c +++ b/sys/dev/video/bktr/bktr_os.c @@ -772,7 +772,7 @@ bktr_filter(struct knote *kn, long hint) if (bktr == NULL) { /* the device is no longer valid/functioning */ - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); return (1); } diff --git a/sys/dev/video/cxm/cxm.c b/sys/dev/video/cxm/cxm.c index ed83036b83..2b9ee89ece 100644 --- a/sys/dev/video/cxm/cxm.c +++ b/sys/dev/video/cxm/cxm.c @@ -2954,7 +2954,7 @@ cxm_filter(struct knote *kn, long hint) if (sc == NULL) { /* the device is no longer valid/functioning */ - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); return (1); } diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index bd5ac9a3d9..f475cf13a1 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -300,7 +300,7 @@ filt_proc(struct knote *kn, long hint) kn->kn_data = p->p_xstat; kn->kn_ptr.p_proc = NULL; } - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); return (1); } diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 050813df4c..42cbc3bf0d 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1375,12 +1375,12 @@ poll_copyout(void *arg, struct kevent *kevp, int count, int *res) case EVFILT_READ: #if 0 /* - * EOF on the read side can indicate a + * NODATA on the read side can indicate a * half-closed situation and not necessarily * a disconnect, so depend on the user * issuing a read() and getting 0 bytes back. */ - if (kevp[i].flags & EV_EOF) + if (kevp[i].flags & EV_NODATA) pfd->revents |= POLLHUP; #endif if (pfd->events & POLLIN) @@ -1397,7 +1397,7 @@ poll_copyout(void *arg, struct kevent *kevp, int count, int *res) * In this case a disconnect is implied even * for a half-closed (write side) situation. */ - if (kevp[i].flags & EV_EOF) { + if (kevp[i].flags & EV_NODATA) { pfd->revents |= POLLHUP; } else { if (pfd->events & POLLOUT) @@ -1408,7 +1408,7 @@ poll_copyout(void *arg, struct kevent *kevp, int count, int *res) break; case EVFILT_EXCEPT: /* - * EV_EOF should never be tagged for this + * EV_NODATA should never be tagged for this * filter. */ if (pfd->events & POLLPRI) diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 5f14a90e12..9a36d75279 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1243,10 +1243,12 @@ filt_piperead(struct knote *kn, long hint) kn->kn_data = rpipe->pipe_buffer.windex - rpipe->pipe_buffer.rindex; - /* - * Only set EOF if all data has been exhausted - */ - if ((rpipe->pipe_state & PIPE_REOF) && kn->kn_data == 0) { + if (rpipe->pipe_state & PIPE_REOF) { + /* + * Only set NODATA if all data has been exhausted + */ + if (kn->kn_data == 0) + kn->kn_flags |= EV_NODATA; kn->kn_flags |= EV_EOF; ready = 1; } @@ -1270,7 +1272,7 @@ filt_pipewrite(struct knote *kn, long hint) kn->kn_data = 0; if (wpipe == NULL) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); return (1); } @@ -1278,7 +1280,7 @@ filt_pipewrite(struct knote *kn, long hint) lwkt_gettoken(&wpipe->pipe_wlock); if (wpipe->pipe_state & PIPE_WEOF) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); ready = 1; } diff --git a/sys/kern/tty.c b/sys/kern/tty.c index e616e1c4dd..21af56005a 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -1354,7 +1354,7 @@ filt_ttyread(struct knote *kn, long hint) lwkt_gettoken(&tty_token); kn->kn_data = ttnread(tp); if (ISSET(tp->t_state, TS_ZOMBIE)) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); lwkt_reltoken(&tty_token); return (1); } diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index cd553daace..99337f1c7d 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -890,7 +890,7 @@ filt_ptcread (struct knote *kn, long hint) lwkt_gettoken(&tty_token); if ((tp->t_state & TS_ZOMBIE) || (pti->pt_flags & PF_SCLOSED)) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); lwkt_reltoken(&tty_token); return (1); } @@ -916,7 +916,7 @@ filt_ptcwrite (struct knote *kn, long hint) lwkt_gettoken(&tty_token); if (tp->t_state & TS_ZOMBIE) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); lwkt_reltoken(&tty_token); return (1); } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 204ff48a49..b20eb28d04 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1811,10 +1811,12 @@ filt_soread(struct knote *kn, long hint) } kn->kn_data = so->so_rcv.ssb_cc; - /* - * Only set EOF if all data has been exhausted. - */ - if ((so->so_state & SS_CANTRCVMORE) && kn->kn_data == 0) { + if (so->so_state & SS_CANTRCVMORE) { + /* + * Only set NODATA if all data has been exhausted. + */ + if (kn->kn_data == 0) + kn->kn_flags |= EV_NODATA; kn->kn_flags |= EV_EOF; kn->kn_fflags = so->so_error; return (1); @@ -1845,7 +1847,7 @@ filt_sowrite(struct knote *kn, long hint) kn->kn_data = ssb_space(&so->so_snd); if (so->so_state & SS_CANTSENDMORE) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); kn->kn_fflags = so->so_error; return (1); } diff --git a/sys/sys/event.h b/sys/sys/event.h index 396fdabc31..c39a6e7155 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -88,6 +88,7 @@ struct kevent { /* returned values */ #define EV_EOF 0x8000 /* EOF detected */ #define EV_ERROR 0x4000 /* error, data contains errno */ +#define EV_NODATA 0x1000 /* EOF and no more data */ /* * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace diff --git a/sys/vfs/devfs/devfs_core.c b/sys/vfs/devfs/devfs_core.c index 65f90f759d..f5ddfe5406 100644 --- a/sys/vfs/devfs/devfs_core.c +++ b/sys/vfs/devfs/devfs_core.c @@ -2305,7 +2305,7 @@ devfs_cdev_unlock(cdev_t dev) static int devfs_detached_filter_eof(struct knote *kn, long hint) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); return (1); } diff --git a/sys/vfs/fifofs/fifo_vnops.c b/sys/vfs/fifofs/fifo_vnops.c index 0c572ad9d9..22e2a5a4aa 100644 --- a/sys/vfs/fifofs/fifo_vnops.c +++ b/sys/vfs/fifofs/fifo_vnops.c @@ -422,12 +422,14 @@ filt_fiforead(struct knote *kn, long hint) lwkt_gettoken(&vp->v_token); kn->kn_data = so->so_rcv.ssb_cc; - if ((so->so_state & SS_ISDISCONNECTED) && kn->kn_data == 0) { + if (so->so_state & SS_ISDISCONNECTED) { + if (kn->kn_data == 0) + kn->kn_flags |= EV_NODATA; kn->kn_flags |= EV_EOF; lwkt_reltoken(&vp->v_token); return (1); } - kn->kn_flags &= ~EV_EOF; + kn->kn_flags &= ~(EV_EOF | EV_NODATA); lwkt_reltoken(&vp->v_token); return (kn->kn_data > 0); } @@ -452,11 +454,11 @@ filt_fifowrite(struct knote *kn, long hint) lwkt_gettoken(&vp->v_token); kn->kn_data = ssb_space(&so->so_snd); if (so->so_state & SS_ISDISCONNECTED) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); lwkt_reltoken(&vp->v_token); return (1); } - kn->kn_flags &= ~EV_EOF; + kn->kn_flags &= ~(EV_EOF | EV_NODATA); lwkt_reltoken(&vp->v_token); return (kn->kn_data >= so->so_snd.ssb_lowat); } diff --git a/sys/vfs/gnu/ext2fs/ext2_vnops.c b/sys/vfs/gnu/ext2fs/ext2_vnops.c index c04dbaaad7..790ed9a747 100644 --- a/sys/vfs/gnu/ext2fs/ext2_vnops.c +++ b/sys/vfs/gnu/ext2fs/ext2_vnops.c @@ -1989,7 +1989,7 @@ filt_ext2read(struct knote *kn, long hint) * the knote for deletion. */ if (hint == NOTE_REVOKE) { - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); return (1); } off = ip->i_size - kn->kn_fp->f_offset; @@ -2008,7 +2008,7 @@ filt_ext2write(struct knote *kn, long hint) * the knote for deletion. */ if (hint == NOTE_REVOKE) - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); kn->kn_data = 0; return (1); @@ -2020,7 +2020,7 @@ filt_ext2vnode(struct knote *kn, long hint) if (kn->kn_sfflags & hint) kn->kn_fflags |= hint; if (hint == NOTE_REVOKE) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); return (1); } return (kn->kn_fflags != 0); diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 533cc249eb..e5101d721a 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -3661,7 +3661,7 @@ filt_hammerread(struct knote *kn, long hint) off_t off; if (hint == NOTE_REVOKE) { - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); return(1); } lwkt_gettoken(&hmp->fs_token); /* XXX use per-ip-token */ @@ -3677,7 +3677,7 @@ static int filt_hammerwrite(struct knote *kn, long hint) { if (hint == NOTE_REVOKE) - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); kn->kn_data = 0; return (1); } @@ -3688,7 +3688,7 @@ filt_hammervnode(struct knote *kn, long hint) if (kn->kn_sfflags & hint) kn->kn_fflags |= hint; if (hint == NOTE_REVOKE) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); return (1); } return (kn->kn_fflags != 0); diff --git a/sys/vfs/tmpfs/tmpfs_vnops.c b/sys/vfs/tmpfs/tmpfs_vnops.c index c2ea751d3d..c740d46b37 100644 --- a/sys/vfs/tmpfs/tmpfs_vnops.c +++ b/sys/vfs/tmpfs/tmpfs_vnops.c @@ -1579,7 +1579,7 @@ filt_tmpfsread(struct knote *kn, long hint) off_t off; if (hint == NOTE_REVOKE) { - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); return(1); } @@ -1605,7 +1605,7 @@ static int filt_tmpfswrite(struct knote *kn, long hint) { if (hint == NOTE_REVOKE) - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); kn->kn_data = 0; return (1); } @@ -1616,7 +1616,7 @@ filt_tmpfsvnode(struct knote *kn, long hint) if (kn->kn_sfflags & hint) kn->kn_fflags |= hint; if (hint == NOTE_REVOKE) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); return (1); } return (kn->kn_fflags != 0); diff --git a/sys/vfs/ufs/ufs_vnops.c b/sys/vfs/ufs/ufs_vnops.c index 65fdd6d1ec..427bfaa6f7 100644 --- a/sys/vfs/ufs/ufs_vnops.c +++ b/sys/vfs/ufs/ufs_vnops.c @@ -2181,7 +2181,7 @@ filt_ufsread(struct knote *kn, long hint) * the knote for deletion. */ if (hint == NOTE_REVOKE) { - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); return (1); } @@ -2201,7 +2201,7 @@ filt_ufswrite(struct knote *kn, long hint) * the knote for deletion. */ if (hint == NOTE_REVOKE) - kn->kn_flags |= (EV_EOF | EV_ONESHOT); + kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); kn->kn_data = 0; return (1); @@ -2213,7 +2213,7 @@ filt_ufsvnode(struct knote *kn, long hint) if (kn->kn_sfflags & hint) kn->kn_fflags |= hint; if (hint == NOTE_REVOKE) { - kn->kn_flags |= EV_EOF; + kn->kn_flags |= (EV_EOF | EV_NODATA); return (1); } return (kn->kn_fflags != 0); -- 2.41.0