Bug 132337 - [zfs] [panic] kernel panic in zfs_fuid_create_cred
Summary: [zfs] [panic] kernel panic in zfs_fuid_create_cred
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 8.0-CURRENT
Hardware: Any Any
: Normal Affects Only Me
Assignee: Pawel Jakub Dawidek
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-03-05 15:00 UTC by Matthew West
Modified: 2010-01-06 08:20 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew West 2009-03-05 15:00:13 UTC
panic: zfs_fuid_create_cred
cpuid = 2
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2a
panic() at panic+0x182
zfs_fuid_create_cred() at zfs_fuid_create_cred+0x56
zfs_perm_init() at zfs_perm_init+0x84
zfs_mknode() at zfs_mknode+0x24e
zfs_freebsd_create() at zfs_freebsd_create+0x617
VOP_CREATE_APV() at VOP_CREATE_APV+0xb3
nfsrv_create() at nfsrv_create+0x909
nfssvc_program() at nfssvc_program+0x1a1
svc_run_internal() at svc_run_internal+0x62b
svc_thread_start() at svc_thread_start+0xb
fork_exit() at fork_exit+0x12a
fork_trampoline() at fork_trampoline+0xe
--- trap 0xc, rip = 0x800695c4c, rsp = 0x7fffffffe8e8, rbp = 0 ---
Uptime: 26m9s
Physical memory: 3056 MB
Dumping 388 MB: 373 357 341 325 309 293 277 261Error dumping block 0x0

** DUMP FAILED (ERROR 5) **
aac0: shutting down controller...FAILED.
Automatic reboot in 15 seconds - press a key on the console to abort
Rebooting...

How-To-Repeat: 
Set up a directory on an NFS share with chmod 777 permissions.  Run iozone3 on a client machine, in the 777 mode directory.

Sometimes you need to ^C the iozone process and restart it a few times to trigger the panic.

I am guessing the problem lies in some of the unimplemented code in the #ifdef TODO block in zfs_fuid.c.
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2009-03-05 15:33:31 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-fs

Over to maintainer(s).
Comment 2 rsofia 2009-04-10 15:27:09 UTC
touching a file `touch hi` on the 777 mode directory over nfs is the 
easiest and most guaranteed way to reproduce this panic.
Comment 3 Thomas Backman 2009-07-23 09:22:13 UTC
Hey all,
Unfortunately, this PR appears to still be unfixed. Is anyone looking  
at this?
I tried to set up a diskless client over NFS yesterday, running ZFS  
on /, and ran in to this panic (exact same backtrace as the PR (see  
bottom the this mail)) a lot of times. In the end, I created a ZVOL  
with UFS on it, and the panics disappeared as expected - since it no  
longer has to work directly with files on a ZFS *filesystem*.
It seems to be pretty easy to trigger, as I couldn't finish the boot  
process on the diskless client more than once until I went with UFS.  
Since then I've gotten 0 panics.

FWIW, my /etc/exports (I know now R/W NFS root isn't a good idea, but  
it might be relevant):
/diskless -maproot=0 -alldirs 192.168.1.6

Regards,
Thomas

Backtrace:

panic: zfs_fuid_create_cred
cpuid = x
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2a
panic() at panic+0x182
zfs_fuid_create_cred() at zfs_fuid_create_cred+0x56
zfs_perm_init() at zfs_perm_init+0x84
zfs_mknode() at zfs_mknode+0x24e
zfs_freebsd_create() at zfs_freebsd_create+0x617
VOP_CREATE_APV() at VOP_CREATE_APV+0xb3
nfsrv_create() at nfsrv_create+0x909
nfssvc_program() at nfssvc_program+0x1a1
svc_run_internal() at svc_run_internal+0x62b
svc_thread_start() at svc_thread_start+0xb
fork_exit() at fork_exit+0x12a
fork_trampoline() at fork_trampoline+0xe
Comment 4 Jaakko Heinonen 2009-07-23 10:24:36 UTC
Hi,

On 2009-07-23, Thomas Backman wrote:
> Unfortunately, this PR appears to still be unfixed. Is anyone looking  
> at this?

> panic: zfs_fuid_create_cred

This PR is a duplicate of kern/133020. There is a workaround fix in
pjd's perforce branch but apparently it was never committed to svn.

See:

	http://p4db.freebsd.org/changeView.cgi?CH=159874
	http://people.freebsd.org/~pjd/patches/zfs_znode.h.patch

-- 
Jaakko
Comment 5 Michael Reifenberger 2009-07-23 14:06:52 UTC
On Thu, 23 Jul 2009, Jaakko Heinonen wrote:
...
> This PR is a duplicate of kern/133020. There is a workaround fix in
> pjd's perforce branch but apparently it was never committed to svn.
>
> See:
>
> 	http://p4db.freebsd.org/changeView.cgi?CH=159874
> 	http://people.freebsd.org/~pjd/patches/zfs_znode.h.patch
>
I'm using this patch since march without problems.

Bye/2
---
Michael Reifenberger
Michael@Reifenberger.com
http://www.Reifenberger.com
Comment 6 Thomas Backman 2009-07-23 14:13:51 UTC
On Jul 23, 2009, at 15:06, Michael Reifenberger wrote:

> On Thu, 23 Jul 2009, Jaakko Heinonen wrote:
> ...
>> This PR is a duplicate of kern/133020. There is a workaround fix in
>> pjd's perforce branch but apparently it was never committed to svn.
>>
>> See:
>>
>> 	http://p4db.freebsd.org/changeView.cgi?CH=159874
>> 	http://people.freebsd.org/~pjd/patches/zfs_znode.h.patch
>>
> I'm using this patch since march without problems.

I've only used it for hours but it seems to work here too, no longer  
using ZVOLs.
Would be nice to have in -RELEASE :)

Jaakko: It's the other way around. 132337 < 133020. This bug was filed  
Mar 05 2009, while 133020 was filed Mar 24 2009.

Regards,
Thomas
Comment 7 dfilter service freebsd_committer freebsd_triage 2009-07-27 15:52:44 UTC
Author: pjd
Date: Mon Jul 27 14:52:34 2009
New Revision: 195909
URL: http://svn.freebsd.org/changeset/base/195909

Log:
  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@r.zeeb.org>
  Tested by:	Thomas Backman <serenity@exscape.org>, Michael Reifenberger <mike@reifenberger.com>
  Approved by:	re (kib)
  MFC after:	2 weeks

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h	Mon Jul 27 14:22:09 2009	(r195908)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h	Mon Jul 27 14:52:34 2009	(r195909)
@@ -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?
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 8 dfilter service freebsd_committer freebsd_triage 2010-01-06 08:19:06 UTC
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@r.zeeb.org>
      Tested by:		Thomas Backman <serenity@exscape.org>, Michael Reifenberger <mike@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@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@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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 9 Pawel Jakub Dawidek freebsd_committer freebsd_triage 2014-06-01 07:01:15 UTC
State Changed
From-To: open->patched

Fix committed to HEAD. 


Comment 10 Pawel Jakub Dawidek freebsd_committer freebsd_triage 2014-06-01 07:01:15 UTC
Responsible Changed
From-To: freebsd-fs->pjd

I'll take this one.
Comment 11 Pawel Jakub Dawidek freebsd_committer freebsd_triage 2014-06-01 07:01:15 UTC
State Changed
From-To: patched->closed

Fix merged to stable/8.