aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/cy/cy.c5
-rw-r--r--sys/dev/cy/cy_isa.c5
-rw-r--r--sys/dev/dgb/dgb.c5
-rw-r--r--sys/dev/dgb/dgm.c5
-rw-r--r--sys/dev/rc/rc.c5
-rw-r--r--sys/dev/si/si.c5
-rw-r--r--sys/dev/sio/sio.c5
-rw-r--r--sys/dev/streams/streams.c3
-rw-r--r--sys/dev/usb/umodem.c5
-rw-r--r--sys/fs/fifofs/fifo_vnops.c66
-rw-r--r--sys/fs/specfs/spec_vnops.c19
-rw-r--r--sys/i386/isa/cx.c5
-rw-r--r--sys/i386/isa/cy.c5
-rw-r--r--sys/i386/isa/istallion.c5
-rw-r--r--sys/i386/isa/pcvt/pcvt_drv.c5
-rw-r--r--sys/i386/isa/rc.c5
-rw-r--r--sys/i386/isa/rp.c5
-rw-r--r--sys/i386/isa/stallion.c5
-rw-r--r--sys/isa/sio.c5
-rw-r--r--sys/kern/kern_descrip.c11
-rw-r--r--sys/kern/kern_event.c107
-rw-r--r--sys/kern/subr_xxx.c9
-rw-r--r--sys/kern/sys_pipe.c31
-rw-r--r--sys/kern/sys_socket.c6
-rw-r--r--sys/kern/tty.c89
-rw-r--r--sys/kern/tty_cons.c20
-rw-r--r--sys/kern/tty_pty.c10
-rw-r--r--sys/kern/uipc_socket.c55
-rw-r--r--sys/kern/vfs_vnops.c87
-rw-r--r--sys/kern/vnode_if.src8
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c66
-rw-r--r--sys/miscfs/specfs/spec_vnops.c19
-rw-r--r--sys/sys/conf.h16
-rw-r--r--sys/sys/event.h1
-rw-r--r--sys/sys/file.h13
-rw-r--r--sys/sys/linedisc.h16
-rw-r--r--sys/sys/socketvar.h2
-rw-r--r--sys/sys/tty.h1
-rw-r--r--sys/ufs/ufs/ufs_vnops.c72
39 files changed, 511 insertions, 296 deletions
diff --git a/sys/dev/cy/cy.c b/sys/dev/cy/cy.c
index 9a56e2df1010..7d7671d9419b 100644
--- a/sys/dev/cy/cy.c
+++ b/sys/dev/cy/cy.c
@@ -405,8 +405,9 @@ static struct cdevsw sio_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
static int comconsole = -1;
diff --git a/sys/dev/cy/cy_isa.c b/sys/dev/cy/cy_isa.c
index 9a56e2df1010..7d7671d9419b 100644
--- a/sys/dev/cy/cy_isa.c
+++ b/sys/dev/cy/cy_isa.c
@@ -405,8 +405,9 @@ static struct cdevsw sio_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
static int comconsole = -1;
diff --git a/sys/dev/dgb/dgb.c b/sys/dev/dgb/dgb.c
index 84e81022c1f0..818aad7a8bbd 100644
--- a/sys/dev/dgb/dgb.c
+++ b/sys/dev/dgb/dgb.c
@@ -255,8 +255,9 @@ static struct cdevsw dgb_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
static speed_t dgbdefaultrate = TTYDEF_SPEED;
diff --git a/sys/dev/dgb/dgm.c b/sys/dev/dgb/dgm.c
index e6eef8f547ec..0e0bcfed9907 100644
--- a/sys/dev/dgb/dgm.c
+++ b/sys/dev/dgb/dgm.c
@@ -258,8 +258,9 @@ static struct cdevsw dgm_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
static speed_t dgmdefaultrate = TTYDEF_SPEED;
diff --git a/sys/dev/rc/rc.c b/sys/dev/rc/rc.c
index a7e5ecbc8d43..6c1ca5d4aaca 100644
--- a/sys/dev/rc/rc.c
+++ b/sys/dev/rc/rc.c
@@ -107,8 +107,9 @@ static struct cdevsw rc_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
/* Per-board structure */
diff --git a/sys/dev/si/si.c b/sys/dev/si/si.c
index cc61a175111b..753849bf496c 100644
--- a/sys/dev/si/si.c
+++ b/sys/dev/si/si.c
@@ -129,8 +129,9 @@ static struct cdevsw si_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
static int si_Nports;
diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c
index ee3d4f180cf6..d8f02c9b5cee 100644
--- a/sys/dev/sio/sio.c
+++ b/sys/dev/sio/sio.c
@@ -388,8 +388,9 @@ static struct cdevsw sio_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
int comconsole = -1;
diff --git a/sys/dev/streams/streams.c b/sys/dev/streams/streams.c
index 1d779f4a9f34..8f279da0cf1b 100644
--- a/sys/dev/streams/streams.c
+++ b/sys/dev/streams/streams.c
@@ -99,7 +99,8 @@ dev_t dt_ptm, dt_arp, dt_icmp, dt_ip, dt_tcp, dt_udp, dt_rawip,
dt_unix_dgram, dt_unix_stream, dt_unix_ord_stream;
static struct fileops svr4_netops = {
- soo_read, soo_write, soo_ioctl, soo_poll, soo_stat, svr4_soo_close
+ soo_read, soo_write, soo_ioctl, soo_poll, sokqfilter,
+ soo_stat, svr4_soo_close
};
#define CDEV_MAJOR 103
diff --git a/sys/dev/usb/umodem.c b/sys/dev/usb/umodem.c
index 3305eeeb7172..b715c5ee0590 100644
--- a/sys/dev/usb/umodem.c
+++ b/sys/dev/usb/umodem.c
@@ -171,8 +171,9 @@ static struct cdevsw umodem_cdevsw = {
/* maj */ UMODEM_CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
#endif
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index 453f2077bec7..79ee0aa7a3d9 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -71,21 +71,20 @@ static int fifo_read __P((struct vop_read_args *));
static int fifo_write __P((struct vop_write_args *));
static int fifo_ioctl __P((struct vop_ioctl_args *));
static int fifo_poll __P((struct vop_poll_args *));
+static int fifo_kqfilter __P((struct vop_kqfilter_args *));
static int fifo_bmap __P((struct vop_bmap_args *));
static int fifo_pathconf __P((struct vop_pathconf_args *));
static int fifo_advlock __P((struct vop_advlock_args *));
-static int filt_fiforattach(struct knote *kn);
static void filt_fifordetach(struct knote *kn);
static int filt_fiforead(struct knote *kn, long hint);
-static int filt_fifowattach(struct knote *kn);
static void filt_fifowdetach(struct knote *kn);
static int filt_fifowrite(struct knote *kn, long hint);
-struct filterops fifo_rwfiltops[] = {
- { 1, filt_fiforattach, filt_fifordetach, filt_fiforead },
- { 1, filt_fifowattach, filt_fifowdetach, filt_fifowrite },
-};
+static struct filterops fiforead_filtops =
+ { 1, NULL, filt_fifordetach, filt_fiforead };
+static struct filterops fifowrite_filtops =
+ { 1, NULL, filt_fifowdetach, filt_fifowrite };
vop_t **fifo_vnodeop_p;
static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
@@ -106,6 +105,7 @@ static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
{ &vop_open_desc, (vop_t *) fifo_open },
{ &vop_pathconf_desc, (vop_t *) fifo_pathconf },
{ &vop_poll_desc, (vop_t *) fifo_poll },
+ { &vop_kqfilter_desc, (vop_t *) fifo_kqfilter },
{ &vop_print_desc, (vop_t *) fifo_print },
{ &vop_read_desc, (vop_t *) fifo_read },
{ &vop_readdir_desc, (vop_t *) fifo_badop },
@@ -354,22 +354,42 @@ fifo_ioctl(ap)
return (0);
}
+/* ARGSUSED */
static int
-filt_fiforattach(struct knote *kn)
+fifo_kqfilter(ap)
+ struct vop_kqfilter_args /* {
+ struct vnode *a_vp;
+ struct knote *a_kn;
+ } */ *ap;
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ 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;
- SLIST_INSERT_HEAD(&so->so_rcv.sb_sel.si_note, kn, kn_selnext);
- so->so_rcv.sb_flags |= SB_KNOTE;
return (0);
}
static void
filt_fifordetach(struct knote *kn)
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ 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))
@@ -379,8 +399,7 @@ filt_fifordetach(struct knote *kn)
static int
filt_fiforead(struct knote *kn, long hint)
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ struct socket *so = (struct socket *)kn->kn_hook;
kn->kn_data = so->so_rcv.sb_cc;
if (so->so_state & SS_CANTRCVMORE) {
@@ -391,22 +410,10 @@ filt_fiforead(struct knote *kn, long hint)
return (kn->kn_data > 0);
}
-static int
-filt_fifowattach(struct knote *kn)
-{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_writesock;
-
- SLIST_INSERT_HEAD(&so->so_snd.sb_sel.si_note, kn, kn_selnext);
- so->so_rcv.sb_flags |= SB_KNOTE;
- return (0);
-}
-
static void
filt_fifowdetach(struct knote *kn)
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ 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))
@@ -416,8 +423,7 @@ filt_fifowdetach(struct knote *kn)
static int
filt_fifowrite(struct knote *kn, long hint)
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ struct socket *so = (struct socket *)kn->kn_hook;
kn->kn_data = sbspace(&so->so_snd);
if (so->so_state & SS_CANTSENDMORE) {
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index dce82120cb4b..35a0a49f7bb7 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -62,6 +62,7 @@ static int spec_getpages __P((struct vop_getpages_args *));
static int spec_ioctl __P((struct vop_ioctl_args *));
static int spec_open __P((struct vop_open_args *));
static int spec_poll __P((struct vop_poll_args *));
+static int spec_kqfilter __P((struct vop_kqfilter_args *));
static int spec_print __P((struct vop_print_args *));
static int spec_read __P((struct vop_read_args *));
static int spec_strategy __P((struct vop_strategy_args *));
@@ -87,6 +88,7 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_open_desc, (vop_t *) spec_open },
{ &vop_pathconf_desc, (vop_t *) vop_stdpathconf },
{ &vop_poll_desc, (vop_t *) spec_poll },
+ { &vop_kqfilter_desc, (vop_t *) spec_kqfilter },
{ &vop_print_desc, (vop_t *) spec_print },
{ &vop_read_desc, (vop_t *) spec_read },
{ &vop_readdir_desc, (vop_t *) vop_panic },
@@ -330,6 +332,23 @@ spec_poll(ap)
dev = ap->a_vp->v_rdev;
return (*devsw(dev)->d_poll)(dev, ap->a_events, ap->a_p);
}
+
+/* ARGSUSED */
+static int
+spec_kqfilter(ap)
+ struct vop_kqfilter_args /* {
+ struct vnode *a_vp;
+ struct knote *a_kn;
+ } */ *ap;
+{
+ dev_t dev;
+
+ dev = ap->a_vp->v_rdev;
+ if (devsw(dev)->d_flags & D_KQFILTER)
+ return (*devsw(dev)->d_kqfilter)(dev, ap->a_kn);
+ return (1);
+}
+
/*
* Synch buffers associated with a block device
*/
diff --git a/sys/i386/isa/cx.c b/sys/i386/isa/cx.c
index 094dc6fe2674..1ec334b53799 100644
--- a/sys/i386/isa/cx.c
+++ b/sys/i386/isa/cx.c
@@ -100,8 +100,9 @@ struct cdevsw cx_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
#else
struct tty *cx_tty [NCX*NCHAN]; /* tty data */
diff --git a/sys/i386/isa/cy.c b/sys/i386/isa/cy.c
index 9a56e2df1010..7d7671d9419b 100644
--- a/sys/i386/isa/cy.c
+++ b/sys/i386/isa/cy.c
@@ -405,8 +405,9 @@ static struct cdevsw sio_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
static int comconsole = -1;
diff --git a/sys/i386/isa/istallion.c b/sys/i386/isa/istallion.c
index 61b7a5087060..41f66be833a3 100644
--- a/sys/i386/isa/istallion.c
+++ b/sys/i386/isa/istallion.c
@@ -654,8 +654,9 @@ static struct cdevsw stli_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
#endif
diff --git a/sys/i386/isa/pcvt/pcvt_drv.c b/sys/i386/isa/pcvt/pcvt_drv.c
index 74134bdeb301..eddc14ac5e85 100644
--- a/sys/i386/isa/pcvt/pcvt_drv.c
+++ b/sys/i386/isa/pcvt/pcvt_drv.c
@@ -108,8 +108,9 @@ static struct cdevsw vt_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
static int pcvt_probe(device_t dev);
diff --git a/sys/i386/isa/rc.c b/sys/i386/isa/rc.c
index a7e5ecbc8d43..6c1ca5d4aaca 100644
--- a/sys/i386/isa/rc.c
+++ b/sys/i386/isa/rc.c
@@ -107,8 +107,9 @@ static struct cdevsw rc_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
/* Per-board structure */
diff --git a/sys/i386/isa/rp.c b/sys/i386/isa/rp.c
index 21c30cc2aad6..2740470d9796 100644
--- a/sys/i386/isa/rp.c
+++ b/sys/i386/isa/rp.c
@@ -816,8 +816,9 @@ static struct cdevsw rp_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
static int rp_controller_port = 0;
diff --git a/sys/i386/isa/stallion.c b/sys/i386/isa/stallion.c
index 73c2ce19b387..9a4ee7f62606 100644
--- a/sys/i386/isa/stallion.c
+++ b/sys/i386/isa/stallion.c
@@ -552,8 +552,9 @@ static struct cdevsw stl_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
static void stl_drvinit(void *unused)
diff --git a/sys/isa/sio.c b/sys/isa/sio.c
index ee3d4f180cf6..d8f02c9b5cee 100644
--- a/sys/isa/sio.c
+++ b/sys/isa/sio.c
@@ -388,8 +388,9 @@ static struct cdevsw sio_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
int comconsole = -1;
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 75ec0ee3f46e..45273463588d 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -93,6 +93,7 @@ static int badfo_ioctl __P((struct file *fp, u_long com, caddr_t data,
struct proc *p));
static int badfo_poll __P((struct file *fp, int events,
struct ucred *cred, struct proc *p));
+static int badfo_kqfilter __P((struct file *fp, struct knote *kn));
static int badfo_stat __P((struct file *fp, struct stat *sb, struct proc *p));
static int badfo_close __P((struct file *fp, struct proc *p));
@@ -1507,6 +1508,7 @@ struct fileops badfileops = {
badfo_readwrite,
badfo_ioctl,
badfo_poll,
+ badfo_kqfilter,
badfo_stat,
badfo_close
};
@@ -1546,6 +1548,15 @@ badfo_poll(fp, events, cred, p)
}
static int
+badfo_kqfilter(fp, kn)
+ struct file *fp;
+ struct knote *kn;
+{
+
+ return (0);
+}
+
+static int
badfo_stat(fp, sb, p)
struct file *fp;
struct stat *sb;
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index c1604d2af5c2..12fb698edd19 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -48,15 +48,6 @@
#include <vm/vm_zone.h>
-static int filt_nullattach(struct knote *kn);
-static int filt_rwtypattach(struct knote *kn);
-static int filt_kqattach(struct knote *kn);
-static void filt_kqdetach(struct knote *kn);
-static int filt_kqueue(struct knote *kn, long hint);
-static int filt_procattach(struct knote *kn);
-static void filt_procdetach(struct knote *kn);
-static int filt_proc(struct knote *kn, long hint);
-
static int kqueue_scan(struct file *fp, int maxevents,
struct kevent *ulistp, const struct timespec *timeout,
struct proc *p);
@@ -68,10 +59,21 @@ static int kqueue_ioctl(struct file *fp, u_long com, caddr_t data,
struct proc *p);
static int kqueue_poll(struct file *fp, int events, struct ucred *cred,
struct proc *p);
+static int kqueue_kqfilter(struct file *fp, struct knote *kn);
static int kqueue_stat(struct file *fp, struct stat *st, struct proc *p);
static int kqueue_close(struct file *fp, struct proc *p);
static void kqueue_wakeup(struct kqueue *kq);
+static struct fileops kqueueops = {
+ kqueue_read,
+ kqueue_write,
+ kqueue_ioctl,
+ kqueue_poll,
+ kqueue_kqfilter,
+ kqueue_stat,
+ kqueue_close
+};
+
static void knote_attach(struct knote *kn, struct filedesc *fdp);
static void knote_drop(struct knote *kn, struct proc *p);
static void knote_enqueue(struct knote *kn);
@@ -80,6 +82,20 @@ static void knote_init(void);
static struct knote *knote_alloc(void);
static void knote_free(struct knote *kn);
+static void filt_kqdetach(struct knote *kn);
+static int filt_kqueue(struct knote *kn, long hint);
+static int filt_procattach(struct knote *kn);
+static void filt_procdetach(struct knote *kn);
+static int filt_proc(struct knote *kn, long hint);
+static int filt_fileattach(struct knote *kn);
+
+static struct filterops kqread_filtops =
+ { 1, NULL, filt_kqdetach, filt_kqueue };
+static struct filterops proc_filtops =
+ { 0, filt_procattach, filt_procdetach, filt_proc };
+static struct filterops file_filtops =
+ { 1, filt_fileattach, NULL, NULL };
+
static vm_zone_t knote_zone;
#define KNOTE_ACTIVATE(kn) do { \
@@ -91,85 +107,38 @@ static vm_zone_t knote_zone;
#define KN_HASHSIZE 64 /* XXX should be tunable */
#define KN_HASH(val, mask) (((val) ^ (val >> 8)) & (mask))
-static struct fileops kqueueops = {
- kqueue_read,
- kqueue_write,
- kqueue_ioctl,
- kqueue_poll,
- kqueue_stat,
- kqueue_close
-};
-
-extern struct filterops so_rwfiltops[];
-extern struct filterops fifo_rwfiltops[];
-extern struct filterops pipe_rwfiltops[];
-extern struct filterops vn_rwfiltops[];
-
-static struct filterops kq_rwfiltops[] = {
- { 1, filt_kqattach, filt_kqdetach, filt_kqueue },
- { 1, filt_nullattach, NULL, NULL },
-};
-
extern struct filterops aio_filtops;
extern struct filterops sig_filtops;
-extern struct filterops vn_filtops;
-
-static struct filterops rwtype_filtops =
- { 1, filt_rwtypattach, NULL, NULL };
-static struct filterops proc_filtops =
- { 0, filt_procattach, filt_procdetach, filt_proc };
-
-/*
- * XXX
- * These must match the order of defines in <sys/file.h>
- */
-static 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 for all system-defined filters.
+ * Table for for all system-defined filters.
*/
static struct filterops *sysfilt_ops[] = {
- &rwtype_filtops, /* EVFILT_READ */
- &rwtype_filtops, /* EVFILT_WRITE */
+ &file_filtops, /* EVFILT_READ */
+ &file_filtops, /* EVFILT_WRITE */
&aio_filtops, /* EVFILT_AIO */
- &vn_filtops, /* EVFILT_VNODE */
+ &file_filtops, /* EVFILT_VNODE */
&proc_filtops, /* EVFILT_PROC */
&sig_filtops, /* EVFILT_SIGNAL */
};
static int
-filt_nullattach(struct knote *kn)
-{
- return (ENXIO);
-}
-
-/*
- * file-type specific attach routine for read/write filters
- */
-static int
-filt_rwtypattach(struct knote *kn)
+filt_fileattach(struct knote *kn)
{
- struct filterops *fops;
-
- 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 (fo_kqfilter(kn->kn_fp, kn));
}
+/*ARGSUSED*/
static 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);
}
diff --git a/sys/kern/subr_xxx.c b/sys/kern/subr_xxx.c
index 6819fb38c57a..f3fd2ed2493b 100644
--- a/sys/kern/subr_xxx.c
+++ b/sys/kern/subr_xxx.c
@@ -134,6 +134,15 @@ noioctl(dev, cmd, data, flags, p)
}
int
+nokqfilter(dev, kn)
+ dev_t dev;
+ struct knote *kn;
+{
+
+ return (ENODEV);
+}
+
+int
nommap(dev, offset, nprot)
dev_t dev;
vm_offset_t offset;
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index cd9e3a7cf1a3..42786d95c14d 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -95,21 +95,24 @@ static int pipe_write __P((struct file *fp, struct uio *uio,
static int pipe_close __P((struct file *fp, struct proc *p));
static int pipe_poll __P((struct file *fp, int events, struct ucred *cred,
struct proc *p));
+static int pipe_kqfilter __P((struct file *fp, struct knote *kn));
static int pipe_stat __P((struct file *fp, struct stat *sb, struct proc *p));
static int pipe_ioctl __P((struct file *fp, u_long cmd, caddr_t data, struct proc *p));
-static struct fileops pipeops =
- { pipe_read, pipe_write, pipe_ioctl, pipe_poll, pipe_stat, pipe_close };
+static struct fileops pipeops = {
+ pipe_read, pipe_write, pipe_ioctl, pipe_poll, pipe_kqfilter,
+ pipe_stat, pipe_close
+};
-static int filt_pipeattach(struct knote *kn);
static void filt_pipedetach(struct knote *kn);
static int filt_piperead(struct knote *kn, long hint);
static 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 },
-};
+static struct filterops pipe_rfiltops =
+ { 1, NULL, filt_pipedetach, filt_piperead };
+static struct filterops pipe_wfiltops =
+ { 1, NULL, filt_pipedetach, filt_pipewrite };
+
/*
* Default pipe buffer size(s), this can be kind-of large now because pipe
@@ -1186,11 +1189,23 @@ pipeclose(cpipe)
}
}
+/*ARGSUSED*/
static 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 f58720b7e4a5..e4db298b339f 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -50,8 +50,10 @@
#include <net/if.h>
#include <net/route.h>
-struct fileops socketops =
- { soo_read, soo_write, soo_ioctl, soo_poll, soo_stat, soo_close };
+struct fileops socketops = {
+ soo_read, soo_write, soo_ioctl, soo_poll, sokqfilter,
+ soo_stat, soo_close
+};
/* ARGSUSED */
int
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index b815e7c75d5a..b5b8a9cd13b8 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -113,6 +113,10 @@ static void ttyrub __P((int c, struct tty *tp));
static void ttyrubo __P((struct tty *tp, int cnt));
static void ttyunblock __P((struct tty *tp));
static int ttywflush __P((struct tty *tp));
+static int filt_ttyread __P((struct knote *kn, long hint));
+static void filt_ttyrdetach __P((struct knote *kn));
+static int filt_ttywrite __P((struct knote *kn, long hint));
+static void filt_ttywdetach __P((struct knote *kn));
/*
* Table with character classes and parity. The 8th bit indicates parity,
@@ -1092,6 +1096,89 @@ ttypoll(dev, events, p)
return (revents);
}
+static struct filterops ttyread_filtops =
+ { 1, NULL, filt_ttyrdetach, filt_ttyread };
+static struct filterops ttywrite_filtops =
+ { 1, NULL, filt_ttywdetach, filt_ttywrite };
+
+int
+ttykqfilter(dev, kn)
+ dev_t dev;
+ struct knote *kn;
+{
+ struct tty *tp = dev->si_tty;
+ 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);
+}
+
+static void
+filt_ttyrdetach(struct knote *kn)
+{
+ struct tty *tp = ((dev_t)kn->kn_hook)->si_tty;
+ int s = spltty();
+
+ SLIST_REMOVE(&tp->t_rsel.si_note, kn, knote, kn_selnext);
+ splx(s);
+}
+
+static int
+filt_ttyread(struct knote *kn, long hint)
+{
+ struct tty *tp = ((dev_t)kn->kn_hook)->si_tty;
+
+ kn->kn_data = ttnread(tp);
+ if (ISSET(tp->t_state, TS_ZOMBIE)) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ return (kn->kn_data > 0);
+}
+
+static void
+filt_ttywdetach(struct knote *kn)
+{
+ struct tty *tp = ((dev_t)kn->kn_hook)->si_tty;
+ int s = spltty();
+
+ SLIST_REMOVE(&tp->t_wsel.si_note, kn, knote, kn_selnext);
+ splx(s);
+}
+
+static int
+filt_ttywrite(kn, hint)
+ struct knote *kn;
+ long hint;
+{
+ struct tty *tp = ((dev_t)kn->kn_hook)->si_tty;
+
+ kn->kn_data = tp->t_outq.c_cc;
+ if (ISSET(tp->t_state, TS_ZOMBIE))
+ return (1);
+ return (kn->kn_data <= tp->t_olowat &&
+ ISSET(tp->t_state, TS_CONNECTED));
+}
+
/*
* Must be called at spltty().
*/
@@ -2118,6 +2205,7 @@ ttwakeup(tp)
if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
wakeup(TSA_HUP_OR_INPUT(tp));
+ KNOTE(&tp->t_rsel.si_note, 0);
}
/*
@@ -2142,6 +2230,7 @@ ttwwakeup(tp)
CLR(tp->t_state, TS_SO_OLOWAT);
wakeup(TSA_OLOWAT(tp));
}
+ KNOTE(&tp->t_wsel.si_note, 0);
}
/*
diff --git a/sys/kern/tty_cons.c b/sys/kern/tty_cons.c
index 784fecad98e2..9aa2c23386d6 100644
--- a/sys/kern/tty_cons.c
+++ b/sys/kern/tty_cons.c
@@ -58,6 +58,7 @@ static d_read_t cnread;
static d_write_t cnwrite;
static d_ioctl_t cnioctl;
static d_poll_t cnpoll;
+static d_kqfilter_t cnkqfilter;
#define CDEV_MAJOR 0
static struct cdevsw cn_cdevsw = {
@@ -73,8 +74,9 @@ static struct cdevsw cn_cdevsw = {
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ cnkqfilter,
};
static dev_t cn_dev_t; /* seems to be never really used */
@@ -398,6 +400,20 @@ cnpoll(dev, events, p)
return ((*devsw(dev)->d_poll)(dev, events, p));
}
+static int
+cnkqfilter(dev, kn)
+ dev_t dev;
+ struct knote *kn;
+{
+ if ((cn_tab == NULL) || cn_mute)
+ return (1);
+
+ dev = cn_tab->cn_dev;
+ if (devsw(dev)->d_flags & D_KQFILTER)
+ return ((*devsw(dev)->d_kqfilter)(dev, kn));
+ return (1);
+}
+
int
cngetc()
{
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index f7a4370ffda5..b6063fc620ab 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -86,8 +86,9 @@ static struct cdevsw pts_cdevsw = {
/* maj */ CDEV_MAJOR_S,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
#define CDEV_MAJOR_C 6
@@ -104,8 +105,9 @@ static struct cdevsw ptc_cdevsw = {
/* maj */ CDEV_MAJOR_C,
/* dump */ nodump,
/* psize */ nopsize,
- /* flags */ D_TTY,
- /* bmaj */ -1
+ /* flags */ D_TTY | D_KQFILTER,
+ /* bmaj */ -1,
+ /* kqfilter */ ttykqfilter,
};
#define BUFSIZ 100 /* Chunk size iomoved to/from user */
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index d8a95cf2efd5..85667de0464c 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -64,21 +64,18 @@
static int do_setopt_accept_filter(struct socket *so, struct sockopt *sopt);
#endif
-static int filt_sorattach(struct knote *kn);
static void filt_sordetach(struct knote *kn);
static int filt_soread(struct knote *kn, long hint);
-static int filt_sowattach(struct knote *kn);
static void filt_sowdetach(struct knote *kn);
static int filt_sowrite(struct knote *kn, long hint);
static int filt_solisten(struct knote *kn, long hint);
static struct filterops solisten_filtops =
- { 1, filt_sorattach, filt_sordetach, filt_solisten };
-
-struct filterops so_rwfiltops[] = {
- { 1, filt_sorattach, filt_sordetach, filt_soread },
- { 1, filt_sowattach, filt_sowdetach, filt_sowrite },
-};
+ { 1, NULL, filt_sordetach, filt_solisten };
+static struct filterops soread_filtops =
+ { 1, NULL, filt_sordetach, filt_soread };
+static struct filterops sowrite_filtops =
+ { 1, NULL, filt_sowdetach, filt_sowrite };
struct vm_zone *socket_zone;
so_gen_t so_gencnt; /* generation count for sockets */
@@ -1534,16 +1531,32 @@ sopoll(struct socket *so, int events, struct ucred *cred, struct proc *p)
return (revents);
}
-static int
-filt_sorattach(struct knote *kn)
+int
+sokqfilter(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);
}
@@ -1576,18 +1589,6 @@ filt_soread(struct knote *kn, long hint)
return (kn->kn_data >= so->so_rcv.sb_lowat);
}
-static 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);
-}
-
static void
filt_sowdetach(struct knote *kn)
{
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 01751233e4a7..760df67c3efc 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -55,9 +55,6 @@
#include <sys/ttycom.h>
#include <sys/conf.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-
static int vn_closefile __P((struct file *fp, struct proc *p));
static int vn_ioctl __P((struct file *fp, u_long com, caddr_t data,
struct proc *p));
@@ -65,30 +62,14 @@ static int vn_read __P((struct file *fp, struct uio *uio,
struct ucred *cred, int flags, struct proc *p));
static int vn_poll __P((struct file *fp, int events, struct ucred *cred,
struct proc *p));
+static int vn_kqfilter __P((struct file *fp, struct knote *kn));
static int vn_statfile __P((struct file *fp, struct stat *sb, struct proc *p));
static int vn_write __P((struct file *fp, struct uio *uio,
struct ucred *cred, int flags, struct proc *p));
-struct fileops vnops =
- { vn_read, vn_write, vn_ioctl, vn_poll, vn_statfile, 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 },
+struct fileops vnops = {
+ vn_read, vn_write, vn_ioctl, vn_poll, vn_kqfilter,
+ vn_statfile, vn_closefile
};
/*
@@ -815,66 +796,10 @@ vfs_write_resume(mp)
}
static int
-filt_vnattach(struct knote *kn)
-{
- struct vnode *vp;
-
- if (kn->kn_fp->f_type != DTYPE_VNODE &&
- kn->kn_fp->f_type != DTYPE_FIFO)
- 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)
- return (EOPNOTSUPP);
-
- mtx_lock(&vp->v_pollinfo.vpi_lock);
- SLIST_INSERT_HEAD(&vp->v_pollinfo.vpi_selinfo.si_note, kn, kn_selnext);
- mtx_unlock(&vp->v_pollinfo.vpi_lock);
-
- return (0);
-}
-
-static void
-filt_vndetach(struct knote *kn)
-{
- struct vnode *vp = (struct vnode *)kn->kn_fp->f_data;
-
- mtx_lock(&vp->v_pollinfo.vpi_lock);
- SLIST_REMOVE(&vp->v_pollinfo.vpi_selinfo.si_note,
- kn, knote, kn_selnext);
- mtx_unlock(&vp->v_pollinfo.vpi_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)
+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_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 82a1c0aeff48..c8f91f1367d0 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -222,6 +222,14 @@ vop_poll {
};
#
+#% 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_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c
index 453f2077bec7..79ee0aa7a3d9 100644
--- a/sys/miscfs/fifofs/fifo_vnops.c
+++ b/sys/miscfs/fifofs/fifo_vnops.c
@@ -71,21 +71,20 @@ static int fifo_read __P((struct vop_read_args *));
static int fifo_write __P((struct vop_write_args *));
static int fifo_ioctl __P((struct vop_ioctl_args *));
static int fifo_poll __P((struct vop_poll_args *));
+static int fifo_kqfilter __P((struct vop_kqfilter_args *));
static int fifo_bmap __P((struct vop_bmap_args *));
static int fifo_pathconf __P((struct vop_pathconf_args *));
static int fifo_advlock __P((struct vop_advlock_args *));
-static int filt_fiforattach(struct knote *kn);
static void filt_fifordetach(struct knote *kn);
static int filt_fiforead(struct knote *kn, long hint);
-static int filt_fifowattach(struct knote *kn);
static void filt_fifowdetach(struct knote *kn);
static int filt_fifowrite(struct knote *kn, long hint);
-struct filterops fifo_rwfiltops[] = {
- { 1, filt_fiforattach, filt_fifordetach, filt_fiforead },
- { 1, filt_fifowattach, filt_fifowdetach, filt_fifowrite },
-};
+static struct filterops fiforead_filtops =
+ { 1, NULL, filt_fifordetach, filt_fiforead };
+static struct filterops fifowrite_filtops =
+ { 1, NULL, filt_fifowdetach, filt_fifowrite };
vop_t **fifo_vnodeop_p;
static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
@@ -106,6 +105,7 @@ static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
{ &vop_open_desc, (vop_t *) fifo_open },
{ &vop_pathconf_desc, (vop_t *) fifo_pathconf },
{ &vop_poll_desc, (vop_t *) fifo_poll },
+ { &vop_kqfilter_desc, (vop_t *) fifo_kqfilter },
{ &vop_print_desc, (vop_t *) fifo_print },
{ &vop_read_desc, (vop_t *) fifo_read },
{ &vop_readdir_desc, (vop_t *) fifo_badop },
@@ -354,22 +354,42 @@ fifo_ioctl(ap)
return (0);
}
+/* ARGSUSED */
static int
-filt_fiforattach(struct knote *kn)
+fifo_kqfilter(ap)
+ struct vop_kqfilter_args /* {
+ struct vnode *a_vp;
+ struct knote *a_kn;
+ } */ *ap;
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ 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;
- SLIST_INSERT_HEAD(&so->so_rcv.sb_sel.si_note, kn, kn_selnext);
- so->so_rcv.sb_flags |= SB_KNOTE;
return (0);
}
static void
filt_fifordetach(struct knote *kn)
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ 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))
@@ -379,8 +399,7 @@ filt_fifordetach(struct knote *kn)
static int
filt_fiforead(struct knote *kn, long hint)
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ struct socket *so = (struct socket *)kn->kn_hook;
kn->kn_data = so->so_rcv.sb_cc;
if (so->so_state & SS_CANTRCVMORE) {
@@ -391,22 +410,10 @@ filt_fiforead(struct knote *kn, long hint)
return (kn->kn_data > 0);
}
-static int
-filt_fifowattach(struct knote *kn)
-{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_writesock;
-
- SLIST_INSERT_HEAD(&so->so_snd.sb_sel.si_note, kn, kn_selnext);
- so->so_rcv.sb_flags |= SB_KNOTE;
- return (0);
-}
-
static void
filt_fifowdetach(struct knote *kn)
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ 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))
@@ -416,8 +423,7 @@ filt_fifowdetach(struct knote *kn)
static int
filt_fifowrite(struct knote *kn, long hint)
{
- struct vnode *vn = (struct vnode *)kn->kn_fp->f_data;
- struct socket *so = (struct socket *)vn->v_fifoinfo->fi_readsock;
+ struct socket *so = (struct socket *)kn->kn_hook;
kn->kn_data = sbspace(&so->so_snd);
if (so->so_state & SS_CANTSENDMORE) {
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
index dce82120cb4b..35a0a49f7bb7 100644
--- a/sys/miscfs/specfs/spec_vnops.c
+++ b/sys/miscfs/specfs/spec_vnops.c
@@ -62,6 +62,7 @@ static int spec_getpages __P((struct vop_getpages_args *));
static int spec_ioctl __P((struct vop_ioctl_args *));
static int spec_open __P((struct vop_open_args *));
static int spec_poll __P((struct vop_poll_args *));
+static int spec_kqfilter __P((struct vop_kqfilter_args *));
static int spec_print __P((struct vop_print_args *));
static int spec_read __P((struct vop_read_args *));
static int spec_strategy __P((struct vop_strategy_args *));
@@ -87,6 +88,7 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_open_desc, (vop_t *) spec_open },
{ &vop_pathconf_desc, (vop_t *) vop_stdpathconf },
{ &vop_poll_desc, (vop_t *) spec_poll },
+ { &vop_kqfilter_desc, (vop_t *) spec_kqfilter },
{ &vop_print_desc, (vop_t *) spec_print },
{ &vop_read_desc, (vop_t *) spec_read },
{ &vop_readdir_desc, (vop_t *) vop_panic },
@@ -330,6 +332,23 @@ spec_poll(ap)
dev = ap->a_vp->v_rdev;
return (*devsw(dev)->d_poll)(dev, ap->a_events, ap->a_p);
}
+
+/* ARGSUSED */
+static int
+spec_kqfilter(ap)
+ struct vop_kqfilter_args /* {
+ struct vnode *a_vp;
+ struct knote *a_kn;
+ } */ *ap;
+{
+ dev_t dev;
+
+ dev = ap->a_vp->v_rdev;
+ if (devsw(dev)->d_flags & D_KQFILTER)
+ return (*devsw(dev)->d_kqfilter)(dev, ap->a_kn);
+ return (1);
+}
+
/*
* Synch buffers associated with a block device
*/
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index b277c9a76fdc..81ea6afc2f4d 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -105,6 +105,7 @@ struct bio;
struct buf;
struct proc;
struct uio;
+struct knote;
typedef int d_open_t __P((dev_t dev, int oflags, int devtype, struct proc *p));
typedef int d_close_t __P((dev_t dev, int fflag, int devtype, struct proc *p));
@@ -118,6 +119,7 @@ typedef int d_psize_t __P((dev_t dev));
typedef int d_read_t __P((dev_t dev, struct uio *uio, int ioflag));
typedef int d_write_t __P((dev_t dev, struct uio *uio, int ioflag));
typedef int d_poll_t __P((dev_t dev, int events, struct proc *p));
+typedef int d_kqfilter_t __P((dev_t dev, struct knote *kn));
typedef int d_mmap_t __P((dev_t dev, vm_offset_t offset, int nprot));
typedef int l_open_t __P((dev_t dev, struct tty *tp));
@@ -169,11 +171,12 @@ typedef int l_modem_t __P((struct tty *tp, int flag));
/*
* Flags for d_flags.
*/
-#define D_MEMDISK 0x10000 /* memory type disk */
-#define D_NAGGED 0x20000 /* nagged about missing make_dev() */
-#define D_CANFREE 0x40000 /* can free blocks */
-#define D_TRACKCLOSE 0x80000 /* track all closes */
-#define D_MMAP_ANON 0x100000 /* special treatment in vm_mmap.c */
+#define D_MEMDISK 0x00010000 /* memory type disk */
+#define D_NAGGED 0x00020000 /* nagged about missing make_dev() */
+#define D_CANFREE 0x00040000 /* can free blocks */
+#define D_TRACKCLOSE 0x00080000 /* track all closes */
+#define D_MMAP_ANON 0x00100000 /* special treatment in vm_mmap.c */
+#define D_KQFILTER 0x00200000 /* has kqfilter entry */
/*
* Character device switch table
@@ -194,6 +197,8 @@ struct cdevsw {
u_int d_flags;
/* This following field is deprecated. Please don't initialize */
int d_XXXbmaj;
+ /* additions below are not binary compatible with 4.2 and below */
+ d_kqfilter_t *d_kqfilter;
};
/*
@@ -241,6 +246,7 @@ d_read_t noread;
d_write_t nowrite;
d_ioctl_t noioctl;
d_mmap_t nommap;
+d_kqfilter_t nokqfilter;
#define nostrategy ((d_strategy_t *)NULL)
#define nopoll seltrue
diff --git a/sys/sys/event.h b/sys/sys/event.h
index 6182bccd0926..9f216786386d 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -127,6 +127,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 a92370a3be5d..207f22788e72 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -48,6 +48,7 @@
struct stat;
struct proc;
struct uio;
+struct knote;
/*
* Kernel descriptor table.
@@ -77,6 +78,8 @@ struct file {
caddr_t data, struct proc *p));
int (*fo_poll) __P((struct file *fp, int events,
struct ucred *cred, struct proc *p));
+ int (*fo_kqfilter) __P((struct file *fp,
+ struct knote *kn));
int (*fo_stat) __P((struct file *fp, struct stat *sb,
struct proc *p));
int (*fo_close) __P((struct file *fp, struct proc *p));
@@ -126,6 +129,7 @@ static __inline int fo_poll __P((struct file *fp, int events,
static __inline int fo_stat __P((struct file *fp, struct stat *sb,
struct proc *p));
static __inline int fo_close __P((struct file *fp, struct proc *p));
+static __inline int fo_kqfilter __P((struct file *fp, struct knote *kn));
static __inline int
fo_read(fp, uio, cred, flags, p)
@@ -212,6 +216,15 @@ fo_close(fp, p)
return ((*fp->f_ops->fo_close)(fp, p));
}
+static __inline int
+fo_kqfilter(fp, kn)
+ struct file *fp;
+ struct knote *kn;
+{
+
+ return ((*fp->f_ops->fo_kqfilter)(fp, kn));
+}
+
#endif /* _KERNEL */
#endif /* !SYS_FILE_H */
diff --git a/sys/sys/linedisc.h b/sys/sys/linedisc.h
index b277c9a76fdc..81ea6afc2f4d 100644
--- a/sys/sys/linedisc.h
+++ b/sys/sys/linedisc.h
@@ -105,6 +105,7 @@ struct bio;
struct buf;
struct proc;
struct uio;
+struct knote;
typedef int d_open_t __P((dev_t dev, int oflags, int devtype, struct proc *p));
typedef int d_close_t __P((dev_t dev, int fflag, int devtype, struct proc *p));
@@ -118,6 +119,7 @@ typedef int d_psize_t __P((dev_t dev));
typedef int d_read_t __P((dev_t dev, struct uio *uio, int ioflag));
typedef int d_write_t __P((dev_t dev, struct uio *uio, int ioflag));
typedef int d_poll_t __P((dev_t dev, int events, struct proc *p));
+typedef int d_kqfilter_t __P((dev_t dev, struct knote *kn));
typedef int d_mmap_t __P((dev_t dev, vm_offset_t offset, int nprot));
typedef int l_open_t __P((dev_t dev, struct tty *tp));
@@ -169,11 +171,12 @@ typedef int l_modem_t __P((struct tty *tp, int flag));
/*
* Flags for d_flags.
*/
-#define D_MEMDISK 0x10000 /* memory type disk */
-#define D_NAGGED 0x20000 /* nagged about missing make_dev() */
-#define D_CANFREE 0x40000 /* can free blocks */
-#define D_TRACKCLOSE 0x80000 /* track all closes */
-#define D_MMAP_ANON 0x100000 /* special treatment in vm_mmap.c */
+#define D_MEMDISK 0x00010000 /* memory type disk */
+#define D_NAGGED 0x00020000 /* nagged about missing make_dev() */
+#define D_CANFREE 0x00040000 /* can free blocks */
+#define D_TRACKCLOSE 0x00080000 /* track all closes */
+#define D_MMAP_ANON 0x00100000 /* special treatment in vm_mmap.c */
+#define D_KQFILTER 0x00200000 /* has kqfilter entry */
/*
* Character device switch table
@@ -194,6 +197,8 @@ struct cdevsw {
u_int d_flags;
/* This following field is deprecated. Please don't initialize */
int d_XXXbmaj;
+ /* additions below are not binary compatible with 4.2 and below */
+ d_kqfilter_t *d_kqfilter;
};
/*
@@ -241,6 +246,7 @@ d_read_t noread;
d_write_t nowrite;
d_ioctl_t noioctl;
d_mmap_t nommap;
+d_kqfilter_t nokqfilter;
#define nostrategy ((d_strategy_t *)NULL)
#define nopoll seltrue
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 09014182bd3e..215286e5df93 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -305,6 +305,7 @@ struct sockaddr;
struct stat;
struct ucred;
struct uio;
+struct knote;
/*
* File operations on sockets.
@@ -319,6 +320,7 @@ int soo_ioctl __P((struct file *fp, u_long cmd, caddr_t data,
int soo_poll __P((struct file *fp, int events, struct ucred *cred,
struct proc *p));
int soo_stat __P((struct file *fp, struct stat *ub, struct proc *p));
+int sokqfilter __P((struct file *fp, struct knote *kn));
/*
* From uipc_socket and friends
diff --git a/sys/sys/tty.h b/sys/sys/tty.h
index afd7854b71f1..0a876cbf13dc 100644
--- a/sys/sys/tty.h
+++ b/sys/sys/tty.h
@@ -263,6 +263,7 @@ struct tty *ttymalloc __P((struct tty *tp));
int ttymodem __P((struct tty *tp, int flag));
int ttyopen __P((dev_t device, struct tty *tp));
int ttypoll __P((dev_t dev, int events, struct proc *p));
+int ttykqfilter __P((dev_t dev, struct knote *kn));
int ttyread __P((dev_t dev, struct uio *uio, int flag));
void ttyregister __P((struct tty *tp));
int ttysleep __P((struct tty *tp, void *chan, int pri, char *wmesg,
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 134e356bfb0e..2244df33b19e 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -61,6 +61,8 @@
#include <machine/mutex.h>
+#include <sys/file.h> /* XXX */
+
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -103,6 +105,10 @@ static int ufsfifo_write __P((struct vop_write_args *));
static int ufsspec_close __P((struct vop_close_args *));
static int ufsspec_read __P((struct vop_read_args *));
static int ufsspec_write __P((struct vop_write_args *));
+static int filt_ufsread __P((struct knote *kn, long hint));
+static int filt_ufsvnode __P((struct knote *kn, long hint));
+static void filt_ufsdetach __P((struct knote *kn));
+static int ufs_kqfilter __P((struct vop_kqfilter_args *ap));
union _qcvt {
int64_t qcvt;
@@ -2176,6 +2182,71 @@ ufs_missingop(ap)
return (EOPNOTSUPP);
}
+static struct filterops ufsread_filtops =
+ { 1, NULL, filt_ufsdetach, filt_ufsread };
+static struct filterops ufsvnode_filtops =
+ { 1, NULL, filt_ufsdetach, filt_ufsvnode };
+
+static int
+ufs_kqfilter(ap)
+ struct vop_kqfilter_args /* {
+ struct vnode *a_vp;
+ struct knote *a_kn;
+ } */ *ap;
+{
+ 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;
+
+ mtx_lock(&vp->v_pollinfo.vpi_lock);
+ SLIST_INSERT_HEAD(&vp->v_pollinfo.vpi_selinfo.si_note, kn, kn_selnext);
+ mtx_unlock(&vp->v_pollinfo.vpi_lock);
+
+ return (0);
+}
+
+static void
+filt_ufsdetach(struct knote *kn)
+{
+ struct vnode *vp = (struct vnode *)kn->kn_hook;
+
+ mtx_lock(&vp->v_pollinfo.vpi_lock);
+ SLIST_REMOVE(&vp->v_pollinfo.vpi_selinfo.si_note, kn, knote, kn_link);
+ mtx_unlock(&vp->v_pollinfo.vpi_lock);
+}
+
+/*ARGSUSED*/
+static int
+filt_ufsread(struct knote *kn, long hint)
+{
+ struct vnode *vp = (struct vnode *)kn->kn_hook;
+ struct inode *ip = VTOI(vp);
+
+ kn->kn_data = ip->i_size - kn->kn_fp->f_offset;
+ return (kn->kn_data != 0);
+}
+
+static int
+filt_ufsvnode(struct knote *kn, long hint)
+{
+
+ if (kn->kn_sfflags & hint)
+ kn->kn_fflags |= hint;
+ return (kn->kn_fflags != 0);
+}
+
/* Global vfs data structures for ufs. */
static vop_t **ufs_vnodeop_p;
static struct vnodeopv_entry_desc ufs_vnodeop_entries[] = {
@@ -2201,6 +2272,7 @@ static struct vnodeopv_entry_desc ufs_vnodeop_entries[] = {
{ &vop_open_desc, (vop_t *) ufs_open },
{ &vop_pathconf_desc, (vop_t *) ufs_pathconf },
{ &vop_poll_desc, (vop_t *) vop_stdpoll },
+ { &vop_kqfilter_desc, (vop_t *) ufs_kqfilter },
{ &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
{ &vop_print_desc, (vop_t *) ufs_print },
{ &vop_readdir_desc, (vop_t *) ufs_readdir },