summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>2001-03-01 20:54:37 +0000
committerNiels Provos <provos@cvs.openbsd.org>2001-03-01 20:54:37 +0000
commit950a6333d90c04783291b2f77e89257bc6df966e (patch)
tree0d452c7deda41df938a0f8d009e3f850249b8eb8 /sys
parent9027db9730b3cc9c6f973b4e6fbdf6b353260158 (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.c5
-rw-r--r--sys/dev/cons.c19
-rw-r--r--sys/dev/cons.h5
-rw-r--r--sys/dev/wscons/wsdisplay.c21
-rw-r--r--sys/kern/kern_event.c150
-rw-r--r--sys/kern/spec_vnops.c21
-rw-r--r--sys/kern/sys_pipe.c32
-rw-r--r--sys/kern/sys_socket.c8
-rw-r--r--sys/kern/tty.c91
-rw-r--r--sys/kern/uipc_socket.c60
-rw-r--r--sys/kern/vfs_vnops.c87
-rw-r--r--sys/kern/vnode_if.src10
-rw-r--r--sys/miscfs/fifofs/fifo.h3
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c96
-rw-r--r--sys/miscfs/specfs/spec_vnops.c21
-rw-r--r--sys/miscfs/specfs/specdev.h3
-rw-r--r--sys/sys/conf.h29
-rw-r--r--sys/sys/event.h22
-rw-r--r--sys/sys/file.h5
-rw-r--r--sys/sys/socketvar.h4
-rw-r--r--sys/sys/specdev.h3
-rw-r--r--sys/sys/tty.h3
-rw-r--r--sys/ufs/ffs/ffs_vnops.c7
-rw-r--r--sys/ufs/ufs/ufs_extern.h3
-rw-r--r--sys/ufs/ufs/ufs_vnops.c86
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);
+}
+
+