Date: Sun, 13 Jun 2010 10:58:01 GMT From: Ilya Putsikau <ilya@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 179568 for review Message-ID: <201006131058.o5DAw1pF084138@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@179568?ac=10 Change 179568 by ilya@ilya_triton on 2010/06/13 10:57:15 - Update node path while processing event, first perform direct lookup for cached path and if it fails try to get full path - Add rename hook - Perform full path lookup for fd in addwatch - Replace full path hash table with inode number hash table. - Improve path handling in both fnnode and fnevent. - Remove reference counting from fnwatch, there can be max 2 references Affected files ... .. //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_notify.c#3 edit .. //depot/projects/soc2010/ilya_fsnotify/src/sys/sys/fsnotify.h#3 edit Differences ... ==== //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_notify.c#3 (text+ko) ==== @@ -34,12 +34,15 @@ #include <sys/conf.h> #include <sys/condvar.h> #include <sys/fcntl.h> +#include <sys/file.h> +#include <sys/filedesc.h> #include <sys/filio.h> #include <sys/hash.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> +#include <sys/mount.h> #include <sys/mutex.h> #include <sys/namei.h> #include <sys/poll.h> @@ -69,12 +72,14 @@ TAILQ_HEAD(, fnwatch) nd_watchlist; struct mtx nd_mtx; struct vnode *nd_vnode; + struct mount *nd_mount; char *nd_path; + char *nd_pathfree; + ino_t nd_ino; + volatile u_int nd_refcnt; int nd_pathlen; - uint32_t nd_pathhash; int nd_watchcount; u_int nd_supermask; - volatile u_int nd_refcnt; }; struct fneventhandle { @@ -86,8 +91,8 @@ struct fnevent { TAILQ_ENTRY(fnevent) ev_queueentry; struct fnnode *ev_node; - char *ev_path; - int ev_pathlen; + char *ev_pathfree; + int ev_pathpos; int ev_mask; int ev_cookie; int ev_handlecount; @@ -102,7 +107,6 @@ struct fnsession *wt_session; int wt_mask; int wt_wd; - volatile u_int wt_refcnt; }; @@ -110,7 +114,6 @@ static MALLOC_DEFINE(M_FSNOTIFY, "fsnotify", "fsnotify"); static MALLOC_DEFINE(M_FSNOTIFYHASH, "fsnotify_hash", "fsnotify hash tables"); -static MALLOC_DEFINE(M_FSNOTIFYPATH, "fsnotify_path", "fsnotify path buffers"); static struct cdev *fsnotify_dev; @@ -121,7 +124,7 @@ static struct taskqueue *fsnotify_tq; static struct fnnode_hashhead **fnnode_vphashtbl; -static struct fnnode_hashhead **fnnode_pathhashtbl; +static struct fnnode_hashhead **fnnode_inohashtbl; static struct mtx fnnode_hashmtx; static u_long fnnode_hashmask; @@ -149,16 +152,20 @@ static void process_queue(void *context, int pending); static void enqueue_direvent(struct fnnode *dirnode, struct componentname *cnp, - int mask); -static void enqueue_fileevent(struct fnnode *dirnode, int mask); + int cookie, int mask); +static void enqueue_fileevent(struct fnnode *dirnode, int cookie, int mask); static void session_drophandle(struct fnsession *ss, struct fneventhandle *eh); static int session_addwatch(struct fnsession *ss, struct fnnode *node, int mask, struct fnwatch **watchpp); static int session_rmwatch(struct fnsession *ss, int wd); static struct fnnode* node_lookup(struct vnode *vp); -static struct fnnode* node_alloc(char *path, int pathlen); -static void node_create(struct fnnode *node, struct vnode *vp); +static struct fnnode* node_lookupex(struct vnode *vp, ino_t *inop, + int vplocked); +static struct fnnode* node_alloc(struct vnode *vp, ino_t ino); static void node_destroy(struct fnnode *node); +static void event_copypath(struct fnevent *event, char *path, int *pathlen); +static int event_pathlen(struct fnevent *event); +static int event_nextcookie(void); static int fsnotify_modevent(struct module *module, int cmd, void *arg) @@ -185,7 +192,7 @@ hashsize = MAX(desiredvnodes / 32, 16); fnnode_vphashtbl = hashinit(hashsize, M_FSNOTIFYHASH, &fnnode_hashmask); - fnnode_pathhashtbl = hashinit(hashsize, M_FSNOTIFYHASH, + fnnode_inohashtbl = hashinit(hashsize, M_FSNOTIFYHASH, &fnnode_hashmask); TASK_INIT(&fsnotify_task, 0, process_queue, NULL); @@ -218,7 +225,7 @@ taskqueue_drain(fsnotify_tq, &fsnotify_task); taskqueue_free(fsnotify_tq); free(fnnode_vphashtbl, M_FSNOTIFYHASH); - free(fnnode_pathhashtbl, M_FSNOTIFYHASH); + free(fnnode_inohashtbl, M_FSNOTIFYHASH); mtx_destroy(&fsnotify_queue_mtx); mtx_destroy(&fnnode_hashmtx); break; @@ -281,11 +288,13 @@ static int fsnotify_read(struct cdev *dev, struct uio *uio, int flag) { - struct fsnotify_event *ue; + struct fnevent *event; + struct fneventhandle *eh; struct fnsession *ss; - struct fneventhandle *eh; + struct fnwatch *watch; + struct fsnotify_event *fe; int len, error; - char user_buf[sizeof(struct fsnotify_event) + PATH_MAX]; + char user_buf[sizeof(struct fsnotify_event) + MAXPATHLEN]; if (uio->uio_resid == 0) return (0); @@ -312,13 +321,16 @@ } eh = TAILQ_FIRST(&ss->ss_queue); - ue = (struct fsnotify_event *) user_buf; - ue->wd = eh->eh_watch->wt_wd; - ue->mask = eh->eh_watch->wt_mask & eh->eh_event->ev_mask; - ue->cookie = eh->eh_event->ev_cookie; - ue->len = eh->eh_event->ev_pathlen + 1; - memcpy(ue->name, eh->eh_event->ev_path, ue->len); - len = ue->len + sizeof(struct fsnotify_event); + event = eh->eh_event; + watch = eh->eh_watch; + fe = (struct fsnotify_event *) user_buf; + fe->fe_wd = watch->wt_wd; + fe->fe_mask = watch->wt_mask & event->ev_mask; + fe->fe_fileno = event->ev_node->nd_ino; + fe->fe_cookie = event->ev_cookie; + event_copypath(event, fe->fe_name, &fe->fe_namelen); + fe->fe_namelen += 1; + len = fe->fe_namelen + sizeof(struct fsnotify_event); mtx_unlock(&ss->ss_mtx); @@ -341,9 +353,16 @@ { struct fnsession *ss; struct fnnode *node; + struct fnnode *freenode; + struct fnevent *event; struct fnwatch *watch; struct fsnotify_addwatch_args *add_args; + struct file *fp; + struct filedesc *fdp; struct vnode *vp; + ino_t ino; + char *path, *pathfree; + int vfslocked; int error; error = devfs_get_cdevpriv((void **)&ss); @@ -353,34 +372,57 @@ switch (cmd) { case FSNOTIFY_ADDWATCH: add_args = (struct fsnotify_addwatch_args *)data; - /* TODO: get vnode for fd */ + fdp = td->td_proc->p_fd; vp = NULL; - node = node_lookup(vp); - if (node == NULL) { - /* TODO: get full path for vp */ - node_alloc(NULL, 0); - node_create(node, vp); - mtx_lock(&node->nd_mtx); + FILEDESC_SLOCK(fdp); + fp = fget_locked(fdp, add_args->fa_fd); + if (fp != NULL && fp->f_type == DTYPE_VNODE) { + vp = fp->f_vnode; + } + FILEDESC_SUNLOCK(fdp); + if (vp == NULL) + return (EBADF); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + node = node_lookupex(vp, &ino, 0); + if (node != NULL) { + VFS_UNLOCK_GIANT(vfslocked); + freenode = NULL; + } else { + error = vn_fullpath(td, vp, &path, &pathfree); + VFS_UNLOCK_GIANT(vfslocked); + if (error != 0) + return (error); + node = node_alloc(vp, ino); + node->nd_path = path; + node->nd_pathlen = strlen(path); + node->nd_pathfree = pathfree; + freenode = node; + } + error = session_addwatch(ss, node, add_args->fa_mask, &watch); + if (error == 0) { + add_args->fa_wd = watch->wt_wd; + } else if (freenode != NULL) { + node_destroy(node); } - error = session_addwatch(ss, node, add_args->mask, &watch); - if (error == 0) - add_args->wd = watch->wt_wd; - return (error); + break; case FSNOTIFY_RMWATCH: error = session_rmwatch(ss, *(int *)data); - return (error); + break; case FIONREAD: mtx_lock(&ss->ss_mtx); - if (!TAILQ_EMPTY(&ss->ss_queue)) + if (!TAILQ_EMPTY(&ss->ss_queue)) { + event = TAILQ_FIRST(&ss->ss_queue)->eh_event; *(int *)data = sizeof(struct fsnotify_event) + - TAILQ_FIRST(&ss->ss_queue)->eh_event->ev_pathlen + 1; - else + event_pathlen(event) + 1; + } else *(int *)data = 0; mtx_unlock(&ss->ss_mtx); - return (0); + break; default: - return (ENOIOCTL); + error = ENOENT; } + + return (error); } static int @@ -419,7 +461,7 @@ dirnode = node_lookup(dvp); if (dirnode != NULL) - enqueue_direvent(NULL, cnp, FE_CREATE); + enqueue_direvent(dirnode, cnp, event_nextcookie(), FE_CREATE); return (0); } @@ -427,20 +469,18 @@ hook_generic_remove(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct fnnode *dirnode, *n; + struct fnnode *dirnode, *node; + int cookie; + + cookie = event_nextcookie(); - n = node_lookup(vp); - if (n != NULL) { - /* TODO */ - /* - node_remove(n); - */ - enqueue_fileevent(NULL, FE_DESTROY); - } + node = node_lookup(vp); + if (node != NULL) + enqueue_fileevent(node, cookie, FE_DESTROY | FE_REMOVE); dirnode = node_lookup(dvp); if (dirnode != NULL) - enqueue_direvent(NULL, cnp, FE_REMOVE); + enqueue_direvent(dirnode, cnp, cookie, FE_REMOVE); } static int @@ -488,21 +528,38 @@ static int hook_rename(struct vop_rename_args *ap) { + struct fnnode *fdirnode, *fnode, *tdirnode, *tnode; + int cookie; + + cookie = event_nextcookie(); + if (ap->a_tvp != NULL) { + tnode = node_lookup(ap->a_tvp); + if (tnode != NULL) { + enqueue_fileevent(tnode, cookie, + FE_DESTROY | FE_REMOVE); + } + } + fnode = node_lookupex(ap->a_fvp, NULL, 0); + if (fnode != NULL) { + /* TODO */ + /* mark path stale */ + } + + fdirnode = node_lookupex(ap->a_fdvp, NULL, 0); + if (fdirnode != NULL) + enqueue_direvent(fdirnode, ap->a_fcnp, cookie, FE_RENAME_FROM); + tdirnode = node_lookup(ap->a_tdvp); + if (tdirnode != NULL) + enqueue_direvent(tdirnode, ap->a_tcnp, cookie, FE_RENAME_TO); + return (0); } -static __inline void -watch_hold(struct fnwatch *watch) -{ - refcount_acquire(&watch->wt_refcnt); -} - static void -watch_drop(struct fnwatch *watch) +watch_tryfree(struct fnwatch *watch) { - if (refcount_release(&watch->wt_refcnt) != 0) { + if (watch->wt_session == NULL && watch->wt_node == NULL) free(watch, M_FSNOTIFY); - } } static int @@ -522,24 +579,6 @@ return (nwd); } -static struct fnnode* -node_alloc(char *path, int pathlen) -{ - struct fnnode *node; - - node = malloc(sizeof(struct fnnode), M_FSNOTIFY, M_WAITOK | M_ZERO); - node->nd_path = malloc(pathlen + 1, M_FSNOTIFYPATH, M_WAITOK); - - refcount_init(&node->nd_refcnt, 1); - - memcpy(node->nd_path, path, pathlen); - node->nd_path[pathlen] = '\0'; - node->nd_pathlen = pathlen; - node->nd_pathhash = hash32_buf(node->nd_path, pathlen, HASHINIT); - - return (node); -} - static __inline void node_hold(struct fnnode *node) { @@ -553,7 +592,7 @@ KASSERT(node->nd_watchcount == 0 && node->nd_supermask == 0 && TAILQ_EMPTY(&node->nd_watchlist), ("Invalid reference count")); mtx_destroy(&node->nd_mtx); - free(node->nd_path, M_FSNOTIFYPATH); + free(node->nd_path, M_TEMP); free(node, M_FSNOTIFY); } } @@ -564,47 +603,65 @@ uint32_t h; h = hash32_buf(vp, sizeof(vp), HASHINIT); + h += vp->v_mount->mnt_hashseed; return fnnode_vphashtbl[h & fnnode_hashmask]; } static __inline struct fnnode_hashhead * -node_pathhashhead(char *path, int pathlen) +node_inohashhead(struct mount *mnt, ino_t ino) { uint32_t h; - h = hash32_buf(path, pathlen, HASHINIT); - return fnnode_vphashtbl[h & fnnode_hashmask]; + h = ino + mnt->mnt_hashseed; + return fnnode_inohashtbl[h & fnnode_hashmask]; } -static void -node_create(struct fnnode *node, struct vnode *vp) +static struct fnnode * +node_alloc(struct vnode *vp, ino_t ino) { - struct fnnode *ni; + struct fnnode *node; MPASS(vp != NULL); + + node = malloc(sizeof(struct fnnode), M_FSNOTIFY, M_WAITOK | M_ZERO); + + refcount_init(&node->nd_refcnt, 1); + mtx_lock(&fnnode_hashmtx); /* DEBUG */ - LIST_FOREACH(ni, node_vphashhead(vp), nd_hashentry) { - if (ni->nd_vnode == vp) { - panic("Node already exists in vnode hash table: %s", - node->nd_path); + LIST_FOREACH(node, node_vphashhead(vp), nd_hashentry) { + if (node->nd_vnode == vp) { + panic("Node already exists in vnode hash table: %p", + node->nd_vnode); } } LIST_INSERT_HEAD(node_vphashhead(vp), node, nd_hashentry); mtx_unlock(&fnnode_hashmtx); + + return (node); } static void -node_destroy(struct fnnode *node) +node_detachwatches(struct fnnode *node) { struct fnwatch *watch; - mtx_lock(&node->nd_mtx); + mtx_assert(&node->nd_mtx, MA_OWNED); + node->nd_watchcount = 0; + node->nd_supermask = 0; while (!TAILQ_EMPTY(&node->nd_watchlist)) { watch = TAILQ_FIRST(&node->nd_watchlist); TAILQ_REMOVE(&node->nd_watchlist, watch, wt_nodeentry); - watch_drop(watch); + watch->wt_node = NULL; + watch_tryfree(watch); } +} + +static void +node_destroy(struct fnnode *node) +{ + mtx_lock(&node->nd_mtx); + node_detachwatches(node); mtx_unlock(&node->nd_mtx); mtx_lock(&fnnode_hashmtx); LIST_REMOVE(node, nd_hashentry); @@ -612,16 +669,36 @@ node_drop(node); } +static int +node_getino(struct vnode *vp, ino_t *inop, int vplocked) +{ + struct vattr va; + int error; + + if (vplocked == 0) { + error = vn_lock(vp, LK_SHARED); + if (error != 0) + return (error); + } + + error = VOP_GETATTR(vp, &va, thread0.td_ucred); + if (error == 0) + *inop = va.va_fileid; + + if (vplocked == 0) + VOP_UNLOCK(vp, 0); + + return (error); +} + static struct fnnode* -node_lookup(struct vnode *vp) +node_lookupex(struct vnode *vp, ino_t *inop, int vplocked) { struct fnnode *node, *rv; - int pathhash, pathlen; - char *path; + ino_t ino; + int error; rv = NULL; - path = NULL; - pathhash = pathlen = 0; /* FIXME */ /* Node is always on one of the hash tables. */ mtx_lock(&fnnode_hashmtx); LIST_FOREACH(node, node_vphashhead(vp), nd_hashentry) { @@ -636,15 +713,19 @@ mtx_unlock(&fnnode_hashmtx); if (node == NULL) { - /* TODO: lookup full path */ + if (inop == NULL) + inop = &ino; + error = node_getino(vp, inop, vplocked); + if (error != 0) + goto done; mtx_lock(&fnnode_hashmtx); - LIST_FOREACH(node, node_vphashhead(vp), nd_hashentry) { - if (node->nd_pathhash != pathhash || - node->nd_pathlen != pathlen || - memcmp(node->nd_path, path, pathlen) != 0) + LIST_FOREACH(node, + node_inohashhead(vp->v_mount, *inop), nd_hashentry) { + if (node->nd_ino != *inop || + node->nd_mount != vp->v_mount) continue; - /* add to vphash */ + /* add to inohash */ mtx_lock(&node->nd_mtx); rv = (node->nd_watchcount == 0 ? NULL : node); if (rv == NULL) @@ -654,22 +735,89 @@ mtx_unlock(&fnnode_hashmtx); } - if (path != NULL) - free(path, M_FSNOTIFY); +done: + return (rv); +} + +static __inline struct fnnode* +node_lookup(struct vnode *vp) +{ + ASSERT_VOP_LOCKED(vp, "fsnotify node lookup"); + + return (node_lookupex(vp, NULL, 1)); +} + +static int +node_updatepath(struct fnnode *node) +{ + struct nameidata ni; + struct vnode *vp; + char *path, *pathfree; + char *npath, *npathfree; + int vfslocked, error; + + /* + * TODO: has races. should be executed only in *single* process_queue + * thread + */ + vp = node->nd_vnode; + if ((vp->v_iflag & VI_DOOMED) != 0) + return (ENOENT); + + path = node->nd_path; + pathfree = node->nd_pathfree; + npath = npathfree = NULL; + vhold(vp); + mtx_unlock(&node->nd_mtx); + + NDINIT(&ni, LOOKUP, MPSAFE | FOLLOW, UIO_SYSSPACE, path, curthread); + error = namei(&ni); + vfslocked = NDHASGIANT(&ni); + if (error == 0) { + if (vp != ni.ni_vp) { + printf("fsnotify: vnode was replaced between lookups: %s\n", + path); + error = ENOENT; + } + NDFREE(&ni, 0); + } + if (error != 0) { + error = vn_fullpath(curthread, vp, &npath, &npathfree); + } - return (rv); + VFS_UNLOCK_GIANT(vfslocked); + if ((vp->v_iflag & VI_DOOMED) != 0) { + printf("fsnotify: vnode is doomed: %s\n", path); + error = ENOENT; + } + vdrop(vp); + mtx_lock(&node->nd_mtx); + if (path != node->nd_path) { + /* Lookup race */ + free(pathfree, M_TEMP); + MPASS(node->nd_path != NULL); + error = 0; + } else if (error == 0 && npath != NULL) { + free(node->nd_pathfree, M_TEMP); + node->nd_path = npath; + node->nd_pathlen = strlen(npath); + node->nd_pathfree = npathfree; + npathfree = NULL; + } + if (npathfree != NULL) + free(npathfree, M_TEMP); + return (error); } static struct fnevent * -event_alloc(struct fnnode *node, char *path, int pathlen, int handle_maxsize, +event_alloc(struct fnnode *node, char *name, int namelen, int handle_maxsize, int mask, int cookie) { struct fnevent *event; - int addslash; MPASS(handle_maxsize > 0); MPASS(mask != 0); - MPASS(pathlen > 0); + MPASS(namelen > 0); event = malloc(sizeof(struct fnevent) + (sizeof(struct fneventhandle) * handle_maxsize), @@ -678,42 +826,78 @@ event->ev_node = node; event->ev_mask = mask; event->ev_cookie = cookie; - addslash = (path[0] != '/' && node->nd_path[0] != '/' ? 1 : 0); - event->ev_pathlen = node->nd_pathlen + addslash + pathlen; - event->ev_path = malloc(event->ev_pathlen + 1, M_FSNOTIFYPATH, - M_WAITOK); - memcpy(event->ev_path, node->nd_path, node->nd_pathlen); - if (addslash != 0) - event->ev_path[node->nd_pathlen] = '/'; - memcpy(event->ev_path + node->nd_pathlen + addslash, path, - pathlen); - event->ev_path[event->ev_pathlen] = '\0'; + event->ev_pathfree = uma_zalloc(namei_zone, M_WAITOK); + event->ev_pathpos = MAXPATHLEN - 1 - namelen; + memcpy(event->ev_pathfree + event->ev_pathpos, name, namelen); + event->ev_pathfree[MAXPATHLEN - 1] = '\0'; return (event); } -static int -event_nextcookie(void) +static void +event_free(struct fnevent *event) +{ + node_drop(event->ev_node); + uma_zfree(namei_zone, event->ev_pathfree); + free(event, M_FSNOTIFY); +} + +static __inline int +event_pathlen(struct fnevent *event) { - static volatile int cookie = 1; + return (MAXPATHLEN - 1 - event->ev_pathpos); +} - return atomic_fetchadd_int(&cookie, 1); +static __inline void +event_copypath(struct fnevent *event, char *path, int *pathlen) +{ + *pathlen = event_pathlen(event); + memcpy(path, event->ev_pathfree + *pathlen, *pathlen); } static void eventhandle_drop(struct fneventhandle *eh) { struct fnnode *node; + int handlecount; node = eh->eh_event->ev_node; mtx_lock(&node->nd_mtx); - eh->eh_event->ev_handlecount--; - if (eh->eh_event->ev_handlecount == 0) { - node_drop(node); - free(eh->eh_event, M_FSNOTIFY); - } + handlecount = --eh->eh_event->ev_handlecount; mtx_unlock(&node->nd_mtx); + MPASS(handlecount >= 0); + if (handlecount == 0) + event_free(eh->eh_event); +} + +static void +event_prependpath(struct fnevent *event, struct fnnode *node) +{ + int pos, len; + + pos = event->ev_pathpos; + len = node->nd_pathlen; + MPASS(len > 0 && node->nd_path[len - 1] != '/'); + MPASS(MAXPATHLEN - pos < len + 1); + + event->ev_pathfree[--pos] = '/'; + pos -= len; + memcpy(event->ev_pathfree + pos, node->nd_path, len); + + event->ev_pathpos = pos; +} + +static int +event_nextcookie(void) +{ + static volatile int cookie = 1; + int r; + + r = atomic_fetchadd_int(&cookie, 1); + if (r == 0) + r = atomic_fetchadd_int(&cookie, 1); + return (r); } static int @@ -724,8 +908,6 @@ watch = malloc(sizeof(struct fnwatch), M_FSNOTIFY, M_WAITOK | M_ZERO); - refcount_init(&watch->wt_refcnt, 2); - watch->wt_wd = watch_nextwd(); watch->wt_mask = mask; watch->wt_session = ss; @@ -738,6 +920,8 @@ mtx_lock(&node->nd_mtx); TAILQ_INSERT_TAIL(&node->nd_watchlist, watch, wt_nodeentry); + node->nd_watchcount++; + node->nd_supermask |= watch->wt_mask; mtx_unlock(&node->nd_mtx); if (watchpp != NULL) @@ -756,8 +940,8 @@ if (watch->wt_wd != wd) continue; TAILQ_REMOVE(&ss->ss_watchlist, watch, wt_sessionentry); - watch_drop(watch); watch->wt_session = NULL; + watch_tryfree(watch); break; } mtx_unlock(&ss->ss_mtx); @@ -805,6 +989,7 @@ struct fnwatch *watch; struct fnevent *event; struct fneventhandle *eh; + struct vnode *vp; int i, handle_count; while (1) { @@ -819,8 +1004,6 @@ node = event->ev_node; - /* FIXME: lookup node full path */ - mtx_lock(&node->nd_mtx); TAILQ_FOREACH(watch, &node->nd_watchlist, wt_nodeentry) { if ((watch->wt_mask & event->ev_mask) == 0) @@ -835,17 +1018,31 @@ eh->eh_watch = watch; } handle_count = event->ev_handlecount; + if (handle_count == 0) { + node->nd_supermask &= ~event->ev_mask; + mtx_unlock(&node->nd_mtx); + event_free(event); + continue; + } + vp = node->nd_vnode; + if (vp != NULL) + node_updatepath(node); + else + printf("fsnotify: vnode not found, reusing cached path: %s\n", + node->nd_path); + if (event->ev_mask & FE_DESTROY) + node_detachwatches(node); + + event_prependpath(event, node); mtx_unlock(&node->nd_mtx); - MPASS(handle_count > 0); - for (i = 0; i < handle_count; i++) { + for (i = 0; i < handle_count; i++) session_enqueue(&event->ev_handlebuf[i]); - } } } static void -enqueue_direvent(struct fnnode *dirnode, struct componentname *cnp, int mask) +enqueue_direvent(struct fnnode *dirnode, struct componentname *cnp, int cookie, int mask) { struct fnevent *event; int supermask, watch_count; @@ -866,7 +1063,7 @@ KASSERT(watch_count > 0, ("No watchers found")); event = event_alloc(dirnode, cnp->cn_nameptr, cnp->cn_namelen, - watch_count + 1, mask, event_nextcookie()); + watch_count + 1, mask, cookie); mtx_lock(&fsnotify_queue_mtx); TAILQ_INSERT_TAIL(&fsnotify_queue, event, ev_queueentry); @@ -876,7 +1073,7 @@ } static void -enqueue_fileevent(struct fnnode *node, int mask) +enqueue_fileevent(struct fnnode *node, int cookie, int mask) { printf("enqueue_fileevent: %x\n", mask); } ==== //depot/projects/soc2010/ilya_fsnotify/src/sys/sys/fsnotify.h#3 (text+ko) ==== @@ -45,17 +45,18 @@ #define FSNOTIFY_RMWATCH _IOW('F', 2, int) struct fsnotify_event { - int32_t wd; - uint32_t mask; - uint32_t cookie; - uint32_t len; - char name[0]; + int32_t fe_wd; + uint32_t fe_mask; + uint32_t fe_cookie; + uint32_t fe_namelen; + ino_t fe_fileno; + char fe_name[0]; }; struct fsnotify_addwatch_args { - int fd; - int32_t wd; - uint32_t mask; + int fa_fd; + uint32_t fa_mask; + int32_t fa_wd; }; #ifdef _KERNEL
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201006131058.o5DAw1pF084138>