Extend kqueue down to the device layer.

Backwards compatible approach suggested by: peter
This commit is contained in:
Jonathan Lemon 2001-02-15 16:34:11 +00:00
parent 2c9ba841c6
commit 608a3ce62a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=72521
39 changed files with 511 additions and 296 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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
*/

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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
};
@ -1545,6 +1547,15 @@ badfo_poll(fp, events, cred, p)
return (0);
}
static int
badfo_kqfilter(fp, kn)
struct file *fp;
struct knote *kn;
{
return (0);
}
static int
badfo_stat(fp, sb, p)
struct file *fp;

View File

@ -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)
filt_fileattach(struct knote *kn)
{
return (ENXIO);
return (fo_kqfilter(kn->kn_fp, kn));
}
/*
* file-type specific attach routine for read/write filters
*/
/*ARGSUSED*/
static int
filt_rwtypattach(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));
}
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);
}

View File

@ -133,6 +133,15 @@ noioctl(dev, cmd, data, flags, p)
return (ENODEV);
}
int
nokqfilter(dev, kn)
dev_t dev;
struct knote *kn;
{
return (ENODEV);
}
int
nommap(dev, offset, nprot)
dev_t dev;

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
/*

View File

@ -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()
{

View File

@ -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 */

View File

@ -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)
{

View File

@ -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)
vn_kqfilter(struct file *fp, struct knote *kn)
{
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)
{
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));
}
/*

View File

@ -221,6 +221,14 @@ vop_poll {
IN struct proc *p;
};
#
#% kqfilter vp U U U
#
vop_kqfilter {
IN struct vnode *vp;
IN struct knote *kn;
};
#
#% revoke vp U U U
#

View File

@ -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) {

View File

@ -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
*/

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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 },