Index: src/sys/ufs/ufs/ufs_vnops.c =================================================================== --- src/sys/ufs/ufs/ufs_vnops.c (revision 161) +++ src/sys/ufs/ufs/ufs_vnops.c (working copy) @@ -57,7 +57,7 @@ #include #include #include -#include +//#include #include #include #include @@ -109,11 +109,6 @@ static vop_whiteout_t ufs_whiteout; static vop_close_t ufsfifo_close; static vop_kqfilter_t ufsfifo_kqfilter; -static int filt_ufsread(struct knote *kn, long hint); -static int filt_ufswrite(struct knote *kn, long hint); -static int filt_ufsvnode(struct knote *kn, long hint); -static void filt_ufsdetach(struct knote *kn); -static vop_kqfilter_t ufs_kqfilter; /* * A virgin directory (no blushing please). @@ -179,7 +174,6 @@ ap->a_dvp, ap->a_vpp, ap->a_cnp); if (error) return (error); - VN_KNOTE_UNLOCKED(ap->a_dvp, NOTE_WRITE); return (0); } @@ -206,7 +200,6 @@ ap->a_dvp, vpp, ap->a_cnp); if (error) return (error); - VN_KNOTE_UNLOCKED(ap->a_dvp, NOTE_WRITE); ip = VTOI(*vpp); ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; if (vap->va_rdev != VNOVAL) { @@ -579,7 +572,6 @@ return (EPERM); error = ufs_chmod(vp, (int)vap->va_mode, cred, td); } - VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); return (error); } @@ -763,8 +755,6 @@ error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0); if (ip->i_nlink <= 0) vp->v_vflag |= VV_NOSYNC; - VN_KNOTE_UNLOCKED(vp, NOTE_DELETE); - VN_KNOTE_UNLOCKED(dvp, NOTE_WRITE); out: return (error); } @@ -825,8 +815,6 @@ softdep_change_linkcnt(ip); } out: - VN_KNOTE_UNLOCKED(vp, NOTE_LINK); - VN_KNOTE_UNLOCKED(tdvp, NOTE_WRITE); return (error); } @@ -1001,7 +989,6 @@ oldparent = dp->i_number; doingdirectory = 1; } - VN_KNOTE_UNLOCKED(fdvp, NOTE_WRITE); /* XXX right place? */ vrele(fdvp); /* @@ -1110,7 +1097,6 @@ } goto bad; } - VN_KNOTE_UNLOCKED(tdvp, NOTE_WRITE); vput(tdvp); } else { if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev) @@ -1194,9 +1180,7 @@ tcnp->cn_cred, tcnp->cn_thread)) != 0) goto bad; } - VN_KNOTE_UNLOCKED(tdvp, NOTE_WRITE); vput(tdvp); - VN_KNOTE_UNLOCKED(tvp, NOTE_DELETE); vput(tvp); xp = NULL; } @@ -1266,7 +1250,6 @@ error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0); xp->i_flag &= ~IN_RENAME; } - VN_KNOTE_UNLOCKED(fvp, NOTE_RENAME); if (dp) vput(fdvp); if (xp) @@ -1584,7 +1567,6 @@ bad: if (error == 0) { - VN_KNOTE_UNLOCKED(dvp, NOTE_WRITE | NOTE_LINK); *ap->a_vpp = tvp; } else { dp->i_effnlink--; @@ -1677,7 +1659,6 @@ } goto out; } - VN_KNOTE_UNLOCKED(dvp, NOTE_WRITE | NOTE_LINK); cache_purge(dvp); /* * Truncate inode. The only stuff left in the directory is "." and @@ -1706,7 +1687,6 @@ ufsdirhash_free(ip); #endif out: - VN_KNOTE_UNLOCKED(vp, NOTE_DELETE); return (error); } @@ -1731,7 +1711,6 @@ vpp, ap->a_cnp); if (error) return (error); - VN_KNOTE_UNLOCKED(ap->a_dvp, NOTE_WRITE); vp = *vpp; len = strlen(ap->a_target); if (len < vp->v_mount->mnt_maxsymlinklen) { @@ -1988,7 +1967,7 @@ error = fifo_specops.vop_kqfilter(ap); if (error) - error = ufs_kqfilter(ap); + error = vfs_kqfilter(ap); return (error); } @@ -2372,106 +2351,6 @@ return (error); } -static struct filterops ufsread_filtops = - { 1, NULL, filt_ufsdetach, filt_ufsread }; -static struct filterops ufswrite_filtops = - { 1, NULL, filt_ufsdetach, filt_ufswrite }; -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_WRITE: - kn->kn_fop = &ufswrite_filtops; - break; - case EVFILT_VNODE: - kn->kn_fop = &ufsvnode_filtops; - break; - default: - return (1); - } - - kn->kn_hook = (caddr_t)vp; - - if (vp->v_pollinfo == NULL) - v_addpollinfo(vp); - if (vp->v_pollinfo == NULL) - return ENOMEM; - knlist_add(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0); - - return (0); -} - -static void -filt_ufsdetach(struct knote *kn) -{ - struct vnode *vp = (struct vnode *)kn->kn_hook; - - KASSERT(vp->v_pollinfo != NULL, ("Mising v_pollinfo")); - knlist_remove(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0); -} - -/*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); -} - -/*ARGSUSED*/ -static int -filt_ufswrite(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); - - kn->kn_data = 0; - return (1); -} - -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. */ struct vop_vector ufs_vnodeops = { .vop_default = &default_vnodeops, @@ -2494,7 +2373,7 @@ .vop_open = ufs_open, .vop_pathconf = ufs_pathconf, .vop_poll = vop_stdpoll, - .vop_kqfilter = ufs_kqfilter, + .vop_kqfilter = vfs_kqfilter, .vop_print = ufs_print, .vop_readdir = ufs_readdir, .vop_readlink = ufs_readlink, Index: src/sys/kern/vfs_vnops.c =================================================================== --- src/sys/kern/vfs_vnops.c (revision 161) +++ src/sys/kern/vfs_vnops.c (working copy) @@ -159,6 +159,7 @@ NDFREE(ndp, NDF_ONLY_PNBUF); return (error); } + VN_KNOTE_UNLOCKED(ndp->ni_dvp, NOTE_WRITE); ASSERT_VOP_UNLOCKED(ndp->ni_dvp, "create"); ASSERT_VOP_LOCKED(ndp->ni_vp, "create"); fmode &= ~O_TRUNC; Index: src/sys/kern/vfs_syscalls.c =================================================================== --- src/sys/kern/vfs_syscalls.c (revision 161) +++ src/sys/kern/vfs_syscalls.c (working copy) @@ -1084,6 +1084,7 @@ if (error) goto bad; } + VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); VFS_UNLOCK_GIANT(vfslocked); /* * Release our private reference, leaving the one associated with @@ -1316,6 +1317,8 @@ error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); if (error == 0) vput(nd.ni_vp); + else + VN_KNOTE_UNLOCKED(nd.ni_dvp, NOTE_WRITE); #ifdef MAC out: #endif @@ -1440,6 +1443,10 @@ if (error == 0) #endif error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); + if (error == 0) { + VN_KNOTE_UNLOCKED(vp, NOTE_LINK); + VN_KNOTE_UNLOCKED(nd.ni_dvp, NOTE_WRITE); + } VOP_UNLOCK(vp, 0, td); vput(nd.ni_dvp); } @@ -1531,8 +1538,10 @@ #endif VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath); - if (error == 0) + if (error == 0) { + VN_KNOTE_UNLOCKED(nd.ni_dvp, NOTE_WRITE); vput(nd.ni_vp); + } #ifdef MAC out2: #endif @@ -1671,7 +1680,10 @@ goto out; #endif VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); - error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); + if (!(error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd))) { + VN_KNOTE_UNLOCKED(vp, NOTE_DELETE); + VN_KNOTE_UNLOCKED(nd.ni_dvp, NOTE_WRITE); + } #ifdef MAC out: #endif @@ -2348,6 +2360,8 @@ error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); + if (!error) + VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); return (error); } @@ -2465,6 +2479,8 @@ error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); + if (!error) + VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); return (error); } @@ -2598,6 +2614,8 @@ error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); + if (!error) + VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); return (error); } @@ -2789,6 +2807,8 @@ error = VOP_SETATTR(vp, &vattr, td->td_ucred, td); VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); + if (!error) + VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); return (error); } @@ -2984,6 +3004,8 @@ vput(vp); vn_finished_write(mp); VFS_UNLOCK_GIANT(vfslocked); + if (!error) + VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); return (error); } @@ -3041,6 +3063,8 @@ } VOP_UNLOCK(vp, 0, td); vn_finished_write(mp); + if (!error) + VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); drop: VFS_UNLOCK_GIANT(vfslocked); fdrop(fp, td); @@ -3179,6 +3203,7 @@ int tvfslocked; int fvfslocked; int error; + int target_exists; bwillwrite(); #ifdef MAC @@ -3221,6 +3246,7 @@ goto out1; } tvfslocked = NDHASGIANT(&tond); + target_exists = 0; tdvp = tond.ni_dvp; tvp = tond.ni_vp; if (tvp != NULL) { @@ -3231,6 +3257,7 @@ error = EISDIR; goto out; } + target_exists = 1; } if (fvp == tdvp) error = EINVAL; @@ -3256,6 +3283,13 @@ } error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); + if (!error) { + VN_KNOTE_UNLOCKED(fromnd.ni_dvp, NOTE_WRITE); + VN_KNOTE_UNLOCKED(tond.ni_dvp, NOTE_WRITE); + if (target_exists) + VN_KNOTE_UNLOCKED(tond.ni_vp, NOTE_DELETE); + VN_KNOTE_UNLOCKED(fromnd.ni_vp, NOTE_RENAME); + } NDFREE(&fromnd, NDF_ONLY_PNBUF); NDFREE(&tond, NDF_ONLY_PNBUF); } else { @@ -3366,8 +3400,10 @@ #endif NDFREE(&nd, NDF_ONLY_PNBUF); vput(nd.ni_dvp); - if (!error) + if (!error) { vput(nd.ni_vp); + VN_KNOTE_UNLOCKED(nd.ni_dvp, NOTE_WRITE | NOTE_LINK); + } vn_finished_write(mp); VFS_UNLOCK_GIANT(vfslocked); ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); @@ -3456,6 +3492,10 @@ vrele(nd.ni_dvp); else vput(nd.ni_dvp); + if (!error) { + VN_KNOTE_UNLOCKED(nd.ni_dvp, NOTE_WRITE | NOTE_LINK); + VN_KNOTE_UNLOCKED(nd.ni_vp, NOTE_DELETE); + } vput(vp); VFS_UNLOCK_GIANT(vfslocked); ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); @@ -4059,6 +4099,7 @@ vn_finished_write(mp); if (error) goto bad; + VN_KNOTE_UNLOCKED(vp, NOTE_ATTRIB); } error = VOP_OPEN(vp, fmode, td->td_ucred, td, -1); if (error) Index: src/sys/kern/uipc_usrreq.c =================================================================== --- src/sys/kern/uipc_usrreq.c (revision 161) +++ src/sys/kern/uipc_usrreq.c (working copy) @@ -837,6 +837,7 @@ vn_finished_write(mp); goto done; } + VN_KNOTE_UNLOCKED(nd.ni_dvp, NOTE_WRITE); vp = nd.ni_vp; ASSERT_VOP_LOCKED(vp, "unp_bind"); soun = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK); Index: src/sys/kern/kern_event.c =================================================================== --- src/sys/kern/kern_event.c (revision 161) +++ src/sys/kern/kern_event.c (working copy) @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -132,7 +133,12 @@ static int filt_timerattach(struct knote *kn); static void filt_timerdetach(struct knote *kn); static int filt_timer(struct knote *kn, long hint); +static int filt_vfsread(struct knote *kn, long hint); +static int filt_vfswrite(struct knote *kn, long hint); +static int filt_vfsvnode(struct knote *kn, long hint); +static void filt_vfsdetach(struct knote *kn); + static struct filterops file_filtops = { 1, filt_fileattach, NULL, NULL }; static struct filterops kqread_filtops = @@ -142,6 +148,12 @@ { 0, filt_procattach, filt_procdetach, filt_proc }; static struct filterops timer_filtops = { 0, filt_timerattach, filt_timerdetach, filt_timer }; +static struct filterops vfsread_filtops = + { 1, NULL, filt_vfsdetach, filt_vfsread }; +static struct filterops vfswrite_filtops = + { 1, NULL, filt_vfsdetach, filt_vfswrite }; +static struct filterops vfsvnode_filtops = + { 1, NULL, filt_vfsdetach, filt_vfsvnode }; static uma_zone_t knote_zone; static int kq_ncallouts = 0; @@ -1840,3 +1852,93 @@ if (kn != NULL) uma_zfree(knote_zone, kn); } + +int +vfs_kqfilter(struct vop_kqfilter_args *ap) +{ + struct vnode *vp = ap->a_vp; + struct knote *kn = ap->a_kn; + + switch (kn->kn_filter) { + case EVFILT_READ: + kn->kn_fop = &vfsread_filtops; + break; + case EVFILT_WRITE: + kn->kn_fop = &vfswrite_filtops; + break; + case EVFILT_VNODE: + kn->kn_fop = &vfsvnode_filtops; + break; + default: + return (1); + } + + kn->kn_hook = (caddr_t)vp; + + if (vp->v_pollinfo == NULL) + v_addpollinfo(vp); + if (vp->v_pollinfo == NULL) + return (ENOMEM); + knlist_add(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0); + + return (0); +} + +static void +filt_vfsdetach(struct knote *kn) +{ + struct vnode *vp = (struct vnode *)kn->kn_hook; + + KASSERT(vp->v_pollinfo != NULL, ("Missing v_pollinfo")); + knlist_remove(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0); +} + +/*ARGSUSED*/ +static int +filt_vfsread(struct knote *kn, long hint) +{ + struct vnode *vp = (struct vnode *)kn->kn_hook; + struct vattr va; + + /* + * 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); + } + + if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread)) + return (0); + + kn->kn_data = va.va_size - kn->kn_fp->f_offset; + return (kn->kn_data != 0); +} + +/*ARGSUSED*/ +static int +filt_vfswrite(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); + + kn->kn_data = 0; + return (1); +} + +static int +filt_vfsvnode(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); +} Index: src/sys/fs/msdosfs/msdosfs_vnops.c =================================================================== --- src/sys/fs/msdosfs/msdosfs_vnops.c (revision 161) +++ src/sys/fs/msdosfs/msdosfs_vnops.c (working copy) @@ -1899,6 +1899,7 @@ .vop_fsync = msdosfs_fsync, .vop_getattr = msdosfs_getattr, .vop_inactive = msdosfs_inactive, + .vop_kqfilter = vfs_kqfilter, .vop_link = msdosfs_link, .vop_lookup = vfs_cache_lookup, .vop_mkdir = msdosfs_mkdir, Index: src/sys/sys/vnode.h =================================================================== --- src/sys/sys/vnode.h (revision 161) +++ src/sys/sys/vnode.h (working copy) @@ -699,6 +699,8 @@ void vfs_hash_rehash(struct vnode *vp, u_int hash); void vfs_hash_remove(struct vnode *vp); +int vfs_kqfilter(struct vop_kqfilter_args *); + #endif /* _KERNEL */ #endif /* !_SYS_VNODE_H_ */