svn commit: r201633 - in stable/7/sys: cddl/compat/opensolaris/kern cddl/compat/opensolaris/sys cddl/contrib/opensolaris/common/nvpair cddl/contrib/opensolaris/uts/common/fs cddl/contrib/opensolari...

Alexander Leidinger netchild at FreeBSD.org
Wed Jan 6 08:18:50 UTC 2010


Author: netchild
Date: Wed Jan  6 08:18:49 2010
New Revision: 201633
URL: http://svn.freebsd.org/changeset/base/201633

Log:
  MFC several ZFS related commits:
   - taskq changes
   - fixes for race conditions
   - locking fixes
   - bug fixes
   - ...
  
  r185310:
  ---snip---
      Remove unused variable.
  
      Found with:	Coverity Prevent(tm)
      CID:	3669,3671
  ---snip---
  
  r185319:
  ---snip---
      Fix locking (file descriptor table and Giant around VFS).
  
      Most submitted by:	kib
      Reviewed by:	kib
  ---snip---
  
  r192689:
  ---snip---
      Fix comment.
  ---snip---
  
  r193110:
  ---snip---
  	work around snapshot shutdown race reported by Henri Hennebert
  ---snip---
  
  r193440:
  ---snip---
      Support shared vnode locks for write operations when the offset is
      provided on filesystems that support it.  This really improves mysql
      + innodb performance on ZFS.
  
      Reviewed by:	jhb, kmacy, jeffr
  ---snip---
  ATTENTION: this commit to releng7 does not allow shared vnode locks
  (there are some VFS changes needed before it can be enabled), it only
  provides the infrastructure and serves mostly as a diff reduction in
  the ZFS code.
  A comment has been added to the locking part to explain why no shared
  locks are used.
  
  r195627:
  ---snip---
      In nvpair_native_embedded_array(), meaningless pointers are zeroed.
      The programmer was aware that alignment was not guaranteed in the
      packed structure and used bzero() to NULL out the pointers.
      However, on ia64, the compiler is quite agressive in finding ILP
      and calls to bzero() are often replaced by simple assignments (i.e.
      stores). Especially when the width or size in question corresponds
      with a store instruction (i.e. st1, st2, st4 or st8).
  
      The problem here is not a compiler bug. The address of the memory
      to zero-out was given by '&packed->nvl_priv' and given the type of
      the 'packed' pointer the compiler could assume proper alignment for
      the replacement of bzero() with an 8-byte wide store to be valid.
      The problem is with the programmer. The programmer knew that the
      address did not have the alignment guarantees needed for a regular
      assignment, but failed to inform the compiler of that fact. In
      fact, the programmer told the compiler the opposite: alignment is
      guaranteed.
  
      The fix is to avoid using a pointer of type "nvlist_t *" and
      instead use a "char *" pointer as the basis for calculating the
      address. This tells the compiler that only 1-byte alignment can
      be assumed and the compiler will either keep the bzero() call
      or instead replace it with a sequence of byte-wise stores. Both
      are valid.
  ---snip---
  
  r195822:
  ---snip---
      Fix extattr_list_file(2) on ZFS in case the attribute directory
      doesn't exist and user doesn't have write access to the file.
      Without this fix, it returns bogus value instead of 0.  For some
      reason this didn't manifest on my kernel compiled with -O0.
  
      PR:			kern/136601
      Submitted by:	Jaakko Heinonen <jh at saunalahti dot fi>
  ---snip---
  
  r195909
  ---snip---
      We don't support ephemeral IDs in FreeBSD and without this fix ZFS can
      panic when in zfs_fuid_create_cred() when userid is negative. It is
      converted to unsigned value which makes IS_EPHEMERAL() macro to
      incorrectly report that this is ephemeral ID. The most reasonable
      solution for now is to always report that the given ID is not ephemeral.
  
      PR:			kern/132337
      Submitted by:	Matthew West <freebsd at r.zeeb.org>
      Tested by:		Thomas Backman <serenity at exscape.org>, Michael Reifenberger <mike at reifenberger.com>
  ---snip---
  
  r196291:
  ---snip---
      - Fix a race where /dev/zfs control device is created before ZFS is fully
        initialized. Also destroy /dev/zfs before doing other deinitializations.
      - Initialization through taskq is no longer needed and there is a race
        where one of the zpool/zfs command loads zfs.ko and tries to do some work
        immediately, but /dev/zfs is not there yet.
  
      Reported by:	pav
  ---snip---
  
  r196269:
  ---snip---
      Fix misalignment in nvpair_native_embedded() caused by the compiler
      replacing the bzero(). See also revision 195627, which fixed the
      misalignment in nvpair_native_embedded_array().
  ---snip---
  
  r196295:
  ---snip---
      Remove OpenSolaris taskq port (it performs very poorly in our kernel) and
      replace it with wrappers around our taskqueue(9).
      To make it possible implement taskqueue_member() function which returns 1
      if the given thread was created by the given taskqueue.
  ---snip---
  The taskqueue_member() function is different due to kproc/kthread changes
  in releng8 and head, the function was...
  Revieved by:	jhb
  
  r196297:
  ---snip---
      Fix panic in zfs recv code. The last vnode (mountpoint's vnode) can have
      0 usecount.
  
      Reported by:	Thomas Backman <serenity at exscape.org>
  ---snip---
  
  r196299:
  ---snip---
      - We need to recycle vnode instead of freeing znode.
  
      Submitted by:	avg
  
      - Add missing vnode interlock unlock.
      - Remove redundant znode locking.
  ---snip---
  
  r196301:
  ---snip---
      If z_buf is NULL, we should free znode immediately.
  
      Noticed by:	avg
  ---snip---
  
  r196307:
  ---snip---
      Manage asynchronous vnode release just like Solaris.
  
      Discussed with:	kmacy
  ---snip---

Added:
  stable/7/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c
     - copied unchanged from r196295, head/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c
  stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/taskq.h
     - copied unchanged from r196295, head/sys/cddl/contrib/opensolaris/uts/common/sys/taskq.h
Deleted:
  stable/7/sys/cddl/compat/opensolaris/sys/taskq.h
  stable/7/sys/cddl/compat/opensolaris/sys/taskq_impl.h
  stable/7/sys/cddl/contrib/opensolaris/uts/common/os/taskq.c
Modified:
  stable/7/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c
  stable/7/sys/cddl/compat/opensolaris/sys/vnode.h
  stable/7/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
  stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
  stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
  stable/7/sys/cddl/dev/cyclic/cyclic.c
  stable/7/sys/cddl/dev/dtrace/i386/dtrace_subr.c
  stable/7/sys/kern/subr_taskqueue.c
  stable/7/sys/kern/vfs_vnops.c
  stable/7/sys/modules/zfs/Makefile
  stable/7/sys/sys/mount.h
  stable/7/sys/sys/taskqueue.h
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c
==============================================================================
--- stable/7/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/compat/opensolaris/kern/opensolaris_kobj.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -67,17 +67,25 @@ static void *
 kobj_open_file_vnode(const char *file)
 {
 	struct thread *td = curthread;
+	struct filedesc *fd;
 	struct nameidata nd;
 	int error, flags;
 
-	if (td->td_proc->p_fd->fd_rdir == NULL)
-		td->td_proc->p_fd->fd_rdir = rootvnode;
-	if (td->td_proc->p_fd->fd_cdir == NULL)
-		td->td_proc->p_fd->fd_cdir = rootvnode;
+	fd = td->td_proc->p_fd;
+	FILEDESC_XLOCK(fd);
+	if (fd->fd_rdir == NULL) {
+		fd->fd_rdir = rootvnode;
+		vref(fd->fd_rdir);
+	}
+	if (fd->fd_cdir == NULL) {
+		fd->fd_cdir = rootvnode;
+		vref(fd->fd_cdir);
+	}
+	FILEDESC_XUNLOCK(fd);
 
 	flags = FREAD;
-	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, file, td);
-	error = vn_open_cred(&nd, &flags, 0, td->td_ucred, NULL);
+	NDINIT(&nd, LOOKUP, MPSAFE, UIO_SYSSPACE, file, td);
+	error = vn_open_cred(&nd, &flags, O_NOFOLLOW, td->td_ucred, NULL);
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	if (error != 0)
 		return (NULL);
@@ -121,13 +129,15 @@ kobj_get_filesize_vnode(struct _buf *fil
 	struct vnode *vp = file->ptr;
 	struct thread *td = curthread;
 	struct vattr va;
-	int error;
+	int error, vfslocked;
 
+	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 	vn_lock(vp, LK_SHARED | LK_RETRY, td);
 	error = VOP_GETATTR(vp, &va, td->td_ucred, td);
 	VOP_UNLOCK(vp, 0, td);
 	if (error == 0)
 		*size = (uint64_t)va.va_size;
+	VFS_UNLOCK_GIANT(vfslocked);
 	return (error);
 }
 
@@ -160,7 +170,7 @@ kobj_read_file_vnode(struct _buf *file, 
 	struct thread *td = curthread;
 	struct uio auio;
 	struct iovec aiov;
-	int error;
+	int error, vfslocked;
 
 	bzero(&aiov, sizeof(aiov));
 	bzero(&auio, sizeof(auio));
@@ -176,9 +186,11 @@ kobj_read_file_vnode(struct _buf *file, 
 	auio.uio_resid = size;
 	auio.uio_td = td;
 
+	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
 	vn_lock(vp, LK_SHARED | LK_RETRY, td);
 	error = VOP_READ(vp, &auio, IO_UNIT | IO_SYNC, td->td_ucred);
 	VOP_UNLOCK(vp, 0, td);
+	VFS_UNLOCK_GIANT(vfslocked);
 	return (error != 0 ? -1 : size - auio.uio_resid);
 }
 
@@ -212,9 +224,11 @@ kobj_close_file(struct _buf *file)
 	if (file->mounted) {
 		struct vnode *vp = file->ptr;
 		struct thread *td = curthread;
-		int flags = FREAD;
+		int vfslocked;
 
-		vn_close(vp, flags, td->td_ucred, td);
+		vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+		vn_close(vp, FREAD, td->td_ucred, td);
+		VFS_UNLOCK_GIANT(vfslocked);
 	}
 	kmem_free(file, sizeof(*file));
 }

Copied: stable/7/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c (from r196295, head/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/7/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c	Wed Jan  6 08:18:49 2010	(r201633, copy of r196295, head/sys/cddl/compat/opensolaris/kern/opensolaris_taskq.c)
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2009 Pawel Jakub Dawidek <pjd at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/kmem.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
+#include <sys/taskq.h>
+
+#include <vm/uma.h>
+
+static uma_zone_t taskq_zone;
+
+struct ostask {
+	struct task	ost_task;
+	task_func_t	*ost_func;
+	void		*ost_arg;
+};
+
+taskq_t *system_taskq = NULL;
+
+static void
+system_taskq_init(void *arg)
+{
+
+	system_taskq = (taskq_t *)taskqueue_thread;
+	taskq_zone = uma_zcreate("taskq_zone", sizeof(struct ostask),
+	    NULL, NULL, NULL, NULL, 0, 0);
+}
+SYSINIT(system_taskq_init, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_init, NULL);
+
+static void
+system_taskq_fini(void *arg)
+{
+
+	uma_zdestroy(taskq_zone);
+}
+SYSUNINIT(system_taskq_fini, SI_SUB_CONFIGURE, SI_ORDER_ANY, system_taskq_fini, NULL);
+
+taskq_t *
+taskq_create(const char *name, int nthreads, pri_t pri, int minalloc __unused,
+    int maxalloc __unused, uint_t flags)
+{
+	taskq_t *tq;
+
+	if ((flags & TASKQ_THREADS_CPU_PCT) != 0) {
+		/* TODO: Calculate number od threads. */
+		printf("%s: TASKQ_THREADS_CPU_PCT\n", __func__);
+	}
+
+	tq = kmem_alloc(sizeof(*tq), KM_SLEEP);
+	tq->tq_queue = taskqueue_create(name, M_WAITOK, taskqueue_thread_enqueue,
+	    &tq->tq_queue);
+	(void) taskqueue_start_threads(&tq->tq_queue, nthreads, pri, name);
+
+	return ((taskq_t *)tq);
+}
+
+void
+taskq_destroy(taskq_t *tq)
+{
+
+	taskqueue_free(tq->tq_queue);
+	kmem_free(tq, sizeof(*tq));
+}
+
+int
+taskq_member(taskq_t *tq, kthread_t *thread)
+{
+
+	return (taskqueue_member(tq->tq_queue, thread));
+}
+
+static void
+taskq_run(void *arg, int pending __unused)
+{
+	struct ostask *task = arg;
+
+	task->ost_func(task->ost_arg);
+
+	uma_zfree(taskq_zone, task);
+}
+
+taskqid_t
+taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
+{
+	struct ostask *task;
+	int mflag;
+
+	if ((flags & (TQ_SLEEP | TQ_NOQUEUE)) == TQ_SLEEP)
+		mflag = M_WAITOK;
+	else
+		mflag = M_NOWAIT;
+
+	task = uma_zalloc(taskq_zone, mflag);
+	if (task == NULL)
+		return (0);
+
+	task->ost_func = func;
+	task->ost_arg = arg;
+
+	TASK_INIT(&task->ost_task, 0, taskq_run, task);
+	taskqueue_enqueue(tq->tq_queue, &task->ost_task);
+
+	return ((taskqid_t)(void *)task);
+}

Modified: stable/7/sys/cddl/compat/opensolaris/sys/vnode.h
==============================================================================
--- stable/7/sys/cddl/compat/opensolaris/sys/vnode.h	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/compat/opensolaris/sys/vnode.h	Wed Jan  6 08:18:49 2010	(r201633)
@@ -75,7 +75,6 @@ vn_is_readonly(vnode_t *vp)
 #define	VN_HOLD(v)	vref(v)
 #define	VN_RELE(v)	vrele(v)
 #define	VN_URELE(v)	vput(v)
-#define	VN_RELE_ASYNC(v, tq)	vn_rele_async(v, tq); 
 
 #define	VOP_REALVP(vp, vpp, ct)	(*(vpp) = (vp), 0)
 

Modified: stable/7/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/common/nvpair/nvpair.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -2523,14 +2523,15 @@ nvpair_native_embedded(nvstream_t *nvs, 
 {
 	if (nvs->nvs_op == NVS_OP_ENCODE) {
 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
-		nvlist_t *packed = (void *)
+		char *packed = (void *)
 		    (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
 		/*
 		 * Null out the pointer that is meaningless in the packed
 		 * structure. The address may not be aligned, so we have
 		 * to use bzero.
 		 */
-		bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
+		bzero(packed + offsetof(nvlist_t, nvl_priv),
+		    sizeof(((nvlist_t *)NULL)->nvl_priv));
 	}
 
 	return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
@@ -2543,7 +2544,6 @@ nvpair_native_embedded_array(nvstream_t 
 		nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
 		char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
 		size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
-		nvlist_t *packed = (nvlist_t *)((uintptr_t)value + len);
 		int i;
 		/*
 		 * Null out pointers that are meaningless in the packed
@@ -2552,13 +2552,17 @@ nvpair_native_embedded_array(nvstream_t 
 		 */
 		bzero(value, len);
 
-		for (i = 0; i < NVP_NELEM(nvp); i++, packed++)
+		value += len;
+		for (i = 0; i < NVP_NELEM(nvp); i++) {
 			/*
 			 * Null out the pointer that is meaningless in the
 			 * packed structure. The address may not be aligned,
 			 * so we have to use bzero.
 			 */
-			bzero(&packed->nvl_priv, sizeof (packed->nvl_priv));
+			bzero(value + offsetof(nvlist_t, nvl_priv),
+			    sizeof(((nvlist_t *)NULL)->nvl_priv));
+			value += sizeof(nvlist_t);
+		}
 	}
 
 	return (nvs_embedded_nvl_array(nvs, nvp, NULL));

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -564,8 +564,13 @@ gfs_file_inactive(vnode_t *vp)
 	if (fp->gfs_parent == NULL || (vp->v_flag & V_XATTRDIR))
 		goto found;
 
-	dp = fp->gfs_parent->v_data;
-
+	/*
+	 * XXX cope with a FreeBSD-specific race wherein the parent's
+	 * snapshot data can be freed before the parent is
+	 */
+	if ((dp = fp->gfs_parent->v_data) == NULL)
+		return (NULL);
+		
 	/*
 	 * First, see if this vnode is cached in the parent.
 	 */

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/vnode.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,9 +36,6 @@
  * contributors.
  */
 
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -76,15 +73,12 @@ xva_getxoptattr(xvattr_t *xvap)
 	return (xoap);
 }
 
-static STAILQ_HEAD(, vnode) vn_rele_async_list;
-static struct mtx vn_rele_async_lock;
-static struct cv vn_rele_async_cv;
-static int vn_rele_list_length;
-static int vn_rele_async_thread_exit;
-
-typedef struct  {
-	struct vnode *stqe_next;
-} vnode_link_t;
+static void
+vn_rele_inactive(vnode_t *vp)
+{
+
+	vrele(vp);
+}
 
 /*
  * Like vn_rele() except if we are going to call VOP_INACTIVE() then do it
@@ -97,117 +91,16 @@ typedef struct  {
  * This is because taskqs throttle back allocation if too many are created.
  */
 void
-vn_rele_async(vnode_t *vp, taskq_t *taskq /* unused */)
+vn_rele_async(vnode_t *vp, taskq_t *taskq)
 {
-	
-	KASSERT(vp != NULL, ("vrele: null vp"));
-	VFS_ASSERT_GIANT(vp->v_mount);
+	VERIFY(vp->v_count > 0);
 	VI_LOCK(vp);
-
-	if (vp->v_usecount > 1 || ((vp->v_iflag & VI_DOINGINACT) &&
-	    vp->v_usecount == 1)) {
-		vp->v_usecount--;
-		vdropl(vp);
-		return;
-	}	
-	if (vp->v_usecount != 1) {
-#ifdef DIAGNOSTIC
-		vprint("vrele: negative ref count", vp);
-#endif
+	if (vp->v_count == 1 && !(vp->v_iflag & VI_DOINGINACT)) {
 		VI_UNLOCK(vp);
-		panic("vrele: negative ref cnt");
-	}
-	/*
-	 * We are exiting
-	 */
-	if (vn_rele_async_thread_exit != 0) {
-		vrele(vp);
+		VERIFY(taskq_dispatch((taskq_t *)taskq,
+		    (task_func_t *)vn_rele_inactive, vp, TQ_SLEEP) != 0);
 		return;
 	}
-	
-	mtx_lock(&vn_rele_async_lock);
-
-	/*  STAILQ_INSERT_TAIL 			*/
-	(*(vnode_link_t *)&vp->v_cstart).stqe_next = NULL;
-	*vn_rele_async_list.stqh_last = vp;
-	vn_rele_async_list.stqh_last =
-	    &((vnode_link_t *)&vp->v_cstart)->stqe_next;
-
-	/****************************************/
-	vn_rele_list_length++;
-	if ((vn_rele_list_length % 100) == 0)
-		cv_signal(&vn_rele_async_cv);
-	mtx_unlock(&vn_rele_async_lock);
-	VI_UNLOCK(vp);
-}
-
-static void
-vn_rele_async_init(void *arg)
-{
-
-	mtx_init(&vn_rele_async_lock, "valock", NULL, MTX_DEF);
-	STAILQ_INIT(&vn_rele_async_list);
-
-	/* cv_init(&vn_rele_async_cv, "vacv"); */
-	vn_rele_async_cv.cv_description = "vacv";
-	vn_rele_async_cv.cv_waiters = 0;
-}
-
-void
-vn_rele_async_fini(void)
-{
-
-	mtx_lock(&vn_rele_async_lock);
-	vn_rele_async_thread_exit = 1;
-	cv_signal(&vn_rele_async_cv);
-	while (vn_rele_async_thread_exit != 0)
-		cv_wait(&vn_rele_async_cv, &vn_rele_async_lock);
-	mtx_unlock(&vn_rele_async_lock);
-	mtx_destroy(&vn_rele_async_lock);
-}
-
-
-static void
-vn_rele_async_cleaner(void)
-{
-	STAILQ_HEAD(, vnode) vn_tmp_list;
-	struct vnode *curvnode;
-
-	STAILQ_INIT(&vn_tmp_list);
-	mtx_lock(&vn_rele_async_lock);
-	while (vn_rele_async_thread_exit == 0) {
-		STAILQ_CONCAT(&vn_tmp_list, &vn_rele_async_list);
-		vn_rele_list_length = 0;
-		mtx_unlock(&vn_rele_async_lock);
-		
-		while (!STAILQ_EMPTY(&vn_tmp_list)) {
-			curvnode = STAILQ_FIRST(&vn_tmp_list);
-
-			/*   STAILQ_REMOVE_HEAD */
-			STAILQ_FIRST(&vn_tmp_list) =
-			    ((vnode_link_t *)&curvnode->v_cstart)->stqe_next;
-			if (STAILQ_FIRST(&vn_tmp_list) == NULL)
-				         vn_tmp_list.stqh_last = &STAILQ_FIRST(&vn_tmp_list);
-			/***********************/
-			vrele(curvnode);
-		}
-		mtx_lock(&vn_rele_async_lock);
-		if (vn_rele_list_length == 0)
-			cv_timedwait(&vn_rele_async_cv, &vn_rele_async_lock,
-			    hz/10);
-	}
-
-	vn_rele_async_thread_exit = 0;
-	cv_broadcast(&vn_rele_async_cv);
-	mtx_unlock(&vn_rele_async_lock);
-	thread_exit();
+	vp->v_usecount--;
+	vdropl(vp);
 }
-
-static struct proc *vn_rele_async_proc;
-static struct kproc_desc up_kp = {
-	"vaclean",
-	vn_rele_async_cleaner,
-	&vn_rele_async_proc
-};
-SYSINIT(vaclean, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &up_kp);
-SYSINIT(vn_rele_async_setup, SI_SUB_VFS, SI_ORDER_FIRST, vn_rele_async_init, NULL);

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -1199,9 +1199,6 @@ dmu_init(void)
 void
 dmu_fini(void)
 {
-#ifdef _KERNEL
-	vn_rele_async_fini();
-#endif
 	arc_fini();
 	dnode_fini();
 	dbuf_fini();

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -91,6 +91,9 @@ dsl_pool_open_impl(spa_t *spa, uint64_t 
 	mutex_init(&dp->dp_lock, NULL, MUTEX_DEFAULT, NULL);
 	mutex_init(&dp->dp_scrub_cancel_lock, NULL, MUTEX_DEFAULT, NULL);
 
+	dp->dp_vnrele_taskq = taskq_create("zfs_vn_rele_taskq", 1, minclsyspri,
+	    1, 4, 0);
+
 	return (dp);
 }
 
@@ -228,6 +231,7 @@ dsl_pool_close(dsl_pool_t *dp)
 	rw_destroy(&dp->dp_config_rwlock);
 	mutex_destroy(&dp->dp_lock);
 	mutex_destroy(&dp->dp_scrub_cancel_lock);
+	taskq_destroy(dp->dp_vnrele_taskq);
 	kmem_free(dp, sizeof (dsl_pool_t));
 }
 
@@ -611,3 +615,9 @@ dsl_pool_create_origin(dsl_pool_t *dp, d
 	dsl_dataset_rele(ds, FTAG);
 	rw_exit(&dp->dp_config_rwlock);
 }
+
+taskq_t *
+dsl_pool_vnrele_taskq(dsl_pool_t *dp)
+{
+	return (dp->dp_vnrele_taskq);
+}

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h	Wed Jan  6 08:18:49 2010	(r201633)
@@ -57,6 +57,7 @@ typedef struct dsl_pool {
 	struct dsl_dir *dp_mos_dir;
 	struct dsl_dataset *dp_origin_snap;
 	uint64_t dp_root_dir_obj;
+	struct taskq *dp_vnrele_taskq;
 
 	/* No lock needed - sync context only */
 	blkptr_t dp_meta_rootbp;
@@ -119,6 +120,8 @@ int dsl_pool_scrub_clean(dsl_pool_t *dp)
 void dsl_pool_scrub_sync(dsl_pool_t *dp, dmu_tx_t *tx);
 void dsl_pool_scrub_restart(dsl_pool_t *dp);
 
+taskq_t *dsl_pool_vnrele_taskq(dsl_pool_t *dp);
+
 #ifdef	__cplusplus
 }
 #endif

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_context.h	Wed Jan  6 08:18:49 2010	(r201633)
@@ -49,6 +49,7 @@ extern "C" {
 #include <sys/conf.h>
 #include <sys/mutex.h>
 #include <sys/rwlock.h>
+#include <sys/kcondvar.h>
 #include <sys/random.h>
 #include <sys/byteorder.h>
 #include <sys/systm.h>

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h	Wed Jan  6 08:18:49 2010	(r201633)
@@ -78,7 +78,11 @@ extern "C" {
 /*
  * Is ID ephemeral?
  */
+#ifdef TODO
 #define	IS_EPHEMERAL(x)		(x > MAXUID)
+#else
+#define	IS_EPHEMERAL(x)		(0)
+#endif
 
 /*
  * Should we use FUIDs?

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -3057,44 +3057,35 @@ zfsdev_fini(void)
 		destroy_dev(zfsdev);
 }
 
-static struct task zfs_start_task;
 static struct root_hold_token *zfs_root_token;
 
-
 uint_t zfs_fsyncer_key;
 extern uint_t rrw_tsd_key;
 
-static void
-zfs_start(void *context __unused, int pending __unused)
-{
-
-	zfsdev_init();
-	spa_init(FREAD | FWRITE);
-	zfs_init();
-	zvol_init();
-
-	tsd_create(&zfs_fsyncer_key, NULL);
-	tsd_create(&rrw_tsd_key, NULL);
-
-	printf("ZFS storage pool version " SPA_VERSION_STRING "\n");
-	root_mount_rel(zfs_root_token);
-}
-
 static int
 zfs_modevent(module_t mod, int type, void *unused __unused)
 {
-	int error;
+	int error = 0;
 
-	error = EOPNOTSUPP;
 	switch (type) {
 	case MOD_LOAD:
 		zfs_root_token = root_mount_hold("ZFS");
 		printf("WARNING: ZFS is considered to be an experimental "
 		    "feature in FreeBSD.\n");
-		TASK_INIT(&zfs_start_task, 0, zfs_start, NULL);
-		taskqueue_enqueue(taskqueue_thread, &zfs_start_task);
+
 		mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
-		error = 0;
+
+		spa_init(FREAD | FWRITE);
+		zfs_init();
+		zvol_init();
+
+		tsd_create(&zfs_fsyncer_key, NULL);
+		tsd_create(&rrw_tsd_key, NULL);
+
+		printf("ZFS storage pool version " SPA_VERSION_STRING "\n");
+		root_mount_rel(zfs_root_token);
+
+		zfsdev_init();
 		break;
 	case MOD_UNLOAD:
 		if (spa_busy() || zfs_busy() || zvol_busy() ||
@@ -3102,14 +3093,19 @@ zfs_modevent(module_t mod, int type, voi
 			error = EBUSY;
 			break;
 		}
+
+		zfsdev_fini();
 		zvol_fini();
 		zfs_fini();
 		spa_fini();
-		zfsdev_fini();
+
 		tsd_destroy(&zfs_fsyncer_key);
 		tsd_destroy(&rrw_tsd_key);
+
 		mutex_destroy(&zfs_share_lock);
-		error = 0;
+		break;
+	default:
+		error = EOPNOTSUPP;
 		break;
 	}
 	return (error);

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -576,6 +576,7 @@ zfs_domount(vfs_t *vfsp, char *osname)
 	vfsp->mnt_flag |= MNT_LOCAL;
 	vfsp->mnt_kern_flag |= MNTK_MPSAFE;
 	vfsp->mnt_kern_flag |= MNTK_LOOKUP_SHARED;
+	vfsp->mnt_kern_flag |= MNTK_SHARED_WRITES;
 
 	if (error = dsl_prop_get_integer(osname, "readonly", &readonly, NULL))
 		goto out;
@@ -924,7 +925,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolea
 	for (zp = list_head(&zfsvfs->z_all_znodes); zp != NULL;
 	    zp = list_next(&zfsvfs->z_all_znodes, zp))
 		if (zp->z_dbuf) {
-			ASSERT(ZTOV(zp)->v_count > 0);
+			ASSERT(ZTOV(zp)->v_count >= 0);
 			zfs_znode_dmu_fini(zp);
 		}
 	mutex_exit(&zfsvfs->z_znodes_lock);

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -925,6 +925,7 @@ zfs_get_done(dmu_buf_t *db, void *vzgd)
 	zgd_t *zgd = (zgd_t *)vzgd;
 	rl_t *rl = zgd->zgd_rl;
 	vnode_t *vp = ZTOV(rl->r_zp);
+	objset_t *os = rl->r_zp->z_zfsvfs->z_os;
 	int vfslocked;
 
 	vfslocked = VFS_LOCK_GIANT(vp->v_vfsp);
@@ -934,7 +935,7 @@ zfs_get_done(dmu_buf_t *db, void *vzgd)
 	 * Release the vnode asynchronously as we currently have the
 	 * txg stopped from syncing.
 	 */
-	VN_RELE_ASYNC(vp, NULL);
+	VN_RELE_ASYNC(vp, dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
 	zil_add_block(zgd->zgd_zilog, zgd->zgd_bp);
 	kmem_free(zgd, sizeof (zgd_t));
 	VFS_UNLOCK_GIANT(vfslocked);
@@ -969,8 +970,8 @@ zfs_get_data(void *arg, lr_write_t *lr, 
 		 * Release the vnode asynchronously as we currently have the
 		 * txg stopped from syncing.
 		 */
-		VN_RELE_ASYNC(ZTOV(zp), NULL);
-
+		VN_RELE_ASYNC(ZTOV(zp),
+		    dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
 		return (ENOENT);
 	}
 
@@ -1046,7 +1047,7 @@ out:
 	 * Release the vnode asynchronously as we currently have the
 	 * txg stopped from syncing.
 	 */
-	VN_RELE_ASYNC(ZTOV(zp), NULL);
+	VN_RELE_ASYNC(ZTOV(zp), dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
 	return (error);
 }
 
@@ -3709,12 +3710,11 @@ zfs_inactive(vnode_t *vp, cred_t *cr, ca
 		 * The fs has been unmounted, or we did a
 		 * suspend/resume and this file no longer exists.
 		 */
-		mutex_enter(&zp->z_lock);
 		VI_LOCK(vp);
 		vp->v_count = 0; /* count arrives as 1 */
-		mutex_exit(&zp->z_lock);
+		VI_UNLOCK(vp);
+		vrecycle(vp, curthread);
 		rw_exit(&zfsvfs->z_teardown_inactive_lock);
-		zfs_znode_free(zp);
 		return;
 	}
 
@@ -3963,7 +3963,7 @@ static int
 zfs_freebsd_access(ap)
 	struct vop_access_args /* {
 		struct vnode *a_vp;
-		int  a_accmode;
+		accmode_t a_accmode;
 		struct ucred *a_cred;
 		struct thread *a_td;
 	} */ *ap;
@@ -4355,7 +4355,6 @@ zfs_freebsd_reclaim(ap)
 {
 	vnode_t	*vp = ap->a_vp;
 	znode_t	*zp = VTOZ(vp);
-	zfsvfs_t *zfsvfs;
 
 	ASSERT(zp != NULL);
 
@@ -4365,13 +4364,18 @@ zfs_freebsd_reclaim(ap)
 	vnode_destroy_vobject(vp);
 
 	mutex_enter(&zp->z_lock);
-	ASSERT(zp->z_phys);
+	ASSERT(zp->z_phys != NULL);
 	ZTOV(zp) = NULL;
-	if (!zp->z_unlinked) {
+	mutex_exit(&zp->z_lock);
+
+	if (zp->z_unlinked)
+		;	/* Do nothing. */
+	else if (zp->z_dbuf == NULL)
+		zfs_znode_free(zp);
+	else /* if (!zp->z_unlinked && zp->z_dbuf != NULL) */ {
+		zfsvfs_t *zfsvfs = zp->z_zfsvfs;
 		int locked;
 
-		zfsvfs = zp->z_zfsvfs;
-		mutex_exit(&zp->z_lock);
 		locked = MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id)) ? 2 :
 		    ZFS_OBJ_HOLD_TRYENTER(zfsvfs, zp->z_id);
 		if (locked == 0) {
@@ -4387,8 +4391,6 @@ zfs_freebsd_reclaim(ap)
 				ZFS_OBJ_HOLD_EXIT(zfsvfs, zp->z_id);
 			zfs_znode_free(zp);
 		}
-	} else {
-		mutex_exit(&zp->z_lock);
 	}
 	VI_LOCK(vp);
 	vp->v_data = NULL;
@@ -4702,6 +4704,9 @@ vop_listextattr {
 
 	ZFS_ENTER(zfsvfs);
 
+	if (sizep != NULL)
+		*sizep = 0;
+
 	error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td,
 	    LOOKUP_XATTR);
 	if (error != 0) {
@@ -4726,9 +4731,6 @@ vop_listextattr {
 	auio.uio_rw = UIO_READ;
 	auio.uio_offset = 0;
 
-	if (sizep != NULL)
-		*sizep = 0;
-
 	do {
 		u_char nlen;
 

Copied: stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/taskq.h (from r196295, head/sys/cddl/contrib/opensolaris/uts/common/sys/taskq.h)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/taskq.h	Wed Jan  6 08:18:49 2010	(r201633, copy of r196295, head/sys/cddl/contrib/opensolaris/uts/common/sys/taskq.h)
@@ -0,0 +1,90 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_SYS_TASKQ_H
+#define	_SYS_TASKQ_H
+
+#include <sys/types.h>
+#include <sys/proc.h>
+#include <sys/taskqueue.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#define	TASKQ_NAMELEN	31
+
+struct taskqueue;
+struct taskq {
+	struct taskqueue	*tq_queue;
+};
+
+typedef struct taskq taskq_t;
+typedef uintptr_t taskqid_t;
+typedef void (task_func_t)(void *);
+
+/*
+ * Public flags for taskq_create(): bit range 0-15
+ */
+#define	TASKQ_PREPOPULATE	0x0001	/* Prepopulate with threads and data */
+#define	TASKQ_CPR_SAFE		0x0002	/* Use CPR safe protocol */
+#define	TASKQ_DYNAMIC		0x0004	/* Use dynamic thread scheduling */
+#define	TASKQ_THREADS_CPU_PCT	0x0008	/* number of threads as % of ncpu */
+
+/*
+ * Flags for taskq_dispatch. TQ_SLEEP/TQ_NOSLEEP should be same as
+ * KM_SLEEP/KM_NOSLEEP.
+ */
+#define	TQ_SLEEP	0x00	/* Can block for memory */
+#define	TQ_NOSLEEP	0x01	/* cannot block for memory; may fail */
+#define	TQ_NOQUEUE	0x02	/* Do not enqueue if can't dispatch */
+#define	TQ_NOALLOC	0x04	/* cannot allocate memory; may fail */
+
+#ifdef _KERNEL
+
+extern taskq_t *system_taskq;
+
+extern void	taskq_init(void);
+extern void	taskq_mp_init(void);
+
+extern taskq_t	*taskq_create(const char *, int, pri_t, int, int, uint_t);
+extern taskq_t	*taskq_create_instance(const char *, int, int, pri_t, int,
+    int, uint_t);
+extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
+extern void	nulltask(void *);
+extern void	taskq_destroy(taskq_t *);
+extern void	taskq_wait(taskq_t *);
+extern void	taskq_suspend(taskq_t *);
+extern int	taskq_suspended(taskq_t *);
+extern void	taskq_resume(taskq_t *);
+extern int	taskq_member(taskq_t *, kthread_t *);
+
+#endif	/* _KERNEL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SYS_TASKQ_H */

Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
==============================================================================
--- stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h	Wed Jan  6 08:18:49 2010	(r201633)
@@ -354,6 +354,11 @@ typedef struct caller_context {
 } caller_context_t;
 
 /*
+ * Structure tags for function prototypes, defined elsewhere.
+ */
+struct taskq;
+
+/*
  * Flags for VOP_LOOKUP
  *
  * Defined in file.h, but also possible, FIGNORECASE
@@ -370,6 +375,13 @@ typedef struct caller_context {
 #define	V_RDDIR_ENTFLAGS	0x01	/* request dirent flags */
 
 /*
+ * Public vnode manipulation functions.
+ */
+#ifdef	_KERNEL
+
+void	vn_rele_async(struct vnode *vp, struct taskq *taskq);
+
+/*
  * Extensible vnode attribute (xva) routines:
  * xva_init() initializes an xvattr_t (zero struct, init mapsize, set AT_XATTR)
  * xva_getxoptattr() returns a ponter to the xoptattr_t section of xvattr_t
@@ -377,10 +389,12 @@ typedef struct caller_context {
 void		xva_init(xvattr_t *);
 xoptattr_t	*xva_getxoptattr(xvattr_t *);	/* Get ptr to xoptattr_t */
 
-struct taskq;
-void	vn_rele_async(struct vnode *vp, struct taskq *taskq);
-void	vn_rele_async_fini(void);
-	
+#define	VN_RELE_ASYNC(vp, taskq)	{ \
+	vn_rele_async(vp, taskq); \
+}
+
+#endif	/* _KERNEL */
+
 /*
  * Flags to VOP_SETATTR/VOP_GETATTR.
  */

Modified: stable/7/sys/cddl/dev/cyclic/cyclic.c
==============================================================================
--- stable/7/sys/cddl/dev/cyclic/cyclic.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/dev/cyclic/cyclic.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -1341,12 +1341,11 @@ cyclic_mp_init(void)
 static void
 cyclic_uninit(void)
 {
-	struct pcpu *pc;
 	cpu_t *c;
 	int id;
 
 	for (id = 0; id <= mp_maxid; id++) {
-		if ((pc = pcpu_find(id)) == NULL)
+		if (pcpu_find(id) == NULL)
 			continue;
 
 		c = &solaris_cpu[id];

Modified: stable/7/sys/cddl/dev/dtrace/i386/dtrace_subr.c
==============================================================================
--- stable/7/sys/cddl/dev/dtrace/i386/dtrace_subr.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/cddl/dev/dtrace/i386/dtrace_subr.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -408,7 +408,6 @@ dtrace_gethrtime_init(void *arg)
 	uint64_t tsc_f;
 	cpumask_t map;
 	int i;
-	struct pcpu *cp;
 
 	/*
 	 * Get TSC frequency known at this moment.
@@ -444,7 +443,7 @@ dtrace_gethrtime_init(void *arg)
 		if (i == curcpu)
 			continue;
 
-		if ((cp = pcpu_find(i)) == NULL)
+		if (pcpu_find(i) == NULL)
 			continue;
 
 		map = 0;

Modified: stable/7/sys/kern/subr_taskqueue.c
==============================================================================
--- stable/7/sys/kern/subr_taskqueue.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/kern/subr_taskqueue.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -463,3 +463,32 @@ taskqueue_fast_run(void *dummy)
 TASKQUEUE_FAST_DEFINE(fast, taskqueue_fast_enqueue, 0,
 	swi_add(NULL, "Fast task queue", taskqueue_fast_run, NULL,
 	SWI_TQ_FAST, INTR_MPSAFE, &taskqueue_fast_ih));
+
+int
+taskqueue_member(struct taskqueue *queue, struct thread *td)
+{
+	int i, j, ret = 0;
+	struct thread *ptd;
+
+	TQ_LOCK(queue);
+	for (i = 0, j = 0; ; i++) {
+		if (queue->tq_pproc[i] == NULL)
+			continue;
+		ptd = FIRST_THREAD_IN_PROC(queue->tq_pproc[i]);
+		/*
+		 * In releng7 all kprocs have only one kthread, so there is
+		 * no need to use FOREACH_THREAD_IN_PROC instead.
+		 * If this changes at some point, only the first 'if' needs
+		 * to be included in the FOREACH_..., the second one can
+		 * stay as it is.
+		 */
+		if (ptd == td) {
+			ret = 1;
+			break;
+		}
+		if (++j >= queue->tq_pcount)
+			break;
+	}
+	TQ_UNLOCK(queue);
+	return (ret);
+}

Modified: stable/7/sys/kern/vfs_vnops.c
==============================================================================
--- stable/7/sys/kern/vfs_vnops.c	Wed Jan  6 07:50:27 2010	(r201632)
+++ stable/7/sys/kern/vfs_vnops.c	Wed Jan  6 08:18:49 2010	(r201633)
@@ -351,7 +351,7 @@ vn_rdwr(rw, vp, base, len, offset, segfl
 	struct iovec aiov;
 	struct mount *mp;
 	struct ucred *cred;
-	int error;
+	int error, lock_flags;
 
 	VFS_ASSERT_GIANT(vp->v_mount);
 
@@ -362,12 +362,23 @@ vn_rdwr(rw, vp, base, len, offset, segfl
 			    (error = vn_start_write(vp, &mp, V_WAIT | PCATCH))
 			    != 0)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list