Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Jul 2010 05:19:40 GMT
From:      Ilya Putsikau <ilya@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 181039 for review
Message-ID:  <201007160519.o6G5JeqL080259@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181039?ac=10

Change 181039 by ilya@ilya_triton on 2010/07/16 05:19:30

	Add write, close and inactive hooks
	Don't send write, close and inactive events for directories
	Clear node changed flag in inactive hook
	Get cookie number only when needed
	Change hooking mechanism to store function pointers in structure
	Use macros to lock/unlock mutexes
	Fix node_lookupex bug

Affected files ...

.. //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_notify.c#7 edit
.. //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_subr.c#4 edit
.. //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vnode_if.src#2 edit
.. //depot/projects/soc2010/ilya_fsnotify/src/sys/sys/fsnotify.h#5 edit
.. //depot/projects/soc2010/ilya_fsnotify/src/sys/sys/vnode.h#3 edit
.. //depot/projects/soc2010/ilya_fsnotify/src/sys/tools/vnode_if.awk#2 edit

Differences ...

==== //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_notify.c#7 (text+ko) ====

@@ -81,6 +81,7 @@
 	int			nd_pathlen;
 	int			nd_watchcount;
 	u_int			nd_supermask;
+	int			nd_flags;
 };
 
 struct fneventhandle {
@@ -141,41 +142,74 @@
 	.d_name		= "fsnotify",
 };
 
-static void hook_reclaim(struct vnode *vp);
-static vop_create_t hook_create;
-static vop_link_t hook_link;
-static vop_mkdir_t hook_mkdir;
-static vop_remove_t hook_remove;
-static vop_rename_t hook_rename;
-static vop_rmdir_t hook_rmdir;
-static vop_symlink_t hook_symlink;
+static fno_close_t hook_close;
+static fno_create_t hook_create;
+static fno_inactive_t hook_inactive;
+static fno_link_t hook_link;
+static fno_mkdir_t hook_mkdir;
+static fno_reclaim_t hook_reclaim;
+static fno_remove_t hook_remove;
+static fno_rename_t hook_rename;
+static fno_rmdir_t hook_rmdir;
+static fno_symlink_t hook_symlink;
+static fno_write_t hook_write;
+
+static struct fsnotify_ops fsnotify_hooks = {
+	.fno_close	= hook_close,
+	.fno_create	= hook_create,
+	.fno_inactive	= hook_inactive,
+	.fno_link	= hook_link,
+	.fno_mkdir	= hook_mkdir,
+	.fno_reclaim	= hook_reclaim,
+	.fno_remove	= hook_remove,
+	.fno_rename	= hook_rename,
+	.fno_rmdir	= hook_rmdir,
+	.fno_symlink	= hook_symlink,
+	.fno_write	= hook_write,
+};
+
+static void fsnotify_daemon(void *context);
 
