Extend kqueue down to the device layer.
Backwards compatible approach suggested by: peter
This commit is contained in:
parent
2c9ba841c6
commit
608a3ce62a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=72521
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 },
|
||||
|
Loading…
Reference in New Issue
Block a user