Index: src/sys/kern/kern_event.c =================================================================== --- src/sys/kern/kern_event.c (revision 163) +++ src/sys/kern/kern_event.c (working copy) @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ #include #include #include +#include #include @@ -132,6 +134,9 @@ 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_nvnodeattach(struct knote *kn); +static void filt_nvnodedetach(struct knote *kn); +static int filt_nvnode(struct knote *kn, long hint); static struct filterops file_filtops = { 1, filt_fileattach, NULL, NULL }; @@ -142,6 +147,8 @@ { 0, filt_procattach, filt_procdetach, filt_proc }; static struct filterops timer_filtops = { 0, filt_timerattach, filt_timerdetach, filt_timer }; +static struct filterops nvnode_filtops = + { 0, filt_nvnodeattach, filt_nvnodedetach, filt_nvnode }; static uma_zone_t knote_zone; static int kq_ncallouts = 0; @@ -228,6 +235,7 @@ { &timer_filtops }, /* EVFILT_TIMER */ { &file_filtops }, /* EVFILT_NETDEV */ { &fs_filtops }, /* EVFILT_FS */ + { &nvnode_filtops }, /* EVFILT_NAMEDVNODE */ }; /* @@ -479,6 +487,64 @@ } /* + * Attaches a knote to a vnode found from a path. + * Note: The vnode does not get vput(). + */ +static int +filt_nvnodeattach(struct knote *kn) +{ + struct vnode *vp; + struct nameidata nd; + int error, vfslocked; + + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_SYSSPACE, + (char *)kn->kn_id, curthread); + + if ((error = namei(&nd)) != 0) + return (error); + + vfslocked = NDHASGIANT(&nd); + vp = nd.ni_vp; + kn->kn_hook = 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); + NDFREE(&nd, NDF_ONLY_PNBUF); + VOP_UNLOCK(vp, 0, curthread); + VFS_UNLOCK_GIANT(vfslocked); + + return (0); +} + +static void +filt_nvnodedetach(struct knote *kn) +{ + struct vnode *vp; + + 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); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); + vput(vp); +} + +static int +filt_nvnode(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); +} + +/* * MPSAFE */ int Index: src/sys/sys/event.h =================================================================== --- src/sys/sys/event.h (revision 163) +++ src/sys/sys/event.h (working copy) @@ -38,8 +38,9 @@ #define EVFILT_TIMER (-7) /* timers */ #define EVFILT_NETDEV (-8) /* network devices */ #define EVFILT_FS (-9) /* filesystem events */ +#define EVFILT_NAMEDVNODE (-10) /* vnodes from paths */ -#define EVFILT_SYSCOUNT 9 +#define EVFILT_SYSCOUNT 10 #define EV_SET(kevp_, a, b, c, d, e, f) do { \ struct kevent *kevp = (kevp_); \