diff options
author | Niels Provos <provos@cvs.openbsd.org> | 2000-11-21 21:49:58 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 2000-11-21 21:49:58 +0000 |
commit | 94de05185b93d013f30d8874f4fea920b09ed369 (patch) | |
tree | b6263191caa04e1a1a335966375a2a0e1efe3ba3 | |
parent | a12c4c01eea21cd09905b7d403f30c7060520a3b (diff) |
support for kernel events on vnodes, from jlemon@freebsd.org, okay art@
-rw-r--r-- | sys/kern/kern_event.c | 10 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 85 | ||||
-rw-r--r-- | sys/sys/vnode.h | 7 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_readwrite.c | 13 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 37 |
5 files changed, 137 insertions, 15 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); +} diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 47ffb2e8af3..9d5685c67e4 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vnode.h,v 1.25 2000/06/17 17:16:05 provos Exp $ */ +/* $OpenBSD: vnode.h,v 1.26 2000/11/21 21:49:56 provos Exp $ */ /* $NetBSD: vnode.h,v 1.38 1996/02/29 20:59:05 cgd Exp $ */ /* @@ -38,6 +38,7 @@ #include <sys/queue.h> #include <sys/lock.h> +#include <sys/select.h> #ifdef UVM /* XXX: clean up includes later */ #include <vm/pglist.h> /* XXX */ #include <vm/vm_param.h> /* XXX */ @@ -126,6 +127,10 @@ struct vnode { #endif enum vtagtype v_tag; /* type of underlying data */ void *v_data; /* private data for fs */ + struct { + struct simplelock vsi_lock; /* lock to protect below */ + struct selinfo vsi_selinfo; /* identity of poller(s) */ + } v_selectinfo; }; #define v_mountedhere v_un.vu_mountedhere #define v_socket v_un.vu_socket diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c index 7a9ce5a44eb..4eb92eb225c 100644 --- a/sys/ufs/ufs/ufs_readwrite.c +++ b/sys/ufs/ufs/ufs_readwrite.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_readwrite.c,v 1.15 1999/02/26 03:35:18 art Exp $ */ +/* $OpenBSD: ufs_readwrite.c,v 1.16 2000/11/21 21:49:57 provos Exp $ */ /* $NetBSD: ufs_readwrite.c,v 1.9 1996/05/11 18:27:57 mycroft Exp $ */ /*- @@ -57,6 +57,11 @@ #define MAXFILESIZE fs->fs_maxfilesize #endif +#include <sys/event.h> + +#define VN_KNOTE(vp, b) \ + KNOTE((struct klist *)&vp->v_selectinfo.vsi_selinfo.si_note, (b)) + /* * Vnode op for reading. */ @@ -186,9 +191,10 @@ WRITE(v) struct proc *p; daddr_t lbn; off_t osize; - int blkoffset, error, flags, ioflag, resid, size, xfersize; + int blkoffset, error, extended, flags, ioflag, resid, size, xfersize; struct timespec ts; + extended = 0; ioflag = ap->a_ioflag; uio = ap->a_uio; vp = ap->a_vp; @@ -257,6 +263,7 @@ WRITE(v) #else vnode_pager_setsize(vp, (u_long)ip->i_ffs_size); #endif + extended = 1; } #if defined(UVM) (void)uvm_vnp_uncache(vp); @@ -298,6 +305,8 @@ WRITE(v) */ if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0) ip->i_ffs_mode &= ~(ISUID | ISGID); + if (resid > uio->uio_resid) + VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0)); if (error) { if (ioflag & IO_UNIT) { (void)VOP_TRUNCATE(vp, osize, diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 5575728b316..2a648f44883 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_vnops.c,v 1.27 1999/03/09 21:16:28 art Exp $ */ +/* $OpenBSD: ufs_vnops.c,v 1.28 2000/11/21 21:49:57 provos Exp $ */ /* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */ /* @@ -56,6 +56,7 @@ #include <sys/malloc.h> #include <sys/dirent.h> #include <sys/lockf.h> +#include <sys/event.h> #include <vm/vm.h> @@ -93,6 +94,8 @@ union _qcvt { tmp.val[_QUAD_LOWWORD] = (l); \ (q) = tmp.qcvt; \ } +#define VN_KNOTE(vp, b) \ + KNOTE(&vp->v_selectinfo.vsi_selinfo.si_note, (b)) /* @@ -120,9 +123,15 @@ ufs_create(v) struct componentname *a_cnp; struct vattr *a_vap; } */ *ap = v; - return + int error; + + error = ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), ap->a_dvp, ap->a_vpp, ap->a_cnp); + if (error) + return (error); + VN_KNOTE(ap->a_dvp, NOTE_WRITE); + return (0); } /* @@ -148,6 +157,7 @@ ufs_mknod(v) ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), ap->a_dvp, vpp, ap->a_cnp)) != 0) return (error); + VN_KNOTE(ap->a_dvp, NOTE_WRITE); ip = VTOI(*vpp); ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; if (vap->va_rdev != VNOVAL) { @@ -433,6 +443,7 @@ ufs_setattr(v) return (EROFS); error = ufs_chmod(vp, (int)vap->va_mode, cred, p); } + VN_KNOTE(vp, NOTE_ATTRIB); return (error); } @@ -677,11 +688,14 @@ ufs_remove(v) ip = VTOI(vp); if (vp->v_type == VDIR || (ip->i_ffs_flags & (IMMUTABLE | APPEND)) || - (VTOI(dvp)->i_ffs_flags & APPEND)) + (VTOI(dvp)->i_ffs_flags & APPEND)) { error = EPERM; - else - error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0); - + goto out; + } + error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0); + VN_KNOTE(vp, NOTE_DELETE); + VN_KNOTE(dvp, NOTE_WRITE); + out: if (dvp == vp) vrele(vp); else @@ -756,6 +770,8 @@ ufs_link(v) ip->i_flag |= IN_CHANGE; } FREE(cnp->cn_pnbuf, M_NAMEI); + VN_KNOTE(vp, NOTE_LINK); + VN_KNOTE(dvp, NOTE_WRITE); out1: if (dvp != vp) VOP_UNLOCK(vp, 0, p); @@ -973,6 +989,7 @@ abortit: oldparent = dp->i_number; doingdirectory = 1; } + VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */ /* Why? */ vrele(fdvp); @@ -1079,6 +1096,7 @@ abortit: } goto bad; } + VN_KNOTE(tdvp, NOTE_WRITE); vput(tdvp); } else { if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) @@ -1153,7 +1171,9 @@ abortit: tcnp->cn_cred, tcnp->cn_proc)) != 0) goto bad; } + VN_KNOTE(tdvp, NOTE_WRITE); vput(tdvp); + VN_KNOTE(tvp, NOTE_DELETE); vput(tvp); xp = NULL; } @@ -1205,6 +1225,7 @@ abortit: error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0); xp->i_flag &= ~IN_RENAME; } + VN_KNOTE(fvp, NOTE_RENAME); if (dp) vput(fdvp); if (xp) @@ -1368,6 +1389,7 @@ ufs_mkdir(v) bad: if (error == 0) { + VN_KNOTE(dvp, NOTE_WRITE); *ap->a_vpp = tvp; } else { dp->i_effnlink--; @@ -1449,6 +1471,7 @@ ufs_rmdir(v) */ if ((error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1)) != 0) goto out; + VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); cache_purge(dvp); /* * Truncate inode. The only stuff left in the directory is "." and @@ -1471,6 +1494,7 @@ ufs_rmdir(v) } cache_purge(vp); out: + VN_KNOTE(vp, NOTE_DELETE); vput(dvp); vput(vp); return (error); @@ -1498,6 +1522,7 @@ ufs_symlink(v) vpp, ap->a_cnp); if (error) return (error); + VN_KNOTE(ap->a_dvp, NOTE_WRITE); vp = *vpp; len = strlen(ap->a_target); if (len < vp->v_mount->mnt_maxsymlinklen) { |