summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>2000-11-21 21:49:58 +0000
committerNiels Provos <provos@cvs.openbsd.org>2000-11-21 21:49:58 +0000
commit94de05185b93d013f30d8874f4fea920b09ed369 (patch)
treeb6263191caa04e1a1a335966375a2a0e1efe3ba3 /sys/kern
parenta12c4c01eea21cd09905b7d403f30c7060520a3b (diff)
support for kernel events on vnodes, from jlemon@freebsd.org, okay art@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_event.c10
-rw-r--r--sys/kern/vfs_vnops.c85
2 files changed, 89 insertions, 6 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 4c5fed5e9ac..d407ba8ad27 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_event.c,v 1.5 2000/11/18 22:16:49 provos Exp $ */
+/* $OpenBSD: kern_event.c,v 1.6 2000/11/21 21:49:57 provos Exp $ */
/*-
* Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org>
@@ -100,8 +100,8 @@ extern struct filterops so_rwfiltops[];
extern struct filterops pipe_rwfiltops[];
#ifdef notyet
extern struct filterops fifo_rwfiltops[];
-extern struct filterops vn_rwfiltops[];
#endif
+extern struct filterops vn_rwfiltops[];
struct filterops kq_rwfiltops[] = {
{ 1, filt_kqattach, filt_kqdetach, filt_kqueue },
@@ -111,8 +111,8 @@ struct filterops kq_rwfiltops[] = {
extern struct filterops sig_filtops;
#ifdef notyet
extern struct filterops aio_filtops;
-extern struct filterops vn_filtops;
#endif
+extern struct filterops vn_filtops;
struct filterops rwtype_filtops =
{ 1, filt_rwtypattach, NULL, NULL };
@@ -125,7 +125,7 @@ struct filterops proc_filtops =
*/
struct filterops *rwtypfilt_sw[] = {
NULL, /* 0 */
- NULL, /* vn_rwfiltops, */ /* DTYPE_VNODE */
+ vn_rwfiltops, /* DTYPE_VNODE */
so_rwfiltops, /* DTYPE_SOCKET */
pipe_rwfiltops, /* DTYPE_PIPE */
/* fifo_rwfiltops, */ /* DTYPE_FIFO */
@@ -139,7 +139,7 @@ struct filterops *sysfilt_ops[] = {
&rwtype_filtops, /* EVFILT_READ */
&rwtype_filtops, /* EVFILT_WRITE */
NULL, /*&aio_filtops,*/ /* EVFILT_AIO */
- NULL, /*&vn_filtops,*/ /* EVFILT_VNODE */
+ &vn_filtops, /* EVFILT_VNODE */
&proc_filtops, /* EVFILT_PROC */
&sig_filtops, /* EVFILT_SIGNAL */
};
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index b9435c46086..6bfcf9614ab 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_vnops.c,v 1.26 2000/04/25 02:10:04 deraadt Exp $ */
+/* $OpenBSD: vfs_vnops.c,v 1.27 2000/11/21 21:49:57 provos Exp $ */
/* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */
/*
@@ -61,6 +61,9 @@
#include <uvm/uvm_extern.h>
#endif
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+
int vn_read __P((struct file *fp, off_t *off, struct uio *uio,
struct ucred *cred));
int vn_write __P((struct file *fp, off_t *off, struct uio *uio,
@@ -73,6 +76,25 @@ int vn_ioctl __P((struct file *fp, u_long com, caddr_t data,
struct fileops vnops =
{ vn_read, vn_write, vn_ioctl, vn_select, 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 },
+};
+
/*
* Common code for vnode open operations.
* Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
@@ -508,3 +530,64 @@ vn_closefile(fp, p)
return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
fp->f_cred, p));
}
+
+static int
+filt_vnattach(struct knote *kn)
+{
+ struct vnode *vp;
+
+ if (kn->kn_fp->f_type != DTYPE_VNODE)
+ 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 || (vp)->v_type == VFIFO)
+ return (EOPNOTSUPP);
+
+ simple_lock(&vp->v_selectinfo.vsi_lock);
+ SLIST_INSERT_HEAD(&vp->v_selectinfo.vsi_selinfo.si_note, kn, kn_selnext);
+ simple_unlock(&vp->v_selectinfo.vsi_lock);
+
+ return (0);
+}
+
+static void
+filt_vndetach(struct knote *kn)
+{
+ struct vnode *vp = (struct vnode *)kn->kn_fp->f_data;
+
+ simple_lock(&vp->v_selectinfo.vsi_lock);
+ SLIST_REMOVE(&vp->v_selectinfo.vsi_selinfo.si_note,
+ kn, knote, kn_selnext);
+ simple_unlock(&vp->v_selectinfo.vsi_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)
+{
+ struct vnode *vp = (struct vnode *)kn->kn_fp->f_data;
+ struct inode *ip = VTOI(vp);
+
+ kn->kn_data = ip->i_ffs_size - kn->kn_fp->f_offset;
+ return (kn->kn_data != 0);
+}