PERFORCE change 180684 for review
Ilya Putsikau
ilya at FreeBSD.org
Fri Jul 9 10:27:44 UTC 2010
http://p4web.freebsd.org/@@180684?ac=10
Change 180684 by ilya at ilya_triton on 2010/07/09 10:27:38
Use kernel process instead of taskqueue to process events
Set root and current firectories for fsnotify process
Lookup and check global path only (not chroot)
Hold vnode reference to prevent vnode reuse
Return inode number in lookupex if node already exists
Affected files ...
.. //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_notify.c#6 edit
Differences ...
==== //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_notify.c#6 (text+ko) ====
@@ -39,6 +39,7 @@
#include <sys/filio.h>
#include <sys/hash.h>
#include <sys/kernel.h>
+#include <sys/kthread.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
@@ -50,7 +51,7 @@
#include <sys/queue.h>
#include <sys/refcount.h>
#include <sys/systm.h>
-#include <sys/taskqueue.h>
+#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/fsnotify.h>
@@ -120,8 +121,7 @@
static TAILQ_HEAD(, fnevent) fsnotify_queue =
TAILQ_HEAD_INITIALIZER(fsnotify_queue);
static struct mtx fsnotify_queue_mtx;
-static struct task fsnotify_task;
-static struct taskqueue *fsnotify_tq;
+static struct proc *fsnotify_proc;
static struct fnnode_hashhead *fnnode_inohashtbl;
static struct mtx fnnode_hashmtx;
@@ -150,7 +150,7 @@
static vop_rmdir_t hook_rmdir;
static vop_symlink_t hook_symlink;
-static void process_queue(void *context, int pending);
+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);
@@ -181,6 +181,7 @@
{
struct fnnode_hashhead *hashhead;
struct fnnode *node;
+ struct proc *p;
int i;
int error = 0;
@@ -201,16 +202,19 @@
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,
+ RFHIGHPID, 0, "fsnotify");
+ if (error != 0) {
+ mtx_destroy(&fsnotify_queue_mtx);
+ mtx_destroy(&fnnode_hashmtx);
+ printf("cannot create fsnotify process\n");
+ return (error);
+ }
+
i = MAX(desiredvnodes / 32, 16);
fnnode_inohashtbl = hashinit(i, M_FSNOTIFYHASH,
&fnnode_hashmask);
- TASK_INIT(&fsnotify_task, 0, process_queue, NULL);
- fsnotify_tq = taskqueue_create("fsnotify", M_WAITOK,
- taskqueue_thread_enqueue, &fsnotify_tq);
- taskqueue_start_threads(&fsnotify_tq, 1, PWAIT,
- "fsnotify taskq");
-
/* FIXME: correct device permissions */
fsnotify_dev = make_dev(&fsnotify_cdevsw, 0, UID_ROOT,
GID_WHEEL, 0666, "fsnotify");
@@ -234,19 +238,29 @@
fsnotify_hook_rmdir = NULL;
fsnotify_hook_symlink = NULL;
destroy_dev(fsnotify_dev);
- taskqueue_drain(fsnotify_tq, &fsnotify_task);
- taskqueue_free(fsnotify_tq);
+
+ mtx_lock(&fsnotify_queue_mtx);
+ if ((p = fsnotify_proc) != NULL) {
+ fsnotify_proc = NULL;
+ wakeup_one(&fsnotify_queue);
+ PROC_LOCK(p);
+ mtx_unlock(&fsnotify_queue_mtx);
+ msleep(p, &p->p_mtx, PWAIT, "fsnotify_destroy", 0);
+ PROC_UNLOCK(p);
+ } else
+ mtx_unlock(&fsnotify_queue_mtx);
+
for (i = 0; i <= fnnode_hashmask; i++) {
hashhead = &fnnode_inohashtbl[i];
while (!LIST_EMPTY(hashhead)) {
node = LIST_FIRST(hashhead);
mtx_lock(&node->nd_mtx);
- if (node->nd_vnode != NULL) {
+ if (NODE_ISVALID(node->nd_vnode)) {
VI_LOCK(node->nd_vnode);
node->nd_vnode->v_fnnode = NULL;
printf("fsnotify unload: deref vp: node %p vp %p\n",
node, node->nd_vnode);
- VI_UNLOCK(node->nd_vnode);
+ vdropl(node->nd_vnode);
node->nd_vnode = NULL;
mtx_unlock(&node->nd_mtx);
node_drop(node);
@@ -432,13 +446,14 @@
if (vp == NULL)
return (EBADF);
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ ino = 0;
node = node_lookupex(vp, &ino, LOOKUP_IGNINVAL);
if (node != NULL) {
node_watchhold(node);
mtx_unlock(&node->nd_mtx);
VFS_UNLOCK_GIANT(vfslocked);
} else {
- error = vn_fullpath(td, vp, &path, &pathfree);
+ error = vn_fullpath_global(td, vp, &path, &pathfree);
VFS_UNLOCK_GIANT(vfslocked);
if (error != 0)
return (error);
@@ -511,16 +526,17 @@
VI_LOCK(vp);
node = vp->v_fnnode;
vp->v_fnnode = NULL;
- VI_UNLOCK(vp);
if (NODE_ISVALID(node)) {
+ vdropl(vp);
printf("node reclaim: deref vnode: node %p vp %p\n",
node, node->nd_vnode);
mtx_lock(&node->nd_mtx);
node->nd_vnode = NULL;
mtx_unlock(&node->nd_mtx);
node_drop(node);
- }
+ } else
+ VI_UNLOCK(vp);
}
static __inline int
@@ -762,7 +778,7 @@
MPASS(ino != 0);
node = malloc(sizeof(struct fnnode), M_FSNOTIFY, M_WAITOK | M_ZERO);
- printf("node alloc: node %p vp %p\n", node, vp);
+ printf("node alloc: node %p vp %p ino %d\n", node, vp, ino);
refcount_init(&node->nd_refcnt, 2);
mtx_init(&node->nd_mtx, "fsnotify_node", NULL, MTX_DEF);
@@ -778,6 +794,7 @@
mtx_unlock(&fnnode_hashmtx);
VI_LOCK(vp);
+ vholdl(vp);
node->nd_vnode = vp;
vp->v_fnnode = node;
VI_UNLOCK(vp);
@@ -873,6 +890,7 @@
MPASS(node->nd_vnode == NULL);
node_hold(node);
printf("node lookup: ref vnode: node %p vp %p\n", node, vp);
+ vholdl(vp);
vp->v_fnnode = node;
node->nd_vnode = vp;
} else
@@ -892,8 +910,9 @@
VI_UNLOCK(vp);
done:
- if (node != NULL)
- mtx_assert(&node->nd_mtx, MA_OWNED);
+ if (node != NULL && inop != NULL)
+ *inop = node->nd_ino;
+
return (node);
}
@@ -914,10 +933,7 @@
char *npath, *npathfree;
int vfslocked, error;
- /*
- * TODO: has races. should be executed only in *single* process_queue
- * thread
- */
+ /* Should be executed in *single* process_queue thread */
vp = node->nd_vnode;
printf("node_updatepath: node %p vp %p %s\n",
node, vp, node->nd_path);
@@ -930,7 +946,8 @@
vhold(vp);
mtx_unlock(&node->nd_mtx);
- NDINIT(&ni, LOOKUP, MPSAFE | FOLLOW, UIO_SYSSPACE, path, curthread);
+ NDINIT_ATVP(&ni, LOOKUP, MPSAFE | FOLLOW, UIO_SYSSPACE, path, rootvnode,
+ curthread);
error = namei(&ni);
vfslocked = NDHASGIANT(&ni);
if (error == 0) {
@@ -941,9 +958,8 @@
}
NDFREE(&ni, 0);
}
- if (error != 0) {
- error = vn_fullpath(curthread, vp, &npath, &npathfree);
- }
+ if (error != 0)
+ error = vn_fullpath_global(curthread, vp, &npath, &npathfree);
VFS_UNLOCK_GIANT(vfslocked);
if ((vp->v_iflag & VI_DOOMED) != 0) {
@@ -1149,7 +1165,7 @@
}
static void
-process_queue(void *context, int pending)
+process_queue(void *context)
{
struct fnnode *node;
struct fnwatch *watch;
@@ -1157,11 +1173,27 @@
struct fneventhandle *eh;
int i, handle_count;
+ MPASS(fsnotify_proc != NULL && fsnotify_proc == curthread->td_proc);
+
+ FILEDESC_XLOCK(fsnotify_proc->p_fd);
+ if (fsnotify_proc->p_fd->fd_cdir == NULL) {
+ fsnotify_proc->p_fd->fd_cdir = rootvnode;
+ vref(rootvnode);
+ }
+ if (fsnotify_proc->p_fd->fd_rdir == NULL) {
+ fsnotify_proc->p_fd->fd_rdir = rootvnode;
+ vref(rootvnode);
+ }
+ FILEDESC_XUNLOCK(fsnotify_proc->p_fd);
+
+ mtx_lock(&fsnotify_queue_mtx);
while (1) {
- mtx_lock(&fsnotify_queue_mtx);
+ if (fsnotify_proc == NULL)
+ break;
if (TAILQ_EMPTY(&fsnotify_queue)) {
- mtx_unlock(&fsnotify_queue_mtx);
- break;
+ msleep(&fsnotify_queue, &fsnotify_queue_mtx, PWAIT,
+ "wait", 0);
+ continue;
}
event = TAILQ_FIRST(&fsnotify_queue);
TAILQ_REMOVE(&fsnotify_queue, event, ev_queueentry);
@@ -1191,8 +1223,7 @@
event_free(event);
continue;
}
- /* FIXME */
- if (0 && node->nd_vnode != NULL)
+ if (node->nd_vnode != NULL)
node_updatepath(node);
else
printf("fsnotify: vnode not found, reusing cached path: %s\n",
@@ -1206,7 +1237,14 @@
for (i = 0; i < handle_count; i++)
session_enqueue(&event->ev_handlebuf[i]);
+
+ mtx_lock(&fsnotify_queue_mtx);
}
+
+ wakeup_one(&fsnotify_queue);
+ mtx_unlock(&fsnotify_queue_mtx);
+
+ kproc_exit(0);
}
static void
@@ -1237,7 +1275,7 @@
TAILQ_INSERT_TAIL(&fsnotify_queue, event, ev_queueentry);
mtx_unlock(&fsnotify_queue_mtx);
- taskqueue_enqueue(fsnotify_tq, &fsnotify_task);
+ wakeup(&fsnotify_queue);
}
static void
More information about the p4-projects
mailing list