diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2014-01-22 18:28:17 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2014-01-22 18:28:17 +0000 |
commit | b66e1c8d1f82095cede35b687ba1b64361307f31 (patch) | |
tree | 03c01cf2ae529c65af4d204d2ef25746c491b4c8 | |
parent | fe29c704e3ed478163cd2d5784200fd95905eac6 (diff) |
bring over kqfilter code from ufs which works better than the
generic flavor. problems noted and tested by ajacoutot
-rw-r--r-- | sys/tmpfs/tmpfs_vnops.c | 107 |
1 files changed, 105 insertions, 2 deletions
diff --git a/sys/tmpfs/tmpfs_vnops.c b/sys/tmpfs/tmpfs_vnops.c index adc83757557..9c822305111 100644 --- a/sys/tmpfs/tmpfs_vnops.c +++ b/sys/tmpfs/tmpfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tmpfs_vnops.c,v 1.12 2014/01/07 04:44:56 guenther Exp $ */ +/* $OpenBSD: tmpfs_vnops.c,v 1.13 2014/01/22 18:28:16 tedu Exp $ */ /* $NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland Exp $ */ /* @@ -53,6 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland E #include <sys/vnode.h> #include <sys/lockf.h> #include <sys/poll.h> +#include <sys/file.h> #include <uvm/uvm.h> @@ -60,6 +61,8 @@ __KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland E #include <tmpfs/tmpfs_vnops.h> #include <tmpfs/tmpfs.h> +int tmpfs_kqfilter(void *v); + /* * vnode operations vector used for files stored in a tmpfs file system. */ @@ -76,7 +79,7 @@ struct vops tmpfs_vops = { .vop_write = tmpfs_write, .vop_ioctl = tmpfs_ioctl, .vop_poll = tmpfs_poll, - .vop_kqfilter = vop_generic_kqfilter, + .vop_kqfilter = tmpfs_kqfilter, .vop_revoke = vop_generic_revoke, .vop_fsync = tmpfs_fsync, .vop_remove = tmpfs_remove, @@ -2568,3 +2571,103 @@ tmpfs_rename_abort(void *v) vrele(fdvp); vrele(fvp); } + +void filt_tmpfsdetach(struct knote *kn); +int filt_tmpfsread(struct knote *kn, long hint); +int filt_tmpfswrite(struct knote *kn, long hint); +int filt_tmpfsvnode(struct knote *kn, long hint); + +struct filterops tmpfsread_filtops = + { 1, NULL, filt_tmpfsdetach, filt_tmpfsread }; +struct filterops tmpfswrite_filtops = + { 1, NULL, filt_tmpfsdetach, filt_tmpfswrite }; +struct filterops tmpfsvnode_filtops = + { 1, NULL, filt_tmpfsdetach, filt_tmpfsvnode }; + +int +tmpfs_kqfilter(void *v) +{ + struct vop_kqfilter_args *ap = v; + struct vnode *vp = ap->a_vp; + struct knote *kn = ap->a_kn; + + switch (kn->kn_filter) { + case EVFILT_READ: + kn->kn_fop = &tmpfsread_filtops; + break; + case EVFILT_WRITE: + kn->kn_fop = &tmpfswrite_filtops; + break; + case EVFILT_VNODE: + kn->kn_fop = &tmpfsvnode_filtops; + break; + default: + return (EINVAL); + } + + kn->kn_hook = (caddr_t)vp; + + SLIST_INSERT_HEAD(&vp->v_selectinfo.si_note, kn, kn_selnext); + + return (0); +} + +void +filt_tmpfsdetach(struct knote *kn) +{ + struct vnode *vp = (struct vnode *)kn->kn_hook; + + SLIST_REMOVE(&vp->v_selectinfo.si_note, kn, knote, kn_selnext); +} + +int +filt_tmpfsread(struct knote *kn, long hint) +{ + struct vnode *vp = (struct vnode *)kn->kn_hook; + tmpfs_node_t *node = VP_TO_TMPFS_NODE(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 = node->tn_size - kn->kn_fp->f_offset; + if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { + kn->kn_fflags |= NOTE_EOF; + return (1); + } + + return (kn->kn_data != 0); +} + +int +filt_tmpfswrite(struct knote *kn, long hint) +{ + /* + * 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 = 0; + return (1); +} + +int +filt_tmpfsvnode(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); +} |