diff options
| author | Jonathan Lemon <jlemon@FreeBSD.org> | 2001-02-26 04:23:21 +0000 |
|---|---|---|
| committer | Jonathan Lemon <jlemon@FreeBSD.org> | 2001-02-26 04:23:21 +0000 |
| commit | d2180fd16490150b692c1f687ae68f4eea73e83a (patch) | |
| tree | f210262f6fae822780014bab8730fc47c1309845 | |
| parent | d1c1cd368b37cc1fb1392285e4ead218530c30a6 (diff) | |
Notes
32 files changed, 471 insertions, 256 deletions
diff --git a/sys/dev/si/si.c b/sys/dev/si/si.c index 603dcf698d08..1acfb290a9d7 100644 --- a/sys/dev/si/si.c +++ b/sys/dev/si/si.c @@ -131,8 +131,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/streams/streams.c b/sys/dev/streams/streams.c index f4c89e06d0ee..4aa4c755b9bb 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 0ba4ab387dbf..cb2849f2ab38 100644 --- a/sys/dev/usb/umodem.c +++ b/sys/dev/usb/umodem.c @@ -167,8 +167,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/gnu/i386/isa/dgb.c b/sys/gnu/i386/isa/dgb.c index f054e7baae3f..28897fcf8f52 100644 --- a/sys/gnu/i386/isa/dgb.c +++ b/sys/gnu/i386/isa/dgb.c @@ -218,8 +218,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/gnu/i386/isa/dgm.c b/sys/gnu/i386/isa/dgm.c index 18122f00db65..594fba6dfb9c 100644 --- a/sys/gnu/i386/isa/dgm.c +++ b/sys/gnu/i386/isa/dgm.c @@ -221,8 +221,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/i386/isa/cx.c b/sys/i386/isa/cx.c index 3bca982abb51..876e63361fbd 100644 --- a/sys/i386/isa/cx.c +++ b/sys/i386/isa/cx.c @@ -101,8 +101,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 dfeb69ac11e5..925666abf842 100644 --- a/sys/i386/isa/cy.c +++ b/sys/i386/isa/cy.c @@ -383,8 +383,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 816773b444b3..b5def9c06d3b 100644 --- a/sys/i386/isa/istallion.c +++ b/sys/i386/isa/istallion.c @@ -647,8 +647,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 5c50173ac4ea..3a470cce6023 100644 --- a/sys/i386/isa/pcvt/pcvt_drv.c +++ b/sys/i386/isa/pcvt/pcvt_drv.c @@ -114,8 +114,9 @@ static struct cdevsw pc_cdevsw = { /* maj */ CDEV_MAJOR, /* dump */ nodump, /* psize */ nopsize, - /* flags */ D_TTY, - /* bmaj */ -1 + /* flags */ D_TTY | D_KQFILTER, + /* bmaj */ -1, + /* kqfilter */ ttykqfilter, }; #if PCVT_NETBSD > 100 /* NetBSD-current Feb 20 1995 */ diff --git a/sys/i386/isa/rc.c b/sys/i386/isa/rc.c index ce6dab2cd789..6b478c7e716d 100644 --- a/sys/i386/isa/rc.c +++ b/sys/i386/isa/rc.c @@ -102,8 +102,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 67f65bb7a461..40a5e3b49e8f 100644 --- a/sys/i386/isa/rp.c +++ b/sys/i386/isa/rp.c @@ -811,8 +811,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 4194878de99d..717c9c0f2aa6 100644 --- a/sys/i386/isa/stallion.c +++ b/sys/i386/isa/stallion.c @@ -540,8 +540,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 0894e84e3913..cd32ef7f0e30 100644 --- a/sys/isa/sio.c +++ b/sys/isa/sio.c @@ -398,8 +398,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 eb43b075cf96..9a88e6dce285 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)); @@ -1480,6 +1481,7 @@ struct fileops badfileops = { badfo_readwrite, badfo_ioctl, badfo_poll, + badfo_kqfilter, badfo_stat, badfo_close }; @@ -1519,6 +1521,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 c51af29e91b5..8bb34c609bb2 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org> + * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -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); } @@ -466,7 +435,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p) kn->kn_fop = fops; /* - * apply reference count to knode structure, so + * apply reference count to knote structure, and * do not release it at the end of this routine. */ fp = NULL; 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 2a7084942a28..a4fb966f58f9 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 @@ -1185,11 +1188,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 c66036a69aaa..50d80b06702a 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, @@ -1085,6 +1089,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(). */ @@ -2102,6 +2189,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); } /* @@ -2126,6 +2214,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 14269c131616..744ff44c7af7 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -87,8 +87,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 @@ -105,8 +106,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 dda845c8e880..0f04d17a94c5 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 /* INET */ -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 */ @@ -1538,16 +1535,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); } @@ -1573,25 +1586,16 @@ filt_soread(struct knote *kn, long hint) kn->kn_data = so->so_rcv.sb_cc; if (so->so_state & SS_CANTRCVMORE) { kn->kn_flags |= EV_EOF; + kn->kn_fflags = so->so_error; return (1); } if (so->so_error) /* temporary udp error */ return (1); + if (kn->kn_sfflags & NOTE_LOWAT) + return (kn->kn_data >= kn->kn_sdata); return (kn->kn_data >= so->so_rcv.sb_lowat); } -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) { @@ -1613,6 +1617,7 @@ filt_sowrite(struct knote *kn, long hint) kn->kn_data = sbspace(&so->so_snd); if (so->so_state & SS_CANTSENDMORE) { kn->kn_flags |= EV_EOF; + kn->kn_fflags = so->so_error; return (1); } if (so->so_error) /* temporary udp error */ @@ -1620,6 +1625,8 @@ filt_sowrite(struct knote *kn, long hint) if (((so->so_state & SS_ISCONNECTED) == 0) && (so->so_proto->pr_flags & PR_CONNREQUIRED)) return (0); + if (kn->kn_sfflags & NOTE_LOWAT) + return (kn->kn_data >= kn->kn_sdata); return (kn->kn_data >= so->so_snd.sb_lowat); } diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 16a0c9c01862..1af02518d601 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -53,9 +53,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)); @@ -63,30 +60,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 }; /* @@ -664,64 +645,8 @@ vn_closefile(fp, p) } 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); - - simple_lock(&vp->v_pollinfo.vpi_lock); - SLIST_INSERT_HEAD(&vp->v_pollinfo.vpi_selinfo.si_note, kn, kn_selnext); - simple_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; - - simple_lock(&vp->v_pollinfo.vpi_lock); - SLIST_REMOVE(&vp->v_pollinfo.vpi_selinfo.si_note, - kn, knote, kn_selnext); - simple_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 c40d3497846d..26ef2ea11fb5 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 5bd13a771d48..cd7dcfbc34ba 100644 --- a/sys/miscfs/fifofs/fifo_vnops.c +++ b/sys/miscfs/fifofs/fifo_vnops.c @@ -71,23 +71,22 @@ 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_inactive __P((struct vop_inactive_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[] = { { &vop_default_desc, (vop_t *) vop_defaultop }, @@ -107,6 +106,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 }, @@ -355,22 +355,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)) @@ -380,8 +400,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) { @@ -392,22 +411,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)) @@ -417,8 +424,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 7a3741ad90d2..f9ee56857dd0 100644 --- a/sys/miscfs/specfs/spec_vnops.c +++ b/sys/miscfs/specfs/spec_vnops.c @@ -62,6 +62,7 @@ static int spec_inactive __P((struct vop_inactive_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 }, @@ -320,6 +322,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 263613c4a23b..7b71ed5dc8a1 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -100,6 +100,7 @@ struct specinfo { 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)); @@ -113,6 +114,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)); @@ -151,10 +153,11 @@ typedef void devfs_remove_t __P((dev_t dev)); /* * 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_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_KQFILTER 0x00200000 /* has kqfilter entry */ /* * Character device switch table @@ -174,6 +177,8 @@ struct cdevsw { d_psize_t *d_psize; u_int d_flags; int d_bmaj; + /* additions below are not binary compatible with 4.2 and below */ + d_kqfilter_t *d_kqfilter; }; /* @@ -221,6 +226,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..de4eefe9869a 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org> + * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,6 +38,15 @@ #define EVFILT_SYSCOUNT 6 +#define EV_SET(kevp, a, b, c, d, e, f) do { \ + (kevp)->ident = (a); \ + (kevp)->filter = (b); \ + (kevp)->flags = (c); \ + (kevp)->fflags = (d); \ + (kevp)->data = (e); \ + (kevp)->udata = (f); \ +} while(0) + struct kevent { uintptr_t ident; /* identifier for this event */ short filter; /* filter for event */ @@ -65,6 +74,11 @@ struct kevent { #define EV_ERROR 0x4000 /* error, data contains errno */ /* + * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace + */ +#define NOTE_LOWAT 0x0001 /* low water mark */ + +/* * data/hint flags for EVFILT_VNODE, shared with userspace */ #define NOTE_DELETE 0x0001 /* vnode was removed */ @@ -73,6 +87,7 @@ struct kevent { #define NOTE_ATTRIB 0x0008 /* attributes changed */ #define NOTE_LINK 0x0010 /* link count changed */ #define NOTE_RENAME 0x0020 /* vnode was renamed */ +#define NOTE_REVOKE 0x0040 /* vnode access was revoked */ /* * data/hint flags for EVFILT_PROC, shared with userspace @@ -127,6 +142,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 b3a092010594..41a7ed8a4aa3 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)); @@ -128,6 +131,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) @@ -214,6 +218,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/socketvar.h b/sys/sys/socketvar.h index 95960c9c7e78..1043493b4dc5 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -306,6 +306,7 @@ struct sockaddr; struct stat; struct ucred; struct uio; +struct knote; /* * File operations on sockets. @@ -320,6 +321,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 46b11ea4edc0..6121ed6a245e 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 8cb433558a46..5084f061d77e 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -59,6 +59,8 @@ #include <sys/event.h> #include <sys/conf.h> +#include <sys/file.h> /* XXX */ + #include <vm/vm.h> #include <vm/vm_extern.h> @@ -101,6 +103,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; @@ -2189,6 +2195,85 @@ 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; + + simple_lock(&vp->v_pollinfo.vpi_lock); + SLIST_INSERT_HEAD(&vp->v_pollinfo.vpi_selinfo.si_note, kn, kn_selnext); + simple_unlock(&vp->v_pollinfo.vpi_lock); + + return (0); +} + +static void +filt_ufsdetach(struct knote *kn) +{ + struct vnode *vp = (struct vnode *)kn->kn_hook; + + simple_lock(&vp->v_pollinfo.vpi_lock); + SLIST_REMOVE(&vp->v_pollinfo.vpi_selinfo.si_note, + kn, knote, kn_selnext); + simple_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); + + /* + * filesystem is gone, so set the EOF flag and schedule + * the knote for deletion. + */ + if (hint == NOTE_REVOKE) { + kn->kn_flags |= (EV_EOF | EV_ONESHOT); + return (1); + } + + kn->kn_data = ip->i_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; + if (hint == NOTE_REVOKE) { + kn->kn_flags |= EV_EOF; + return (1); + } + 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[] = { @@ -2215,6 +2300,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_print_desc, (vop_t *) ufs_print }, { &vop_readdir_desc, (vop_t *) ufs_readdir }, { &vop_readlink_desc, (vop_t *) ufs_readlink }, |
