kevent: Restore old EV_EOF semantics
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 23 Sep 2011 06:23:53 +0000 (14:23 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 23 Sep 2011 06:23:53 +0000 (14:23 +0800)
- 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

17 files changed:
sys/dev/misc/cmx/cmx.c
sys/dev/misc/kbd/kbd.c
sys/dev/video/bktr/bktr_os.c
sys/dev/video/cxm/cxm.c
sys/kern/kern_event.c
sys/kern/sys_generic.c
sys/kern/sys_pipe.c
sys/kern/tty.c
sys/kern/tty_pty.c
sys/kern/uipc_socket.c
sys/sys/event.h
sys/vfs/devfs/devfs_core.c
sys/vfs/fifofs/fifo_vnops.c
sys/vfs/gnu/ext2fs/ext2_vnops.c
sys/vfs/hammer/hammer_vnops.c
sys/vfs/tmpfs/tmpfs_vnops.c
sys/vfs/ufs/ufs_vnops.c

index 9174fae..815590c 100644 (file)
@@ -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);
        }
 
index b39133e..3c9ecc5 100644 (file)
@@ -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)
index 0724075..710cedc 100644 (file)
@@ -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);
        }
 
index ed83036..2b9ee89 100644 (file)
@@ -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);
        }
 
index bd5ac9a..f475cf1 100644 (file)
@@ -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);
        }
 
index 050813d..42cbc3b 100644 (file)
@@ -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)
index 5f14a90..9a36d75 100644 (file)
@@ -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;
        }
 
index e616e1c..21af560 100644 (file)
@@ -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);
        }
index cd553da..99337f1 100644 (file)
@@ -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);
        }
index 204ff48..b20eb28 100644 (file)
@@ -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);
        }
index 396fdab..c39a6e7 100644 (file)
@@ -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
index 65f90f7..f5ddfe5 100644 (file)
@@ -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);
 }
 
index 0c572ad..22e2a5a 100644 (file)
@@ -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);
 }
index c04dbaa..790ed9a 100644 (file)
@@ -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);
index 533cc24..e5101d7 100644 (file)
@@ -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);
index c2ea751..c740d46 100644 (file)
@@ -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);
index 65fdd6d..427bfaa 100644 (file)
@@ -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);