summaryrefslogtreecommitdiff
path: root/sys/kern
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/kern
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/kern')
-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
8 files changed, 254 insertions, 205 deletions
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 {