summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2014-01-22 18:28:17 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2014-01-22 18:28:17 +0000
commitb66e1c8d1f82095cede35b687ba1b64361307f31 (patch)
tree03c01cf2ae529c65af4d204d2ef25746c491b4c8
parentfe29c704e3ed478163cd2d5784200fd95905eac6 (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.c107
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);
+}