-static void process_queue(void *context);
-static void enqueue_direvent(struct fnnode *dirnode, struct componentname *cnp,
-    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_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_alloc(struct vnode *vp, ino_t ino);
 static struct fnnode* node_lookup(struct vnode *vp);
-static struct fnnode* node_lookupex(struct vnode *vp, ino_t *inop,
-    int flags);
-static struct fnnode* node_alloc(struct vnode *vp, ino_t ino);
+static struct fnnode* node_lookupex(struct vnode *vp, ino_t *inop, int flags);
 static void node_hold(struct fnnode *node);
 static void node_drop(struct fnnode *node);
 static void node_watchhold(struct fnnode *node);
 static void node_watchdrop(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 void event_enqueue(struct fnnode *node, struct componentname *cnp,
+    int *cookiep, int mask);
+
 static void watch_free(struct fnwatch *watch);
 
-#define	NODE_ISVALID(a)		((a) != NULL && (a) != FNNODE_INVAL)
+#define	NODE_ISDIR		0x0001
+#define	NODE_CHANGED		0x0002
 
 #define	LOOKUP_VPLOCKED		0x0001
 #define	LOOKUP_IGNINVAL		0x0002
 
+#define	NODE_ISVALID(n)		((n) != NULL && (n) != FNNODE_INVAL)
+
+#define	NODE_LOCK(n)		mtx_lock(&(n)->nd_mtx)
+#define	NODE_UNLOCK(n)		mtx_unlock(&(n)->nd_mtx)
+
+#define SESSION_LOCK(s)		mtx_lock(&(s)->ss_mtx)
+#define SESSION_UNLOCK(s)	mtx_unlock(&(s)->ss_mtx)
+
+#define QUEUE_LOCK()		mtx_lock(&fsnotify_queue_mtx)
+#define QUEUE_UNLOCK()		mtx_unlock(&fsnotify_queue_mtx)
+
+#define INOHASH_LOCK()		mtx_lock(&fnnode_hashmtx)
+#define INOHASH_UNLOCK()	mtx_unlock(&fnnode_hashmtx)
+
 static int
 fsnotify_modevent(struct module *module, int cmd, void *arg)
 {
@@ -187,14 +221,7 @@
 
 	switch (cmd) {
 	case MOD_LOAD:
-		if (fsnotify_hook_reclaim != NULL ||
-		    fsnotify_hook_create != NULL ||
-		    fsnotify_hook_link != NULL ||
-		    fsnotify_hook_mkdir != NULL ||
-		    fsnotify_hook_remove != NULL ||
-		    fsnotify_hook_rename != NULL ||
-		    fsnotify_hook_rmdir != NULL ||
-		    fsnotify_hook_symlink != NULL) {
+		if (fsnotify_curops != &fsnotify_nullops) {
 			printf("fsnotify already loaded\n");
 			return (EEXIST);
 		}
@@ -202,7 +229,7 @@
 		mtx_init(&fsnotify_queue_mtx, "fsnotify_queue", NULL, MTX_DEF);
 		mtx_init(&fnnode_hashmtx, "fsnotify_hash", NULL, MTX_DEF);
 
-		error = kproc_create(process_queue, NULL, &fsnotify_proc,
+		error = kproc_create(fsnotify_daemon, NULL, &fsnotify_proc,
 		    RFHIGHPID, 0, "fsnotify");
 		if (error != 0) {
 			mtx_destroy(&fsnotify_queue_mtx);
@@ -219,42 +246,28 @@
 		fsnotify_dev = make_dev(&fsnotify_cdevsw, 0, UID_ROOT,
 		    GID_WHEEL, 0666, "fsnotify");
 
-		fsnotify_hook_reclaim = hook_reclaim;
-		fsnotify_hook_create = hook_create;
-		fsnotify_hook_link = hook_link;
-		fsnotify_hook_mkdir = hook_mkdir;
-		fsnotify_hook_remove = hook_remove;
-		fsnotify_hook_rename = hook_rename;
-		fsnotify_hook_rmdir = hook_rmdir;
-		fsnotify_hook_symlink = hook_symlink;
+		fsnotify_curops = &fsnotify_hooks;
 		break;
 	case MOD_UNLOAD:
-		fsnotify_hook_reclaim = NULL;
-		fsnotify_hook_create = NULL;
-		fsnotify_hook_link = NULL;
-		fsnotify_hook_mkdir = NULL;
-		fsnotify_hook_remove = NULL;
-		fsnotify_hook_rename = NULL;
-		fsnotify_hook_rmdir = NULL;
-		fsnotify_hook_symlink = NULL;
+		fsnotify_curops = &fsnotify_nullops;
 		destroy_dev(fsnotify_dev);
 
-		mtx_lock(&fsnotify_queue_mtx);
+		QUEUE_LOCK();
 		if ((p = fsnotify_proc) != NULL) {
 			fsnotify_proc = NULL;
 			wakeup_one(&fsnotify_queue);
 			PROC_LOCK(p);
-			mtx_unlock(&fsnotify_queue_mtx);
+			QUEUE_UNLOCK();
 			msleep(p, &p->p_mtx, PWAIT, "fsnotify_destroy", 0);
 			PROC_UNLOCK(p);
 		} else
-			mtx_unlock(&fsnotify_queue_mtx);
+			QUEUE_UNLOCK();
 
 		for (i = 0; i <= fnnode_hashmask; i++) {
 			hashhead = &fnnode_inohashtbl[i];
 			while (!LIST_EMPTY(hashhead)) {
 				node = LIST_FIRST(hashhead);
-				mtx_lock(&node->nd_mtx);
+				NODE_LOCK(node);
 				if (NODE_ISVALID(node->nd_vnode)) {
 					VI_LOCK(node->nd_vnode);
 					node->nd_vnode->v_fnnode = NULL;
@@ -262,10 +275,10 @@
 					    node, node->nd_vnode);
 					vdropl(node->nd_vnode);
 					node->nd_vnode = NULL;
-					mtx_unlock(&node->nd_mtx);
+					NODE_UNLOCK(node);
 					node_drop(node);
 				} else
-					mtx_unlock(&node->nd_mtx);
+					NODE_UNLOCK(node);
 				KASSERT(LIST_FIRST(hashhead)->nd_refcnt == 1,
 				    ("Invalid node reference count: %d",
 				    LIST_FIRST(hashhead)->nd_refcnt));
@@ -308,7 +321,7 @@
 	struct fneventhandle *eh;
 
 	printf("session_dtor: %p\n", ss);
-	mtx_lock(&ss->ss_mtx);
+	SESSION_LOCK(ss);
 	while (!TAILQ_EMPTY(&ss->ss_queue)) {
 		eh = TAILQ_FIRST(&ss->ss_queue);
 		session_drophandle(ss, eh);
@@ -318,7 +331,7 @@
 		watch = TAILQ_FIRST(&ss->ss_watchlist);
 		watch_free(watch);
 	}
-	mtx_unlock(&ss->ss_mtx);
+	SESSION_UNLOCK(ss);
 
 	cv_destroy(&ss->ss_queuecv);
 	mtx_destroy(&ss->ss_mtx);
@@ -367,7 +380,7 @@
 	if (error != 0)
 		return (error);
 
-	mtx_lock(&ss->ss_mtx);
+	SESSION_LOCK(ss);
 
 	if (TAILQ_EMPTY(&ss->ss_queue)) {
 		if (flag & O_NONBLOCK)
@@ -378,7 +391,7 @@
 	}
 
 	if (error != 0) {
-		mtx_unlock(&ss->ss_mtx);
+		SESSION_UNLOCK(ss);
 		return (error);
 	}
 
@@ -394,18 +407,18 @@
 	len = fe->fe_namelen + sizeof(struct fsnotify_event);
 	destroy = event->ev_mask & FE_DESTROY;
 
-	mtx_unlock(&ss->ss_mtx);
+	SESSION_UNLOCK(ss);
 
 	error = uiomove(user_buf, MIN(len, uio->uio_resid), uio);
 	printf("fsnotify_read: uiomove: error %d, offset %jd, len %d\n", error,
 	    uio->uio_offset, len);
 	if (error == 0 && uio->uio_offset >= len) {
 		uio->uio_offset = 0;
-		mtx_lock(&ss->ss_mtx);
+		SESSION_LOCK(ss);
 		session_drophandle(ss, eh);
 		if (destroy != 0)
 			watch_free(watch);
-		mtx_unlock(&ss->ss_mtx);
+		SESSION_UNLOCK(ss);
 	}
 
 	return (error);
@@ -450,7 +463,7 @@
 		node = node_lookupex(vp, &ino, LOOKUP_IGNINVAL);
 		if (node != NULL) {
 			node_watchhold(node);
-			mtx_unlock(&node->nd_mtx);
+			NODE_UNLOCK(node);
 			VFS_UNLOCK_GIANT(vfslocked);
 		} else {
 			error = vn_fullpath_global(td, vp, &path, &pathfree);
@@ -462,7 +475,7 @@
 			node->nd_pathlen = strlen(path);
 			node->nd_pathfree = pathfree;
 			node_watchhold(node);
-			mtx_unlock(&node->nd_mtx);
+			NODE_UNLOCK(node);
 		}
 		error = session_addwatch(ss, node, add_args->fa_mask, &watch);
 		node_drop(node);
@@ -474,14 +487,14 @@
 		error = session_rmwatch(ss, *(int *)data);
 		break;
 	case FIONREAD:
-		mtx_lock(&ss->ss_mtx);
+		SESSION_LOCK(ss);
 		if (!TAILQ_EMPTY(&ss->ss_queue)) {
 			event = TAILQ_FIRST(&ss->ss_queue)->eh_event;
 			*(int *)data = sizeof(struct fsnotify_event) +
 			    event_pathlen(event) + 1;
 		} else
 			*(int *)data = 0;
-		mtx_unlock(&ss->ss_mtx);
+		SESSION_UNLOCK(ss);
 		break;
 	default:
 		error = ENOENT;
@@ -503,10 +516,10 @@
 	revents = 0;
 
 	if (events & (POLLIN | POLLRDNORM)) {
-		mtx_lock(&ss->ss_mtx);
+		SESSION_LOCK(ss);
 		if (!TAILQ_EMPTY(&ss->ss_queue))
 			revents = (events & (POLLIN | POLLRDNORM));
-		mtx_unlock(&ss->ss_mtx);
+		SESSION_UNLOCK(ss);
 	}
 
 	if (revents == 0)
@@ -531,23 +544,70 @@
 		vdropl(vp);
 		printf("node reclaim: deref vnode: node %p  vp %p\n",
 		    node, node->nd_vnode);
-		mtx_lock(&node->nd_mtx);
+		NODE_LOCK(node);
 		node->nd_vnode = NULL;
-		mtx_unlock(&node->nd_mtx);
+		NODE_UNLOCK(node);
 		node_drop(node);
 	} else
 		VI_UNLOCK(vp);
 }
 
+static void
+hook_close(struct vop_close_args *ap)
+{
+	struct fnnode *node;
+	int cookie = 0;
+
+	node = node_lookup(ap->a_vp);
+	if (node != NULL) {
+		if ((node->nd_flags & NODE_ISDIR) == 0)
+			event_enqueue(node, NULL, &cookie, FE_CLOSE);
+		else
+			NODE_UNLOCK(node);
+	}
+}
+
+static void
+hook_inactive(struct vop_inactive_args *ap)
+{
+	struct fnnode *node;
+	int cookie = 0, mask;
+
+	node = node_lookup(ap->a_vp);
+	if (node != NULL) {
+		if ((node->nd_flags & NODE_ISDIR) == 0) {
+			mask = (node->nd_flags & NODE_CHANGED) != 0 ?
+			    FE_INACTIVE_CHANGED : FE_INACTIVE;
+			event_enqueue(node, NULL, &cookie, mask);
+			node->nd_flags &= ~NODE_CHANGED;
+		} else
+			NODE_UNLOCK(node);
+	}
+}
+
+static void
+hook_write(struct vop_write_args *ap)
+{
+	struct fnnode *node;
+
+	node = node_lookup(ap->a_vp);
+	if (node != NULL) {
+		if ((node->nd_flags & NODE_ISDIR) == 0)
+			node->nd_flags |= NODE_CHANGED;
+		NODE_UNLOCK(node);
+	}
+}
+
 static __inline int
 hook_generic_create(struct vnode *dvp, struct vnode *vp,
     struct componentname *cnp)
 {
 	struct fnnode *dirnode;
+	int cookie = 0;
 
 	dirnode = node_lookup(dvp);
 	if (dirnode != NULL)
-		enqueue_direvent(dirnode, cnp, event_nextcookie(), FE_CREATE);
+		event_enqueue(dirnode, cnp, &cookie, FE_CREATE);
 	return (0);
 }
 
@@ -556,95 +616,85 @@
     struct componentname *cnp)
 {
 	struct fnnode *dirnode, *node;
-	int cookie;
+	int cookie = 0;
 
-	cookie = event_nextcookie();
 	printf("hook_generic_remove: %s\n", cnp->cn_nameptr);
 
 	node = node_lookup(vp);
 	if (node != NULL)
-		enqueue_fileevent(node, cookie, FE_DESTROY | FE_REMOVE);
+		event_enqueue(node, NULL, &cookie, FE_DESTROY | FE_REMOVE);
 
 	dirnode = node_lookup(dvp);
 	if (dirnode != NULL)
-		enqueue_direvent(dirnode, cnp, cookie, FE_REMOVE);
+		event_enqueue(dirnode, cnp, &cookie, FE_REMOVE);
 }
 
-static int
+static void
 hook_create(struct vop_create_args *ap)
 {
 	printf("hook_create: %s\n", ap->a_cnp->cn_nameptr);
 	hook_generic_create(ap->a_dvp, *ap->a_vpp, ap->a_cnp);
-	return (0);
 }
 
-static int
+static void
 hook_mkdir(struct vop_mkdir_args *ap)
 {
 	printf("hook_mkdir: %s\n", ap->a_cnp->cn_nameptr);
 	hook_generic_create(ap->a_dvp, *ap->a_vpp, ap->a_cnp);
-	return (0);
 }
 
-static int
+static void
 hook_link(struct vop_link_args *ap)
 {
 	printf("hook_link: %s\n", ap->a_cnp->cn_nameptr);
 	hook_generic_create(ap->a_tdvp, ap->a_vp, ap->a_cnp);
-	return (0);
 }
 
-static int
+static void
 hook_symlink(struct vop_symlink_args *ap)
 {
 	printf("hook_symlink: %s\n", ap->a_cnp->cn_nameptr);
 	hook_generic_create(ap->a_dvp, *ap->a_vpp, ap->a_cnp);
-	return (0);
 }
 
-static int
+static void
 hook_remove(struct vop_remove_args *ap)
 {
 	hook_generic_remove(ap->a_dvp, ap->a_vp, ap->a_cnp);
-	return (0);
 }
 
-static int
+static void
 hook_rmdir(struct vop_rmdir_args *ap)
 {
 	hook_generic_remove(ap->a_dvp, ap->a_vp, ap->a_cnp);
-	return (0);
 }
 
-static int
+static void
 hook_rename(struct vop_rename_args *ap)
 {
 	struct fnnode *fdirnode, *fnode, *tdirnode, *tnode;
-	int cookie;
+	int cookie = 0;
 
-	cookie = event_nextcookie();
 	if (ap->a_tvp != NULL) {
 		tnode = node_lookupex(ap->a_tvp, NULL, 0);
 		if (tnode != NULL) {
-			enqueue_fileevent(tnode, cookie,
+			event_enqueue(tnode, NULL, &cookie,
 			    FE_DESTROY | FE_REMOVE);
 		}
 	}
 	fnode = node_lookupex(ap->a_fvp, NULL, 0);
 	if (fnode != NULL) {
-		mtx_unlock(&fnode->nd_mtx);
+		NODE_UNLOCK(fnode);
 		/* 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);
+		event_enqueue(fdirnode, ap->a_fcnp, &cookie, FE_RENAME_FROM);
 	tdirnode = node_lookupex(ap->a_tdvp, NULL, 0);
 	if (tdirnode != NULL)
-		enqueue_direvent(tdirnode, ap->a_tcnp, cookie, FE_RENAME_TO);
-
-	return (0);
+		event_enqueue(tdirnode, ap->a_tcnp, &cookie, FE_RENAME_TO);
 }
 
 static int
@@ -690,13 +740,13 @@
 	mtx_assert(&ss->ss_mtx, MA_OWNED);
 
 	if (node != NULL) {
-		mtx_lock(&node->nd_mtx);
+		NODE_LOCK(node);
 		if (watch->wt_node != NULL) {
 			MPASS(watch->wt_node == node);
 			watch_detachnode(watch);
 			node_watchdrop(node);
 		} else
-			mtx_unlock(&node->nd_mtx);
+			NODE_UNLOCK(node);
 	}
 
 	TAILQ_REMOVE(&ss->ss_watchlist, watch, wt_sessionentry);
@@ -733,10 +783,10 @@
 	if (TAILQ_EMPTY(&node->nd_watchlist)) {
 		MPASS(node->nd_watchcount == 0);
 		node->nd_supermask = 0;
-		mtx_unlock(&node->nd_mtx);
+		NODE_UNLOCK(node);
 		node_drop(node);
 	} else
-		mtx_unlock(&node->nd_mtx);
+		NODE_UNLOCK(node);
 }
 
 static void
@@ -744,19 +794,19 @@
 {
 	mtx_assert(&node->nd_mtx, MA_NOTOWNED);
 	if (refcount_release(&node->nd_refcnt) != 0) {
+		printf("node_drop: free node %p\n", node);
 		MPASS(node->nd_vnode == NULL);
 		KASSERT(node->nd_watchcount == 0 && 
 		    TAILQ_EMPTY(&node->nd_watchlist),
 		    ("Invalid watch count: %d", node->nd_watchcount));
 		if (node->nd_ino != 0) {
-			mtx_lock(&fnnode_hashmtx);
+			INOHASH_LOCK();
 			LIST_REMOVE(node, nd_hashentry);
-			mtx_unlock(&fnnode_hashmtx);
+			INOHASH_UNLOCK();
 		}
 		mtx_destroy(&node->nd_mtx);
 		free(node->nd_pathfree, M_TEMP);
 		free(node, M_FSNOTIFY);
-		printf("node free: %p\n", node);
 	}
 }
 
@@ -786,17 +836,19 @@
 
 	node->nd_ino = ino;
 
-	mtx_lock(&node->nd_mtx);
+	NODE_LOCK(node);
 
-	mtx_lock(&fnnode_hashmtx);
+	INOHASH_LOCK();
 	LIST_INSERT_HEAD(node_inohashhead(vp->v_mount, ino),
 	    node, nd_hashentry);
-	mtx_unlock(&fnnode_hashmtx);
+	INOHASH_UNLOCK();
 
 	VI_LOCK(vp);
 	vholdl(vp);
 	node->nd_vnode = vp;
 	vp->v_fnnode = node;
+	if (vp->v_type == VDIR)
+		node->nd_flags |= NODE_ISDIR;
 	VI_UNLOCK(vp);
 
 	return (node);
@@ -817,7 +869,7 @@
 	if (watch != NULL)
 		node_watchdrop(node);
 	else
-		mtx_unlock(&node->nd_mtx);
+		NODE_UNLOCK(node);
 }
 
 static int
@@ -849,7 +901,7 @@
 node_lookupex(struct vnode *vp, ino_t *inop, int flags)
 {
 	struct fnnode *node, *rv;
-	ino_t ino;
+	ino_t inotmp;
 	int error;
 
 	rv = NULL;
@@ -861,10 +913,11 @@
 		if ((flags & LOOKUP_IGNINVAL) == 0)
 			goto done;
 	} else if (node != NULL) {
-		mtx_lock(&node->nd_mtx);
+		NODE_LOCK(node);
 		MPASS(node->nd_vnode == vp);
-		if (node->nd_watchcount == 0) {
-			mtx_unlock(&node->nd_mtx);
+		if (node->nd_watchcount == 0 &&
+		    (flags & LOOKUP_IGNINVAL) == 0) {
+			NODE_UNLOCK(node);
 			node = NULL;
 		}
 		goto done;
@@ -872,19 +925,19 @@
 
 	node = NULL;
 	if (inop == NULL)
-		inop = &ino;
+		inop = &inotmp;
 	error = node_getino(vp, inop, flags & LOOKUP_VPLOCKED);
 	if (error != 0)
 		goto done;
 
-	mtx_lock(&fnnode_hashmtx);
+	INOHASH_LOCK();
 	LIST_FOREACH(node,
 	    node_inohashhead(vp->v_mount, *inop), nd_hashentry) {
 		if (node->nd_ino != *inop ||
 		    node->nd_mount != vp->v_mount)
 			continue;
-		mtx_lock(&node->nd_mtx);
-		mtx_unlock(&fnnode_hashmtx);
+		NODE_LOCK(node);
+		INOHASH_UNLOCK();
 		VI_LOCK(vp);
 		if (!NODE_ISVALID(vp->v_fnnode)) {
 			MPASS(node->nd_vnode == NULL);
@@ -896,13 +949,14 @@
 		} else
 			MPASS(vp->v_fnnode == node && vp == node->nd_vnode);
 		VI_UNLOCK(vp);
-		if (node->nd_watchcount == 0) {
-			mtx_unlock(&node->nd_mtx);
+		if (node->nd_watchcount == 0 &&
+		    (flags & LOOKUP_IGNINVAL) == 0) {
+			NODE_UNLOCK(node);
 			node = NULL;
 		}
 		goto done;
 	}
-	mtx_unlock(&fnnode_hashmtx);
+	INOHASH_UNLOCK();
 
 	VI_LOCK(vp);
 	if (!NODE_ISVALID(vp->v_fnnode))
@@ -933,7 +987,7 @@
 	char *npath, *npathfree;
 	int vfslocked, error;
 
-	/* Should be executed in *single* process_queue thread */
+	/* Should be executed in *single* fsnotify_daemon thread */
 	vp = node->nd_vnode;
 	printf("node_updatepath: node %p  vp %p  %s\n",
 	    node, vp, node->nd_path);
@@ -944,7 +998,7 @@
 	pathfree = node->nd_pathfree;
 	npath = npathfree = NULL;
 	vhold(vp);
-	mtx_unlock(&node->nd_mtx);
+	NODE_UNLOCK(node);
 
 	NDINIT_ATVP(&ni, LOOKUP, MPSAFE | FOLLOW, UIO_SYSSPACE, path, rootvnode,
 	    curthread);
@@ -967,7 +1021,7 @@
 		error = ENOENT;
 	}
 	vdrop(vp);
-	mtx_lock(&node->nd_mtx);
+	NODE_LOCK(node);
 	if (path != node->nd_path) {
 		/* Lookup race */
 		free(pathfree, M_TEMP);
@@ -993,7 +1047,6 @@
 
 	MPASS(handle_maxsize > 0);
 	MPASS(mask != 0);
-	MPASS(namelen > 0);
 
 	event = malloc(sizeof(struct fnevent) +
 	    (sizeof(struct fneventhandle) * handle_maxsize),
@@ -1004,8 +1057,12 @@
 	event->ev_cookie = cookie;
 	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';
+	if (name != NULL) {
+		MPASS((node->nd_flags & NODE_ISDIR) != 0);
+		memcpy(event->ev_pathfree + event->ev_pathpos, name, namelen);
+	} else
+		MPASS((node->nd_flags & NODE_ISDIR) == 0);
 	printf("event alloc: %p\n", event);
 
 	return (event);
@@ -1042,9 +1099,9 @@
 
 	node = eh->eh_event->ev_node;
 
-	mtx_lock(&node->nd_mtx);
+	NODE_LOCK(node);
 	handlecount = --eh->eh_event->ev_handlecount;
-	mtx_unlock(&node->nd_mtx);
+	NODE_UNLOCK(node);
 	MPASS(handlecount >= 0);
 	if (handlecount == 0)
 		event_free(eh->eh_event);
@@ -1058,9 +1115,10 @@
 	pos = event->ev_pathpos;
 	len = node->nd_pathlen;
 	MPASS(len > 0 && node->nd_path[len - 1] != '/');
-	MPASS(MAXPATHLEN - pos < len + 1);
+	MPASS(pos >= len + 1);
 
-	event->ev_pathfree[--pos] = '/';
+	if (event_pathlen(event) != 0)
+		event->ev_pathfree[--pos] = '/';
 	pos -= len;
 	memcpy(event->ev_pathfree + pos, node->nd_path, len);
 
@@ -1079,13 +1137,58 @@
 	return (r);
 }
 
+static void
+event_enqueue(struct fnnode *node, struct componentname *cnp, int *cookiep,
+    int mask)
+{
+	struct fnevent *event;
+	char *nameptr;
+	int namelen, supermask, watchcount;
+
+	printf("event_enqueue: %s %x\n",
+	    cnp != NULL ? cnp->cn_nameptr : NULL, mask);
+
+	mtx_assert(&node->nd_mtx, MA_OWNED);
+	watchcount = node->nd_watchcount;
+	supermask = node->nd_supermask & mask;
+	node_hold(node);
+	NODE_UNLOCK(node);
+
+	if (supermask == 0) {
+		node_drop(node);
+		return;
+	}
+
+	KASSERT(watchcount > 0, ("No watches found"));
+
+	if (cnp != NULL) {
+		nameptr = cnp->cn_nameptr;
+		namelen = cnp->cn_namelen;
+	} else {
+		nameptr = NULL;
+		namelen = 0;
+	}
+
+	if (*cookiep == 0)
+		*cookiep = event_nextcookie();
+	event = event_alloc(node, nameptr, namelen, watchcount + 1, mask,
+	    *cookiep);
+
+	QUEUE_LOCK();
+	TAILQ_INSERT_TAIL(&fsnotify_queue, event, ev_queueentry);
+	QUEUE_UNLOCK();
+
+	wakeup(&fsnotify_queue);
+}
+
 static int
 session_addwatch(struct fnsession *ss, struct fnnode *node, int mask,
     struct fnwatch **watchpp)
 {
 	struct fnwatch *watch;
 
-	printf("session_addwatch: %s: session=%p\n", node->nd_path, ss);
+	printf("session_addwatch: %s: node %p  session %p\n",
+	    node->nd_path, node, ss);
 
 	watch = malloc(sizeof(struct fnwatch), M_FSNOTIFY, M_WAITOK | M_ZERO);
 	printf("watch alloc: %p\n", watch);
@@ -1095,15 +1198,15 @@
 	watch->wt_session = ss;
 	watch->wt_node = node;
 
-	mtx_lock(&ss->ss_mtx);
+	SESSION_LOCK(ss);
 	TAILQ_INSERT_TAIL(&ss->ss_watchlist, watch, wt_sessionentry);
-	mtx_unlock(&ss->ss_mtx);
+	SESSION_UNLOCK(ss);
 
-	mtx_lock(&node->nd_mtx);
+	NODE_LOCK(node);
 	TAILQ_INSERT_TAIL(&node->nd_watchlist, watch, wt_nodeentry);
 	node->nd_watchcount++;
 	node->nd_supermask |= watch->wt_mask;
-	mtx_unlock(&node->nd_mtx);
+	NODE_UNLOCK(node);
 
 	if (watchpp != NULL)
 		*watchpp = watch;
@@ -1117,7 +1220,7 @@
 	struct fnwatch *watch;
 	struct fneventhandle *eh, *ehtmp;
 
-	mtx_lock(&ss->ss_mtx);
+	SESSION_LOCK(ss);
 	TAILQ_FOREACH(watch, &ss->ss_watchlist, wt_sessionentry) {
 		if (watch->wt_wd != wd)
 			continue;
@@ -1129,7 +1232,7 @@
   		watch_free(watch);
 		break;
 	}
-	mtx_unlock(&ss->ss_mtx);
+	SESSION_UNLOCK(ss);
 	if (watch == NULL)
 		return (ENOENT);
 	return (0);
@@ -1156,16 +1259,16 @@
 		return;
 	}
 
-	mtx_lock(&ss->ss_mtx);
+	SESSION_LOCK(ss);
 	TAILQ_INSERT_TAIL(&ss->ss_queue, eh, eh_queueentry);
 	ss->ss_queuesize++;
-	mtx_unlock(&ss->ss_mtx);
+	SESSION_UNLOCK(ss);
 	cv_broadcast(&ss->ss_queuecv);
 	selwakeup(&ss->ss_queuepoll);
 }
 
 static void
-process_queue(void *context)
+fsnotify_daemon(void *context)
 {
 	struct fnnode *node;
 	struct fnwatch *watch;
@@ -1186,7 +1289,7 @@
 	}
 	FILEDESC_XUNLOCK(fsnotify_proc->p_fd);
 
-	mtx_lock(&fsnotify_queue_mtx);
+	QUEUE_LOCK();
 	while (1) {
 		if (fsnotify_proc == NULL)
 			break;
@@ -1197,11 +1300,11 @@
 		}
 		event = TAILQ_FIRST(&fsnotify_queue);
 		TAILQ_REMOVE(&fsnotify_queue, event, ev_queueentry);
-		mtx_unlock(&fsnotify_queue_mtx);
+		QUEUE_UNLOCK();
 
 		node = event->ev_node;
 
-		mtx_lock(&node->nd_mtx);
+		NODE_LOCK(node);
 		TAILQ_FOREACH(watch, &node->nd_watchlist, wt_nodeentry) {
 			if ((watch->wt_mask & event->ev_mask) == 0)
 				continue;
@@ -1210,7 +1313,7 @@
 				    event->ev_handlemaxsize);
 				break;
 			}
-			printf("process_queue: handle event %p in session %p\n",
+			printf("fsnotify: handle event %p in session %p\n",
 			    event, watch->wt_session);
 			eh = &event->ev_handlebuf[event->ev_handlecount++];
 			eh->eh_event = event;
@@ -1219,7 +1322,7 @@
 		handle_count = event->ev_handlecount;
 		if (handle_count == 0) {
 			node->nd_supermask &= ~event->ev_mask;
-			mtx_unlock(&node->nd_mtx);
+			NODE_UNLOCK(node);
 			event_free(event);
 			continue;
 		}
@@ -1233,54 +1336,17 @@
 		if (event->ev_mask & FE_DESTROY)
 			node_detachallwatches(node);
 		else
-			mtx_unlock(&node->nd_mtx);
+			NODE_UNLOCK(node);
 
 		for (i = 0; i < handle_count; i++)
 			session_enqueue(&event->ev_handlebuf[i]);
 
-		mtx_lock(&fsnotify_queue_mtx);
+		QUEUE_LOCK();
 	}
 
 	wakeup_one(&fsnotify_queue);
-	mtx_unlock(&fsnotify_queue_mtx);
+	QUEUE_UNLOCK();
 
 	kproc_exit(0);
 }
 
-static void
-enqueue_direvent(struct fnnode *dirnode, struct componentname *cnp, int cookie, int mask)
-{
-	struct fnevent *event;
-	int supermask, watchcount;
-
-	printf("enqueue_direvent: %s %x\n", cnp->cn_nameptr, mask);
-
-	mtx_assert(&dirnode->nd_mtx, MA_OWNED);
-	watchcount = dirnode->nd_watchcount;
-	supermask = dirnode->nd_supermask & mask;
-	node_hold(dirnode);
-	mtx_unlock(&dirnode->nd_mtx);
-
-	if (supermask == 0) {
-		node_drop(dirnode);
-		return;
-	}
-
-	KASSERT(watchcount > 0, ("No watchers found"));
-
-	event = event_alloc(dirnode, cnp->cn_nameptr, cnp->cn_namelen,
-	    watchcount + 1, mask, cookie);
-
-	mtx_lock(&fsnotify_queue_mtx);
-	TAILQ_INSERT_TAIL(&fsnotify_queue, event, ev_queueentry);
-	mtx_unlock(&fsnotify_queue_mtx);
-
-	wakeup(&fsnotify_queue);
-}
-
-static void
-enqueue_fileevent(struct fnnode *node, int cookie, int mask)
-{
-	printf("enqueue_fileevent: %x\n", mask);
-}
-

==== //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_subr.c#4 (text+ko) ====

@@ -276,21 +276,23 @@
  * fsnotify hooks
  */
 
-void (*fsnotify_hook_reclaim)(struct vnode *vp) = NULL;
-vop_create_t *fsnotify_hook_create = NULL;
-vop_link_t *fsnotify_hook_link = NULL;
-vop_mkdir_t *fsnotify_hook_mkdir = NULL;
-vop_remove_t *fsnotify_hook_remove = NULL;
-vop_rename_t *fsnotify_hook_rename = NULL;
-vop_rmdir_t *fsnotify_hook_rmdir = NULL;
-vop_symlink_t *fsnotify_hook_symlink = NULL;
+static void fsnotify_nullop(void *);
 
-#define FSNOTIFY_FUNCPTR(f)	__CONCAT(fsnotify_hook_, f)
+struct fsnotify_ops fsnotify_nullops = {
+	.fno_close	= (fno_close_t *) fsnotify_nullop,
+	.fno_create	= (fno_create_t *) fsnotify_nullop,
+	.fno_inactive	= (fno_inactive_t *) fsnotify_nullop,
+	.fno_link	= (fno_link_t *) fsnotify_nullop,
+	.fno_mkdir	= (fno_mkdir_t *) fsnotify_nullop,
+	.fno_reclaim	= (fno_reclaim_t *) fsnotify_nullop,
+	.fno_remove	= (fno_remove_t *) fsnotify_nullop,
+	.fno_rename	= (fno_rename_t *) fsnotify_nullop,
+	.fno_rmdir	= (fno_rmdir_t *) fsnotify_nullop,
+	.fno_symlink	= (fno_symlink_t *) fsnotify_nullop,
+	.fno_write	= (fno_write_t *) fsnotify_nullop,
+};
 
-#define FSNOTIFY(f, a)	do { \
-	if (FSNOTIFY_FUNCPTR(f) != NULL) \
-		(FSNOTIFY_FUNCPTR(f))(a); \
-	} while (0)
+struct fsnotify_ops *fsnotify_curops = &fsnotify_nullops;
 
 /*
  * Macros to control when a vnode is freed and recycled.  All require
@@ -2600,8 +2602,7 @@
 	 */
 	delmntque(vp);
 	cache_purge(vp);
-	if (fsnotify_hook_reclaim != NULL)
-		fsnotify_hook_reclaim(vp);
+	fsnotify_curops->fno_reclaim(vp);
 	/*
 	 * Done with purge, reset to the standard lock and invalidate
 	 * the vnode.
@@ -3777,6 +3778,11 @@
 #endif /* 0 */
 #endif /* DEBUG_VFS_LOCKS */
 
+static void
+fsnotify_nullop(void *ap __unused)

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007160519.o6G5JeqL080259>