From owner-p4-projects@FreeBSD.ORG Fri Jul 9 10:27:44 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 40791106572C; Fri, 9 Jul 2010 10:27:43 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 67A21106566B for ; Fri, 9 Jul 2010 10:27:43 +0000 (UTC) (envelope-from ilya@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 562FE8FC19 for ; Fri, 9 Jul 2010 10:27:43 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o69ARgKC024681 for ; Fri, 9 Jul 2010 10:27:42 GMT (envelope-from ilya@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o69ARgtw024679 for perforce@freebsd.org; Fri, 9 Jul 2010 10:27:42 GMT (envelope-from ilya@FreeBSD.org) Date: Fri, 9 Jul 2010 10:27:42 GMT Message-Id: <201007091027.o69ARgtw024679@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to ilya@FreeBSD.org using -f From: Ilya Putsikau To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 180684 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Jul 2010 10:27:44 -0000 http://p4web.freebsd.org/@@180684?ac=10 Change 180684 by ilya@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 #include #include +#include #include #include #include @@ -50,7 +51,7 @@ #include #include #include -#include +#include #include #include @@ -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