diff options
author | Niels Provos <provos@cvs.openbsd.org> | 2001-03-01 20:54:37 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 2001-03-01 20:54:37 +0000 |
commit | 950a6333d90c04783291b2f77e89257bc6df966e (patch) | |
tree | 0d452c7deda41df938a0f8d009e3f850249b8eb8 /sys | |
parent | 9027db9730b3cc9c6f973b4e6fbdf6b353260158 (diff) |
port kqueue changes from freebsd, plus all required openbsd glue.
okay deraadt@, millert@
from jlemon@freebsd.org:
extend kqueue down to the device layer, backwards compatible approach
suggested by peter@freebsd.org
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/svr4/svr4_net.c | 5 | ||||
-rw-r--r-- | sys/dev/cons.c | 19 | ||||
-rw-r--r-- | sys/dev/cons.h | 5 | ||||
-rw-r--r-- | sys/dev/wscons/wsdisplay.c | 21 | ||||
-rw-r--r-- | sys/kern/kern_event.c | 150 | ||||
-rw-r--r-- | sys/kern/spec_vnops.c | 21 | ||||
-rw-r--r-- | sys/kern/sys_pipe.c | 32 | ||||
-rw-r--r-- | sys/kern/sys_socket.c | 8 | ||||
-rw-r--r-- | sys/kern/tty.c | 91 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 60 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 87 | ||||
-rw-r--r-- | sys/kern/vnode_if.src | 10 | ||||
-rw-r--r-- | sys/miscfs/fifofs/fifo.h | 3 | ||||
-rw-r--r-- | sys/miscfs/fifofs/fifo_vnops.c | 96 | ||||
-rw-r--r-- | sys/miscfs/specfs/spec_vnops.c | 21 | ||||
-rw-r--r-- | sys/miscfs/specfs/specdev.h | 3 | ||||
-rw-r--r-- | sys/sys/conf.h | 29 | ||||
-rw-r--r-- | sys/sys/event.h | 22 | ||||
-rw-r--r-- | sys/sys/file.h | 5 | ||||
-rw-r--r-- | sys/sys/socketvar.h | 4 | ||||
-rw-r--r-- | sys/sys/specdev.h | 3 | ||||
-rw-r--r-- | sys/sys/tty.h | 3 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vnops.c | 7 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_extern.h | 3 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 86 |
25 files changed, 561 insertions, 233 deletions
diff --git a/sys/compat/svr4/svr4_net.c b/sys/compat/svr4/svr4_net.c index 4b9b85410b4..0aee6d4ca34 100644 --- a/sys/compat/svr4/svr4_net.c +++ b/sys/compat/svr4/svr4_net.c @@ -1,4 +1,4 @@ -/* $OpenBSD: svr4_net.c,v 1.9 1999/07/13 15:17:53 provos Exp $ */ +/* $OpenBSD: svr4_net.c,v 1.10 2001/03/01 20:54:32 provos Exp $ */ /* $NetBSD: svr4_net.c,v 1.12 1996/09/07 12:40:51 mycroft Exp $ */ /* @@ -82,7 +82,8 @@ int svr4_netattach __P((int)); static int svr4_soo_close __P((struct file *fp, struct proc *p)); static struct fileops svr4_netops = { - soo_read, soo_write, soo_ioctl, soo_select, svr4_soo_close + soo_read, soo_write, soo_ioctl, soo_select, soo_kqfilter, + svr4_soo_close }; diff --git a/sys/dev/cons.c b/sys/dev/cons.c index f2a017da15a..78700bfa8ed 100644 --- a/sys/dev/cons.c +++ b/sys/dev/cons.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cons.c,v 1.8 2001/02/09 20:48:24 mickey Exp $ */ +/* $OpenBSD: cons.c,v 1.9 2001/03/01 20:54:32 provos Exp $ */ /* $NetBSD: cons.c,v 1.30 1996/04/08 19:57:30 jonathan Exp $ */ /* @@ -227,6 +227,23 @@ cnselect(dev, rw, p) return (ttselect(cn_tab->cn_dev, rw, p)); } + +int +cnkqfilter(dev, kn) + dev_t dev; + struct knote *kn; +{ + if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE)) + return 0; + if (cn_tab == NULL) + return (1); + + dev = cn_tab->cn_dev; + if (cdevsw[major(dev)].d_type & D_KQFILTER) + return ((*cdevsw[major(dev)].d_kqfilter)(dev, kn)); + return (1); +} + int cngetc() { diff --git a/sys/dev/cons.h b/sys/dev/cons.h index b8e6a6a53a6..14adef8e9ae 100644 --- a/sys/dev/cons.h +++ b/sys/dev/cons.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cons.h,v 1.6 1998/06/17 14:58:34 mickey Exp $ */ +/* $OpenBSD: cons.h,v 1.7 2001/03/01 20:54:33 provos Exp $ */ /* $NetBSD: cons.h,v 1.14 1996/03/14 19:08:35 christos Exp $ */ /* @@ -72,6 +72,8 @@ struct consdev { extern struct consdev constab[]; extern struct consdev *cn_tab; +struct knote; + void cninit __P((void)); int cnset __P((dev_t)); int cnopen __P((dev_t, int, int, struct proc *)); @@ -80,6 +82,7 @@ int cnread __P((dev_t, struct uio *, int)); int cnwrite __P((dev_t, struct uio *, int)); int cnioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); int cnselect __P((dev_t, int, struct proc *)); +int cnkqfilter __P((dev_t, struct knote *)); int cngetc __P((void)); void cnputc __P((int)); void cnpollc __P((int)); diff --git a/sys/dev/wscons/wsdisplay.c b/sys/dev/wscons/wsdisplay.c index bc9cf1bfa15..552c37a67c5 100644 --- a/sys/dev/wscons/wsdisplay.c +++ b/sys/dev/wscons/wsdisplay.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wsdisplay.c,v 1.14 2001/02/25 23:24:19 aaron Exp $ */ +/* $OpenBSD: wsdisplay.c,v 1.15 2001/03/01 20:54:33 provos Exp $ */ /* $NetBSD: wsdisplay.c,v 1.37.4.1 2000/06/30 16:27:53 simonb Exp $ */ /* @@ -1179,6 +1179,25 @@ wsdisplayselect(dev, events, p) return (0); } +int +wsdisplaykqfilter(dev, kn) + dev_t dev; + struct knote *kn; +{ + struct wsdisplay_softc *sc = wsdisplay_cd.cd_devs[WSDISPLAYUNIT(dev)]; + struct wsscreen *scr; + + if (ISWSDISPLAYCTL(dev)) + return (1); + + scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]; + + if (WSSCREEN_HAS_TTY(scr)) + return (ttkqfilter(dev, kn)); + else + return (1); +} + void wsdisplaystart(tp) struct tty *tp; diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index d407ba8ad27..5e7ea093237 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1,7 +1,7 @@ -/* $OpenBSD: kern_event.c,v 1.6 2000/11/21 21:49:57 provos Exp $ */ +/* $OpenBSD: kern_event.c,v 1.7 2001/03/01 20:54:33 provos Exp $ */ /*- - * Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org> + * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/kern/kern_event.c,v 1.15 2000/08/07 16:45:42 jlemon Exp $ + * $FreeBSD: src/sys/kern/kern_event.c,v 1.22 2001/02/23 20:32:42 jlemon Exp $ */ #include <sys/param.h> @@ -49,15 +49,6 @@ #include <sys/mount.h> #include <sys/syscallargs.h> -int filt_nullattach(struct knote *kn); -int filt_rwtypattach(struct knote *kn); -int filt_kqattach(struct knote *kn); -void filt_kqdetach(struct knote *kn); -int filt_kqueue(struct knote *kn, long hint); -int filt_procattach(struct knote *kn); -void filt_procdetach(struct knote *kn); -int filt_proc(struct knote *kn, long hint); - int kqueue_scan(struct file *fp, int maxevents, struct kevent *ulistp, const struct timespec *timeout, struct proc *p, int *retval); @@ -69,9 +60,19 @@ int kqueue_write(struct file *fp, off_t *poff, struct uio *uio, int kqueue_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p); int kqueue_select(struct file *fp, int which, struct proc *p); +int kqueue_kqfilter(struct file *fp, struct knote *kn); int kqueue_close(struct file *fp, struct proc *p); void kqueue_wakeup(struct kqueue *kq); +struct fileops kqueueops = { + kqueue_read, + kqueue_write, + kqueue_ioctl, + kqueue_select, + kqueue_kqfilter, + kqueue_close +}; + void knote_attach(struct knote *kn, struct filedesc *fdp); void knote_drop(struct knote *kn, struct proc *p); void knote_enqueue(struct knote *kn); @@ -79,6 +80,20 @@ void knote_dequeue(struct knote *kn); struct knote *knote_alloc(void); void knote_free(struct knote *kn); +void filt_kqdetach(struct knote *kn); +int filt_kqueue(struct knote *kn, long hint); +int filt_procattach(struct knote *kn); +void filt_procdetach(struct knote *kn); +int filt_proc(struct knote *kn, long hint); +int filt_fileattach(struct knote *kn); + +struct filterops kqread_filtops = + { 1, NULL, filt_kqdetach, filt_kqueue }; +struct filterops proc_filtops = + { 0, filt_procattach, filt_procdetach, filt_proc }; +struct filterops file_filtops = + { 1, filt_fileattach, NULL, NULL }; + #define KNOTE_ACTIVATE(kn) do { \ kn->kn_status |= KN_ACTIVE; \ if ((kn->kn_status & (KN_QUEUED | KN_DISABLED)) == 0) \ @@ -88,88 +103,40 @@ void knote_free(struct knote *kn); #define KN_HASHSIZE 64 /* XXX should be tunable */ #define KN_HASH(val, mask) (((val) ^ (val >> 8)) & (mask)) -struct fileops kqueueops = { - kqueue_read, - kqueue_write, - kqueue_ioctl, - kqueue_select, - kqueue_close -}; - -extern struct filterops so_rwfiltops[]; -extern struct filterops pipe_rwfiltops[]; -#ifdef notyet -extern struct filterops fifo_rwfiltops[]; -#endif -extern struct filterops vn_rwfiltops[]; - -struct filterops kq_rwfiltops[] = { - { 1, filt_kqattach, filt_kqdetach, filt_kqueue }, - { 1, filt_nullattach, NULL, NULL }, -}; - extern struct filterops sig_filtops; #ifdef notyet extern struct filterops aio_filtops; #endif -extern struct filterops vn_filtops; - -struct filterops rwtype_filtops = - { 1, filt_rwtypattach, NULL, NULL }; -struct filterops proc_filtops = - { 0, filt_procattach, filt_procdetach, filt_proc }; /* - * XXX - * These must match the order of defines in <sys/file.h> - */ -struct filterops *rwtypfilt_sw[] = { - NULL, /* 0 */ - vn_rwfiltops, /* DTYPE_VNODE */ - so_rwfiltops, /* DTYPE_SOCKET */ - pipe_rwfiltops, /* DTYPE_PIPE */ - /* fifo_rwfiltops, */ /* DTYPE_FIFO */ - kq_rwfiltops, /* DTYPE_KQUEUE */ -}; - -/* - * table for all system-defined filters. + * Table for for all system-defined filters. */ struct filterops *sysfilt_ops[] = { - &rwtype_filtops, /* EVFILT_READ */ - &rwtype_filtops, /* EVFILT_WRITE */ + &file_filtops, /* EVFILT_READ */ + &file_filtops, /* EVFILT_WRITE */ NULL, /*&aio_filtops,*/ /* EVFILT_AIO */ - &vn_filtops, /* EVFILT_VNODE */ + &file_filtops, /* EVFILT_VNODE */ &proc_filtops, /* EVFILT_PROC */ &sig_filtops, /* EVFILT_SIGNAL */ }; int -filt_nullattach(struct knote *kn) -{ - return (ENXIO); -} - -/* - * file-type specific attach routine for read/write filters - */ -int -filt_rwtypattach(struct knote *kn) +filt_fileattach(struct knote *kn) { - struct filterops *fops; + struct file *fp = kn->kn_fp; - fops = rwtypfilt_sw[kn->kn_fp->f_type]; - if (fops == NULL) - return (EINVAL); - kn->kn_fop = &fops[~kn->kn_filter]; /* convert to 0-base index */ - return (kn->kn_fop->f_attach(kn)); + return ((*fp->f_ops->fo_kqfilter)(fp, kn)); } int -filt_kqattach(struct knote *kn) +kqueue_kqfilter(struct file *fp, struct knote *kn) { struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data; + if (kn->kn_filter != EVFILT_READ) + return (1); + + kn->kn_fop = &kqread_filtops; SLIST_INSERT_HEAD(&kq->kq_sel.si_note, kn, kn_selnext); return (0); } @@ -338,7 +305,7 @@ sys_kevent(struct proc *p, void *v, register_t *retval) } */ *uap = v; struct kevent *kevp; struct kqueue *kq; - struct file *fp; + struct file *fp = NULL; struct timespec ts; int i, n, nerrors, error; @@ -347,10 +314,12 @@ sys_kevent(struct proc *p, void *v, register_t *retval) (fp->f_type != DTYPE_KQUEUE)) return (EBADF); + fp->f_count++; + if (SCARG(uap, timeout) != NULL) { error = copyin(SCARG(uap, timeout), &ts, sizeof(ts)); if (error) - return error; + goto done; SCARG(uap, timeout) = &ts; } @@ -363,7 +332,7 @@ sys_kevent(struct proc *p, void *v, register_t *retval) error = copyin(SCARG(uap, changelist), kq->kq_kev, n * sizeof(struct kevent)); if (error) - return (error); + goto done; for (i = 0; i < n; i++) { kevp = &kq->kq_kev[i]; kevp->flags &= ~EV_SYSFLAGS; @@ -379,7 +348,7 @@ sys_kevent(struct proc *p, void *v, register_t *retval) SCARG(uap, nevents)--; nerrors++; } else { - return (error); + goto done; } } } @@ -388,12 +357,16 @@ sys_kevent(struct proc *p, void *v, register_t *retval) } if (nerrors) { *retval = nerrors; - return (0); + error = 0; + goto done; } error = kqueue_scan(fp, SCARG(uap, nevents), SCARG(uap, eventlist), SCARG(uap, timeout), p, &n); *retval = n; + done: + if (fp != NULL) + closef(fp, p); return (error); } @@ -427,6 +400,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p) if ((u_int)kev->ident >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[kev->ident]) == NULL) return (EBADF); + fp->f_count++; if (kev->ident < fdp->fd_knlistsize) { SLIST_FOREACH(kn, &fdp->fd_knlist[kev->ident], kn_link) @@ -448,8 +422,10 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p) } } - if (kn == NULL && ((kev->flags & EV_ADD) == 0)) - return (ENOENT); + if (kn == NULL && ((kev->flags & EV_ADD) == 0)) { + error = ENOENT; + goto done; + } /* * kn now contains the matching knote, or NULL if no match @@ -458,14 +434,20 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p) if (kn == NULL) { kn = knote_alloc(); - if (kn == NULL) - return (ENOMEM); - if (fp != NULL) - fp->f_count++; + if (kn == NULL) { + error = ENOMEM; + goto done; + } kn->kn_fp = fp; kn->kn_kq = kq; kn->kn_fop = fops; + /* + * apply reference count to knote structure, and + * do not release it at the end of this routine. + */ + fp = NULL; + kn->kn_sfflags = kev->fflags; kn->kn_sdata = kev->data; kev->fflags = 0; @@ -516,6 +498,8 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p) } done: + if (fp != NULL) + closef(fp, p); return (error); } diff --git a/sys/kern/spec_vnops.c b/sys/kern/spec_vnops.c index 5d6281fc865..b241aed4e27 100644 --- a/sys/kern/spec_vnops.c +++ b/sys/kern/spec_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: spec_vnops.c,v 1.17 2001/02/24 19:07:10 csapuntz Exp $ */ +/* $OpenBSD: spec_vnops.c,v 1.18 2001/03/01 20:54:35 provos Exp $ */ /* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */ /* @@ -81,6 +81,7 @@ struct vnodeopv_entry_desc spec_vnodeop_entries[] = { { &vop_lease_desc, spec_lease_check }, /* lease */ { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ { &vop_select_desc, spec_select }, /* select */ + { &vop_kqfilter_desc, spec_kqfilter }, /* kqfilter */ { &vop_revoke_desc, spec_revoke }, /* revoke */ { &vop_mmap_desc, spec_mmap }, /* mmap */ { &vop_fsync_desc, spec_fsync }, /* fsync */ @@ -472,6 +473,24 @@ spec_select(v) return (*cdevsw[major(dev)].d_select)(dev, ap->a_which, ap->a_p); } } +/* ARGSUSED */ +int +spec_kqfilter(v) + void *v; +{ + struct vop_kqfilter_args /* { + struct vnode *a_vp; + struct knote *a_kn; + } */ *ap = v; + + dev_t dev; + + dev = ap->a_vp->v_rdev; + if (cdevsw[major(dev)].d_type & D_KQFILTER) + return (*cdevsw[major(dev)].d_kqfilter)(dev, ap->a_kn); + return (1); +} + /* * Synch buffers associated with a block device */ diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 28dfd3dc210..cfbb2efcd2e 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_pipe.c,v 1.25 2000/11/16 20:02:17 provos Exp $ */ +/* $OpenBSD: sys_pipe.c,v 1.26 2001/03/01 20:54:33 provos Exp $ */ /* * Copyright (c) 1996 John S. Dyson @@ -67,21 +67,24 @@ int pipe_read __P((struct file *, off_t *, struct uio *, struct ucred *)); int pipe_write __P((struct file *, off_t *, struct uio *, struct ucred *)); int pipe_close __P((struct file *, struct proc *)); int pipe_select __P((struct file *, int which, struct proc *)); +int pipe_kqfilter __P((struct file *fp, struct knote *kn)); int pipe_ioctl __P((struct file *, u_long, caddr_t, struct proc *)); -static struct fileops pipeops = - { pipe_read, pipe_write, pipe_ioctl, pipe_select, pipe_close }; +static struct fileops pipeops = { + pipe_read, pipe_write, pipe_ioctl, pipe_select, pipe_kqfilter, + pipe_close +}; -int filt_pipeattach(struct knote *kn); void filt_pipedetach(struct knote *kn); int filt_piperead(struct knote *kn, long hint); int filt_pipewrite(struct knote *kn, long hint); -struct filterops pipe_rwfiltops[] = { - { 1, filt_pipeattach, filt_pipedetach, filt_piperead }, - { 1, filt_pipeattach, filt_pipedetach, filt_pipewrite }, -}; +struct filterops pipe_rfiltops = + { 1, NULL, filt_pipedetach, filt_piperead }; +struct filterops pipe_wfiltops = + { 1, NULL, filt_pipedetach, filt_pipewrite }; + /* * Default pipe buffer size(s), this can be kind-of large now because pipe * space is pageable. The pipe code will try to maintain locality of @@ -758,10 +761,21 @@ pipeclose(cpipe) #endif int -filt_pipeattach(struct knote *kn) +pipe_kqfilter(struct file *fp, struct knote *kn) { struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data; + switch (kn->kn_filter) { + case EVFILT_READ: + kn->kn_fop = &pipe_rfiltops; + break; + case EVFILT_WRITE: + kn->kn_fop = &pipe_wfiltops; + break; + default: + return (1); + } + SLIST_INSERT_HEAD(&rpipe->pipe_sel.si_note, kn, kn_selnext); return (0); } diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index f385310036a..1d51c9349fa 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_socket.c,v 1.4 2000/04/19 08:34:53 csapuntz Exp $ */ +/* $OpenBSD: sys_socket.c,v 1.5 2001/03/01 20:54:34 provos Exp $ */ /* $NetBSD: sys_socket.c,v 1.13 1995/08/12 23:59:09 mycroft Exp $ */ /* @@ -50,8 +50,10 @@ #include <net/if.h> #include <net/route.h> -struct fileops socketops = - { soo_read, soo_write, soo_ioctl, soo_select, soo_close }; +struct fileops socketops = { + soo_read, soo_write, soo_ioctl, soo_select, soo_kqfilter, + soo_close +}; /* ARGSUSED */ int diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 1a7990146d1..3437a0537dc 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.41 2000/07/19 13:37:28 art Exp $ */ +/* $OpenBSD: tty.c,v 1.42 2001/03/01 20:54:34 provos Exp $ */ /* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */ /*- @@ -70,6 +70,10 @@ void ttyunblock __P((struct tty *)); static void ttyecho __P((int, struct tty *)); static void ttyrubo __P((struct tty *, int)); static int proc_compare __P((struct proc *, struct proc *)); +int filt_ttyread __P((struct knote *kn, long hint)); +void filt_ttyrdetach __P((struct knote *kn)); +int filt_ttywrite __P((struct knote *kn, long hint)); +void filt_ttywdetach __P((struct knote *kn)); /* Symbolic sleep message strings. */ char ttclos[] = "ttycls"; @@ -1049,6 +1053,90 @@ win: splx(s); return (0); } +struct filterops ttyread_filtops = + { 1, NULL, filt_ttyrdetach, filt_ttyread }; +struct filterops ttywrite_filtops = + { 1, NULL, filt_ttywdetach, filt_ttywrite }; + +int +ttkqfilter(dev, kn) + dev_t dev; + struct knote *kn; +{ + struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev); + struct klist *klist; + int s; + + switch (kn->kn_filter) { + case EVFILT_READ: + klist = &tp->t_rsel.si_note; + kn->kn_fop = &ttyread_filtops; + break; + case EVFILT_WRITE: + klist = &tp->t_wsel.si_note; + kn->kn_fop = &ttywrite_filtops; + break; + default: + return (1); + } + + kn->kn_hook = (caddr_t)dev; + + s = spltty(); + SLIST_INSERT_HEAD(klist, kn, kn_selnext); + splx(s); + + return (0); +} + +void +filt_ttyrdetach(struct knote *kn) +{ + dev_t dev = (dev_t)kn->kn_hook; + struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev); + int s = spltty(); + + SLIST_REMOVE(&tp->t_rsel.si_note, kn, knote, kn_selnext); + splx(s); +} + +int +filt_ttyread(struct knote *kn, long hint) +{ + dev_t dev = (dev_t)kn->kn_hook; + struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev); + + kn->kn_data = ttnread(tp); + if (!ISSET(tp->t_state, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) { + kn->kn_flags |= EV_EOF; + return (1); + } + return (kn->kn_data > 0); +} + +void +filt_ttywdetach(struct knote *kn) +{ + dev_t dev = (dev_t)kn->kn_hook; + struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev); + int s = spltty(); + + SLIST_REMOVE(&tp->t_wsel.si_note, kn, knote, kn_selnext); + splx(s); +} + +int +filt_ttywrite(kn, hint) + struct knote *kn; + long hint; +{ + dev_t dev = (dev_t)kn->kn_hook; + struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev); + + kn->kn_data = tp->t_outq.c_cc; + return (kn->kn_data <= tp->t_lowat); +} + static int ttnread(tp) struct tty *tp; @@ -1935,6 +2023,7 @@ ttwakeup(tp) if (ISSET(tp->t_state, TS_ASYNC)) pgsignal(tp->t_pgrp, SIGIO, 1); wakeup((caddr_t)&tp->t_rawq); + KNOTE(&tp->t_rsel.si_note, 0); } /* diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 8b36265424e..207f52feade 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.30 2001/02/07 12:20:42 itojun Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.31 2001/03/01 20:54:34 provos Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -51,21 +51,19 @@ #include <sys/signalvar.h> #include <sys/resourcevar.h> -int filt_sorattach(struct knote *kn); void filt_sordetach(struct knote *kn); int filt_soread(struct knote *kn, long hint); -int filt_sowattach(struct knote *kn); void filt_sowdetach(struct knote *kn); int filt_sowrite(struct knote *kn, long hint); int filt_solisten(struct knote *kn, long hint); struct filterops solisten_filtops = - { 1, filt_sorattach, filt_sordetach, filt_solisten }; + { 1, NULL, filt_sordetach, filt_solisten }; +struct filterops soread_filtops = + { 1, NULL, filt_sordetach, filt_soread }; +struct filterops sowrite_filtops = + { 1, NULL, filt_sowdetach, filt_sowrite }; -struct filterops so_rwfiltops[] = { - { 1, filt_sorattach, filt_sordetach, filt_soread }, - { 1, filt_sowattach, filt_sowdetach, filt_sowrite }, -}; #ifndef SOMINCONN #define SOMINCONN 80 @@ -1114,15 +1112,31 @@ sohasoutofband(so) } int -filt_sorattach(struct knote *kn) +soo_kqfilter(struct file *fp, struct knote *kn) { struct socket *so = (struct socket *)kn->kn_fp->f_data; - int s = splnet(); + struct sockbuf *sb; + int s; - if (so->so_options & SO_ACCEPTCONN) - kn->kn_fop = &solisten_filtops; - SLIST_INSERT_HEAD(&so->so_rcv.sb_sel.si_note, kn, kn_selnext); - so->so_rcv.sb_flags |= SB_KNOTE; + switch (kn->kn_filter) { + case EVFILT_READ: + if (so->so_options & SO_ACCEPTCONN) + kn->kn_fop = &solisten_filtops; + else + kn->kn_fop = &soread_filtops; + sb = &so->so_rcv; + break; + case EVFILT_WRITE: + kn->kn_fop = &sowrite_filtops; + sb = &so->so_snd; + break; + default: + return (1); + } + + s = splnet(); + SLIST_INSERT_HEAD(&sb->sb_sel.si_note, kn, kn_selnext); + sb->sb_flags |= SB_KNOTE; splx(s); return (0); } @@ -1148,25 +1162,16 @@ filt_soread(struct knote *kn, long hint) kn->kn_data = so->so_rcv.sb_cc; if (so->so_state & SS_CANTRCVMORE) { kn->kn_flags |= EV_EOF; + kn->kn_fflags = so->so_error; return (1); } if (so->so_error) /* temporary udp error */ return (1); + if (kn->kn_sfflags & NOTE_LOWAT) + return (kn->kn_data >= kn->kn_sdata); return (kn->kn_data >= so->so_rcv.sb_lowat); } -int -filt_sowattach(struct knote *kn) -{ - struct socket *so = (struct socket *)kn->kn_fp->f_data; - int s = splnet(); - - SLIST_INSERT_HEAD(&so->so_snd.sb_sel.si_note, kn, kn_selnext); - so->so_snd.sb_flags |= SB_KNOTE; - splx(s); - return (0); -} - void filt_sowdetach(struct knote *kn) { @@ -1188,6 +1193,7 @@ filt_sowrite(struct knote *kn, long hint) kn->kn_data = sbspace(&so->so_snd); if (so->so_state & SS_CANTSENDMORE) { kn->kn_flags |= EV_EOF; + kn->kn_fflags = so->so_error; return (1); } if (so->so_error) /* temporary udp error */ @@ -1195,6 +1201,8 @@ filt_sowrite(struct knote *kn, long hint) if (((so->so_state & SS_ISCONNECTED) == 0) && (so->so_proto->pr_flags & PR_CONNREQUIRED)) return (0); + if (kn->kn_sfflags & NOTE_LOWAT) + return (kn->kn_data >= kn->kn_sdata); return (kn->kn_data >= so->so_snd.sb_lowat); } diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 6bfcf9614ab..9e1b9907a27 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_vnops.c,v 1.27 2000/11/21 21:49:57 provos Exp $ */ +/* $OpenBSD: vfs_vnops.c,v 1.28 2001/03/01 20:54:34 provos Exp $ */ /* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */ /* @@ -61,39 +61,18 @@ #include <uvm/uvm_extern.h> #endif -#include <ufs/ufs/quota.h> -#include <ufs/ufs/inode.h> - int vn_read __P((struct file *fp, off_t *off, struct uio *uio, struct ucred *cred)); int vn_write __P((struct file *fp, off_t *off, struct uio *uio, struct ucred *cred)); int vn_select __P((struct file *fp, int which, struct proc *p)); +int vn_kqfilter __P((struct file *fp, struct knote *kn)); int vn_closefile __P((struct file *fp, struct proc *p)); int vn_ioctl __P((struct file *fp, u_long com, caddr_t data, struct proc *p)); struct fileops vnops = - { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile }; - -static int filt_nullattach(struct knote *kn); -static int filt_vnattach(struct knote *kn); -static void filt_vndetach(struct knote *kn); -static int filt_vnode(struct knote *kn, long hint); -static int filt_vnread(struct knote *kn, long hint); - -struct filterops vn_filtops = - { 1, filt_vnattach, filt_vndetach, filt_vnode }; - -/* - * XXX - * filt_vnread is ufs-specific, so the attach routine should really - * switch out to different filterops based on the vn filetype - */ -struct filterops vn_rwfiltops[] = { - { 1, filt_vnattach, filt_vndetach, filt_vnread }, - { 1, filt_nullattach, NULL, NULL }, -}; + { vn_read, vn_write, vn_ioctl, vn_select, vn_kqfilter, vn_closefile }; /* * Common code for vnode open operations. @@ -531,63 +510,9 @@ vn_closefile(fp, p) fp->f_cred, p)); } -static int -filt_vnattach(struct knote *kn) -{ - struct vnode *vp; - - if (kn->kn_fp->f_type != DTYPE_VNODE) - return (EBADF); - - vp = (struct vnode *)kn->kn_fp->f_data; - - /* - * XXX - * this is a hack simply to cause the filter attach to fail - * for non-ufs filesystems, until the support for them is done. - */ - if ((vp)->v_tag != VT_UFS || (vp)->v_type == VFIFO) - return (EOPNOTSUPP); - - simple_lock(&vp->v_selectinfo.vsi_lock); - SLIST_INSERT_HEAD(&vp->v_selectinfo.vsi_selinfo.si_note, kn, kn_selnext); - simple_unlock(&vp->v_selectinfo.vsi_lock); - - return (0); -} - -static void -filt_vndetach(struct knote *kn) -{ - struct vnode *vp = (struct vnode *)kn->kn_fp->f_data; - - simple_lock(&vp->v_selectinfo.vsi_lock); - SLIST_REMOVE(&vp->v_selectinfo.vsi_selinfo.si_note, - kn, knote, kn_selnext); - simple_unlock(&vp->v_selectinfo.vsi_lock); -} - -static int -filt_vnode(struct knote *kn, long hint) -{ - if (kn->kn_sfflags & hint) - kn->kn_fflags |= hint; - return (kn->kn_fflags != 0); -} - -static int -filt_nullattach(struct knote *kn) -{ - return (ENXIO); -} - /*ARGSUSED*/ -static int -filt_vnread(struct knote *kn, long hint) +int +vn_kqfilter(struct file *fp, struct knote *kn) { - struct vnode *vp = (struct vnode *)kn->kn_fp->f_data; - struct inode *ip = VTOI(vp); - - kn->kn_data = ip->i_ffs_size - kn->kn_fp->f_offset; - return (kn->kn_data != 0); + return (VOP_KQFILTER(((struct vnode *)fp->f_data), kn)); } diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 722ca9c4fa1..5a98a21d5a6 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -1,4 +1,4 @@ -# $OpenBSD: vnode_if.src,v 1.9 1998/12/05 16:54:02 csapuntz Exp $ +# $OpenBSD: vnode_if.src,v 1.10 2001/03/01 20:54:34 provos Exp $ # $NetBSD: vnode_if.src,v 1.10 1996/05/11 18:26:27 mycroft Exp $ # # Copyright (c) 1992, 1993 @@ -227,6 +227,14 @@ vop_select { }; # +#% kqfilter vp U U U +# +vop_kqfilter { + IN struct vnode *vp; + IN struct knote *kn; +}; + +# #% revoke vp U U U # vop_revoke { diff --git a/sys/miscfs/fifofs/fifo.h b/sys/miscfs/fifofs/fifo.h index 088bb3232be..8a5b96a1dbe 100644 --- a/sys/miscfs/fifofs/fifo.h +++ b/sys/miscfs/fifofs/fifo.h @@ -1,4 +1,4 @@ -/* $OpenBSD: fifo.h,v 1.6 1998/08/06 19:34:34 csapuntz Exp $ */ +/* $OpenBSD: fifo.h,v 1.7 2001/03/01 20:54:34 provos Exp $ */ /* $NetBSD: fifo.h,v 1.10 1996/02/09 22:40:15 christos Exp $ */ /* @@ -56,6 +56,7 @@ int fifo_write __P((void *)); #define fifo_lease_check nullop int fifo_ioctl __P((void *)); int fifo_select __P((void *)); +int fifo_kqfilter __P((void *)); #define fifo_mmap fifo_badop #define fifo_fsync nullop #define fifo_seek fifo_badop diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c index 4bb6da560ab..142aae7f6cf 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.8 2000/11/15 23:21:42 provos Exp $ */ +/* $OpenBSD: fifo_vnops.c,v 1.9 2001/03/01 20:54:34 provos Exp $ */ /* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */ /* @@ -47,6 +47,7 @@ #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/file.h> +#include <sys/event.h> #include <sys/errno.h> #include <sys/malloc.h> #include <sys/un.h> @@ -79,6 +80,7 @@ struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { { &vop_lease_desc, fifo_lease_check }, /* lease */ { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ { &vop_select_desc, fifo_select }, /* select */ + { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */ { &vop_revoke_desc, fifo_revoke }, /* revoke */ { &vop_mmap_desc, fifo_mmap }, /* mmap */ { &vop_fsync_desc, fifo_fsync }, /* fsync */ @@ -110,6 +112,17 @@ struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { { &vop_bwrite_desc, fifo_bwrite }, /* bwrite */ { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } }; + +void filt_fifordetach(struct knote *kn); +int filt_fiforead(struct knote *kn, long hint); +void filt_fifowdetach(struct knote *kn); +int filt_fifowrite(struct knote *kn, long hint); + +struct filterops fiforead_filtops = + { 1, NULL, filt_fifordetach, filt_fiforead }; +struct filterops fifowrite_filtops = + { 1, NULL, filt_fifowdetach, filt_fifowrite }; + struct vnodeopv_desc fifo_vnodeop_opv_desc = { &fifo_vnodeop_p, fifo_vnodeop_entries }; @@ -537,3 +550,84 @@ fifo_badop(v) /* NOTREACHED */ return(0); } + + +int +fifo_kqfilter(v) + void *v; +{ + struct vop_kqfilter_args /* { + struct vnode *a_vp; + struct knote *a_kn; + } */ *ap = v; + struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock; + struct sockbuf *sb; + + switch (ap->a_kn->kn_filter) { + case EVFILT_READ: + ap->a_kn->kn_fop = &fiforead_filtops; + sb = &so->so_rcv; + break; + case EVFILT_WRITE: + ap->a_kn->kn_fop = &fifowrite_filtops; + sb = &so->so_snd; + break; + default: + return (1); + } + + ap->a_kn->kn_hook = (caddr_t)so; + + SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext); + sb->sb_flags |= SB_KNOTE; + + return (0); +} + +void +filt_fifordetach(struct knote *kn) +{ + struct socket *so = (struct socket *)kn->kn_hook; + + SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext); + if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note)) + so->so_rcv.sb_flags &= ~SB_KNOTE; +} + +int +filt_fiforead(struct knote *kn, long hint) +{ + struct socket *so = (struct socket *)kn->kn_hook; + + kn->kn_data = so->so_rcv.sb_cc; + if (so->so_state & SS_CANTRCVMORE) { + kn->kn_flags |= EV_EOF; + return (1); + } + kn->kn_flags &= ~EV_EOF; + return (kn->kn_data > 0); +} + +void +filt_fifowdetach(struct knote *kn) +{ + struct socket *so = (struct socket *)kn->kn_hook; + + SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext); + if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note)) + so->so_snd.sb_flags &= ~SB_KNOTE; +} + +int +filt_fifowrite(struct knote *kn, long hint) +{ + struct socket *so = (struct socket *)kn->kn_hook; + + kn->kn_data = sbspace(&so->so_snd); + if (so->so_state & SS_CANTSENDMORE) { + kn->kn_flags |= EV_EOF; + return (1); + } + kn->kn_flags &= ~EV_EOF; + return (kn->kn_data >= so->so_snd.sb_lowat); +} diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c index 5d6281fc865..b241aed4e27 100644 --- a/sys/miscfs/specfs/spec_vnops.c +++ b/sys/miscfs/specfs/spec_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: spec_vnops.c,v 1.17 2001/02/24 19:07:10 csapuntz Exp $ */ +/* $OpenBSD: spec_vnops.c,v 1.18 2001/03/01 20:54:35 provos Exp $ */ /* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */ /* @@ -81,6 +81,7 @@ struct vnodeopv_entry_desc spec_vnodeop_entries[] = { { &vop_lease_desc, spec_lease_check }, /* lease */ { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ { &vop_select_desc, spec_select }, /* select */ + { &vop_kqfilter_desc, spec_kqfilter }, /* kqfilter */ { &vop_revoke_desc, spec_revoke }, /* revoke */ { &vop_mmap_desc, spec_mmap }, /* mmap */ { &vop_fsync_desc, spec_fsync }, /* fsync */ @@ -472,6 +473,24 @@ spec_select(v) return (*cdevsw[major(dev)].d_select)(dev, ap->a_which, ap->a_p); } } +/* ARGSUSED */ +int +spec_kqfilter(v) + void *v; +{ + struct vop_kqfilter_args /* { + struct vnode *a_vp; + struct knote *a_kn; + } */ *ap = v; + + dev_t dev; + + dev = ap->a_vp->v_rdev; + if (cdevsw[major(dev)].d_type & D_KQFILTER) + return (*cdevsw[major(dev)].d_kqfilter)(dev, ap->a_kn); + return (1); +} + /* * Synch buffers associated with a block device */ diff --git a/sys/miscfs/specfs/specdev.h b/sys/miscfs/specfs/specdev.h index 3d7de64876b..ea0eea0c841 100644 --- a/sys/miscfs/specfs/specdev.h +++ b/sys/miscfs/specfs/specdev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: specdev.h,v 1.8 2001/02/23 14:42:39 csapuntz Exp $ */ +/* $OpenBSD: specdev.h,v 1.9 2001/03/01 20:54:35 provos Exp $ */ /* $NetBSD: specdev.h,v 1.12 1996/02/13 13:13:01 mycroft Exp $ */ /* @@ -97,6 +97,7 @@ int spec_write __P((void *)); #define spec_lease_check nullop int spec_ioctl __P((void *)); int spec_select __P((void *)); +int spec_kqfilter __P((void *)); #define spec_mmap spec_badop int spec_fsync __P((void *)); #define spec_seek spec_badop diff --git a/sys/sys/conf.h b/sys/sys/conf.h index ec0c4e76edb..3948bd2e35f 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.h,v 1.38 2000/09/26 14:03:51 art Exp $ */ +/* $OpenBSD: conf.h,v 1.39 2001/03/01 20:54:35 provos Exp $ */ /* $NetBSD: conf.h,v 1.33 1996/05/03 20:03:32 christos Exp $ */ /*- @@ -50,6 +50,7 @@ struct proc; struct tty; struct uio; struct vnode; +struct knote; /* * Types for d_type @@ -58,6 +59,11 @@ struct vnode; #define D_DISK 2 #define D_TTY 3 +/* + * Flags for d_type + */ +#define D_KQFILTER 0x00010000 /* has kqfilter entry */ + #ifdef _KERNEL #define dev_type_open(n) int n __P((dev_t, int, int, struct proc *)) @@ -156,7 +162,8 @@ struct cdevsw { (*d_tty) __P((dev_t dev)); int (*d_select) __P((dev_t dev, int which, struct proc *p)); int (*d_mmap) __P((dev_t, int, int)); - int d_type; + u_int d_type; + int (*d_kqfilter) __P((dev_t dev, struct knote *kn)); }; #ifdef _KERNEL @@ -170,11 +177,13 @@ extern struct cdevsw cdevsw[]; #define dev_type_tty(n) struct tty *n __P((dev_t)) #define dev_type_select(n) int n __P((dev_t, int, struct proc *)) #define dev_type_mmap(n) int n __P((dev_t, int, int)) +#define dev_type_kqfilter(n) int n __P((dev_t, struct knote *)) #define cdev_decl(n) \ dev_decl(n,open); dev_decl(n,close); dev_decl(n,read); \ dev_decl(n,write); dev_decl(n,ioctl); dev_decl(n,stop); \ - dev_decl(n,tty); dev_decl(n,select); dev_decl(n,mmap) + dev_decl(n,tty); dev_decl(n,select); dev_decl(n,mmap); \ + dev_decl(n,kqfilter) /* open, close, read, write, ioctl */ #define cdev_disk_init(c,n) { \ @@ -199,7 +208,8 @@ extern struct cdevsw cdevsw[]; #define cdev_tty_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ - dev_init(c,n,tty), ttselect, (dev_type_mmap((*))) enodev, D_TTY } + dev_init(c,n,tty), ttselect, (dev_type_mmap((*))) enodev, \ + D_TTY | D_KQFILTER, ttkqfilter } /* open, close, read, ioctl, select */ #define cdev_mouse_init(c,n) { \ @@ -231,13 +241,15 @@ extern struct cdevsw cdevsw[]; #define cdev_cn_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ - 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev, D_TTY } + 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev, \ + D_TTY | D_KQFILTER, dev_init(c,n,kqfilter) } /* open, read, write, ioctl, select -- XXX should be a tty */ #define cdev_ctty_init(c,n) { \ dev_init(c,n,open), (dev_type_close((*))) nullop, dev_init(c,n,read), \ dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ - 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev, D_TTY } + 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev, \ + D_TTY | D_KQFILTER, ttkqfilter } /* open, close, read, write, ioctl, mmap */ #define cdev_mm_init(c,n) { \ @@ -257,7 +269,7 @@ extern struct cdevsw cdevsw[]; dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ dev_init(c,n,tty), dev_init(c,n,select), (dev_type_mmap((*))) enodev, \ - D_TTY } + D_TTY | D_KQFILTER, ttkqfilter } /* open, close, read, ioctl, select -- XXX should be a generic device */ #define cdev_log_init(c,n) { \ @@ -366,7 +378,8 @@ extern struct cdevsw cdevsw[]; #define cdev_wsdisplay_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ - dev_init(c,n,tty), ttselect, dev_init(c,n,mmap) } + dev_init(c,n,tty), ttselect, dev_init(c,n,mmap), \ + D_KQFILTER, dev_init(c,n,kqfilter) } /* open, close, read, write, ioctl, select */ #define cdev_random_init(c,n) { \ diff --git a/sys/sys/event.h b/sys/sys/event.h index 3f63627c1f1..6642b2a827f 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -1,7 +1,7 @@ -/* $OpenBSD: event.h,v 1.2 2000/11/16 20:31:29 mickey Exp $ */ +/* $OpenBSD: event.h,v 1.3 2001/03/01 20:54:35 provos Exp $ */ /*- - * Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org> + * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/sys/event.h,v 1.7 2000/05/26 02:06:54 jake Exp $ + * $FreeBSD: src/sys/sys/event.h,v 1.11 2001/02/24 01:41:31 jlemon Exp $ */ #ifndef _SYS_EVENT_H_ @@ -40,6 +40,15 @@ #define EVFILT_SYSCOUNT 6 +#define EV_SET(kevp, a, b, c, d, e, f) do { \ + (kevp)->ident = (a); \ + (kevp)->filter = (b); \ + (kevp)->flags = (c); \ + (kevp)->fflags = (d); \ + (kevp)->data = (e); \ + (kevp)->udata = (f); \ +} while(0) + struct kevent { u_int ident; /* identifier for this event */ short filter; /* filter for event */ @@ -67,6 +76,11 @@ struct kevent { #define EV_ERROR 0x4000 /* error, data contains errno */ /* + * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace + */ +#define NOTE_LOWAT 0x0001 /* low water mark */ + +/* * data/hint flags for EVFILT_VNODE, shared with userspace */ #define NOTE_DELETE 0x0001 /* vnode was removed */ @@ -75,6 +89,7 @@ struct kevent { #define NOTE_ATTRIB 0x0008 /* attributes changed */ #define NOTE_LINK 0x0010 /* link count changed */ #define NOTE_RENAME 0x0020 /* vnode was renamed */ +#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ /* * data/hint flags for EVFILT_PROC, shared with userspace @@ -129,6 +144,7 @@ struct knote { struct proc *p_proc; /* proc pointer */ } kn_ptr; struct filterops *kn_fop; + caddr_t kn_hook; #define KN_ACTIVE 0x01 /* event has been triggered */ #define KN_QUEUED 0x02 /* event is on queue */ #define KN_DISABLED 0x04 /* event is disabled */ diff --git a/sys/sys/file.h b/sys/sys/file.h index 35482f912b9..d472143dd51 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -1,4 +1,4 @@ -/* $OpenBSD: file.h,v 1.9 2000/11/16 20:02:20 provos Exp $ */ +/* $OpenBSD: file.h,v 1.10 2001/03/01 20:54:35 provos Exp $ */ /* $NetBSD: file.h,v 1.11 1995/03/26 20:24:13 jtc Exp $ */ /* @@ -44,6 +44,7 @@ struct proc; struct uio; +struct knote; /* * Kernel descriptor table. @@ -71,6 +72,8 @@ struct file { caddr_t data, struct proc *p)); int (*fo_select) __P((struct file *fp, int which, struct proc *p)); + int (*fo_kqfilter) __P((struct file *fp, + struct knote *kn)); int (*fo_close) __P((struct file *fp, struct proc *p)); } *f_ops; off_t f_offset; diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 034fa0fad73..33b550b8a73 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: socketvar.h,v 1.19 2000/11/16 20:02:20 provos Exp $ */ +/* $OpenBSD: socketvar.h,v 1.20 2001/03/01 20:54:35 provos Exp $ */ /* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */ /*- @@ -215,6 +215,7 @@ struct sockaddr; struct proc; struct msghdr; struct stat; +struct knote; /* * File operations on sockets. @@ -226,6 +227,7 @@ int soo_write __P((struct file *fp, off_t *, struct uio *uio, int soo_ioctl __P((struct file *fp, u_long cmd, caddr_t data, struct proc *p)); int soo_select __P((struct file *fp, int which, struct proc *p)); +int soo_kqfilter __P((struct file *fp, struct knote *kn)); int soo_close __P((struct file *fp, struct proc *p)); int soo_stat __P((struct socket *, struct stat *)); int uipc_usrreq __P((struct socket *, int , struct mbuf *, diff --git a/sys/sys/specdev.h b/sys/sys/specdev.h index 3d7de64876b..ea0eea0c841 100644 --- a/sys/sys/specdev.h +++ b/sys/sys/specdev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: specdev.h,v 1.8 2001/02/23 14:42:39 csapuntz Exp $ */ +/* $OpenBSD: specdev.h,v 1.9 2001/03/01 20:54:35 provos Exp $ */ /* $NetBSD: specdev.h,v 1.12 1996/02/13 13:13:01 mycroft Exp $ */ /* @@ -97,6 +97,7 @@ int spec_write __P((void *)); #define spec_lease_check nullop int spec_ioctl __P((void *)); int spec_select __P((void *)); +int spec_kqfilter __P((void *)); #define spec_mmap spec_badop int spec_fsync __P((void *)); #define spec_seek spec_badop diff --git a/sys/sys/tty.h b/sys/sys/tty.h index 36f822b1095..b611311f944 100644 --- a/sys/sys/tty.h +++ b/sys/sys/tty.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.h,v 1.7 2000/11/16 20:02:21 provos Exp $ */ +/* $OpenBSD: tty.h,v 1.8 2001/03/01 20:54:35 provos Exp $ */ /* $NetBSD: tty.h,v 1.30.4.1 1996/06/02 09:08:13 mrg Exp $ */ /*- @@ -227,6 +227,7 @@ int ttioctl __P((struct tty *tp, u_long com, caddr_t data, int flag, int ttread __P((struct tty *tp, struct uio *uio, int flag)); void ttrstrt __P((void *tp)); int ttselect __P((dev_t device, int rw, struct proc *p)); +int ttkqfilter __P((dev_t dev, struct knote *kn)); void ttsetwater __P((struct tty *tp)); int ttspeedtab __P((int speed, struct speedtab *table)); int ttstart __P((struct tty *tp)); diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 2e2da61ccd7..02e87bf79fc 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_vnops.c,v 1.12 2001/02/24 19:07:10 csapuntz Exp $ */ +/* $OpenBSD: ffs_vnops.c,v 1.13 2001/03/01 20:54:36 provos Exp $ */ /* $NetBSD: ffs_vnops.c,v 1.7 1996/05/11 18:27:24 mycroft Exp $ */ /* @@ -86,6 +86,7 @@ struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { { &vop_lease_desc, ufs_lease_check }, /* lease */ { &vop_ioctl_desc, ufs_ioctl }, /* ioctl */ { &vop_select_desc, ufs_select }, /* select */ + { &vop_kqfilter_desc, ufs_kqfilter }, /* kqfilter */ { &vop_revoke_desc, ufs_revoke }, /* revoke */ { &vop_mmap_desc, ufs_mmap }, /* mmap */ { &vop_fsync_desc, ffs_fsync }, /* fsync */ @@ -138,7 +139,8 @@ struct vnodeopv_entry_desc ffs_specop_entries[] = { { &vop_lease_desc, spec_lease_check }, /* lease */ { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ { &vop_select_desc, spec_select }, /* select */ - { &vop_revoke_desc, spec_revoke }, /* revoke */ + { &vop_kqfilter_desc, spec_kqfilter }, /* kqfilter */ + { &vop_revoke_desc, spec_revoke }, /* revoke */ { &vop_mmap_desc, spec_mmap }, /* mmap */ { &vop_fsync_desc, ffs_fsync }, /* fsync */ { &vop_seek_desc, spec_seek }, /* seek */ @@ -191,6 +193,7 @@ struct vnodeopv_entry_desc ffs_fifoop_entries[] = { { &vop_lease_desc, fifo_lease_check }, /* lease */ { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ { &vop_select_desc, fifo_select }, /* select */ + { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */ { &vop_revoke_desc, fifo_revoke }, /* revoke */ { &vop_mmap_desc, fifo_mmap }, /* mmap */ { &vop_fsync_desc, ffs_fsync }, /* fsync */ diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h index bdf0c2b3abf..c0f10acdf92 100644 --- a/sys/ufs/ufs/ufs_extern.h +++ b/sys/ufs/ufs/ufs_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_extern.h,v 1.10 2001/02/21 23:24:31 csapuntz Exp $ */ +/* $OpenBSD: ufs_extern.h,v 1.11 2001/03/01 20:54:36 provos Exp $ */ /* $NetBSD: ufs_extern.h,v 1.5 1996/02/09 22:36:03 christos Exp $ */ /*- @@ -90,6 +90,7 @@ int ufs_rename __P((void *)); int ufs_rmdir __P((void *)); int ufs_seek __P((void *)); int ufs_select __P((void *)); +int ufs_kqfilter __P((void *)); int ufs_setattr __P((void *)); int ufs_strategy __P((void *)); int ufs_symlink __P((void *)); diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index e224d37e729..211b66cad2b 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_vnops.c,v 1.29 2001/02/21 23:24:32 csapuntz Exp $ */ +/* $OpenBSD: ufs_vnops.c,v 1.30 2001/03/01 20:54:36 provos Exp $ */ /* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */ /* @@ -77,6 +77,9 @@ static int ufs_chmod __P((struct vnode *, int, struct ucred *, struct proc *)); static int ufs_chown __P((struct vnode *, uid_t, gid_t, struct ucred *, struct proc *)); +int filt_ufsread __P((struct knote *kn, long hint)); +int filt_ufsvnode __P((struct knote *kn, long hint)); +void filt_ufsdetach __P((struct knote *kn)); union _qcvt { int64_t qcvt; @@ -2205,4 +2208,85 @@ bad: return (error); } +struct filterops ufsread_filtops = + { 1, NULL, filt_ufsdetach, filt_ufsread }; +struct filterops ufsvnode_filtops = + { 1, NULL, filt_ufsdetach, filt_ufsvnode }; + +int +ufs_kqfilter(v) + void *v; +{ + struct vop_kqfilter_args /* { + struct vnode *a_vp; + struct knote *a_kn; + } */ *ap = v; + struct vnode *vp = ap->a_vp; + struct knote *kn = ap->a_kn; + + switch (kn->kn_filter) { + case EVFILT_READ: + kn->kn_fop = &ufsread_filtops; + break; + case EVFILT_VNODE: + kn->kn_fop = &ufsvnode_filtops; + break; + default: + return (1); + } + + kn->kn_hook = (caddr_t)vp; + + simple_lock(&vp->v_selectinfo.vsi_lock); + SLIST_INSERT_HEAD(&vp->v_selectinfo.vsi_selinfo.si_note, kn, kn_selnext); + simple_unlock(&vp->v_selectinfo.vsi_lock); + + return (0); +} + +void +filt_ufsdetach(struct knote *kn) +{ + struct vnode *vp = (struct vnode *)kn->kn_hook; + + simple_lock(&vp->v_selectinfo.vsi_lock); + SLIST_REMOVE(&vp->v_selectinfo.vsi_selinfo.si_note, + kn, knote, kn_selnext); + simple_unlock(&vp->v_selectinfo.vsi_lock); +} + +/*ARGSUSED*/ +int +filt_ufsread(struct knote *kn, long hint) +{ + struct vnode *vp = (struct vnode *)kn->kn_hook; + struct inode *ip = VTOI(vp); + + /* + * filesystem is gone, so set the EOF flag and schedule + * the knote for deletion. + */ + if (hint == NOTE_REVOKE) { + kn->kn_flags |= (EV_EOF | EV_ONESHOT); + return (1); + } + + kn->kn_data = ip->i_ffs_size - kn->kn_fp->f_offset; + return (kn->kn_data != 0); +} + +int +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; + return (1); + } + return (kn->kn_fflags != 0); +} + + |