Index: kern/kern_jail.c
===================================================================
RCS file: /data/ncvs/src/sys/kern/kern_jail.c,v
retrieving revision 1.34
diff -u -r1.34 kern_jail.c
--- kern/kern_jail.c	11 Jun 2003 00:56:55 -0000	1.34
+++ kern/kern_jail.c	20 Jan 2004 20:28:20 -0000
@@ -18,6 +18,7 @@
 #include <sys/sysproto.h>
 #include <sys/malloc.h>
 #include <sys/proc.h>
+#include <sys/taskqueue.h>
 #include <sys/jail.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
@@ -60,6 +61,7 @@
 int	prisoncount = 0;
 
 static void		 init_prison(void *);
+static void		 prison_complete(void *context, int pending);
 static struct prison	*prison_find(int);
 static int		 sysctl_jail_list(SYSCTL_HANDLER_ARGS);
 
@@ -255,7 +257,6 @@
 prison_free(struct prison *pr)
 {
 
-	mtx_assert(&Giant, MA_OWNED);
 	mtx_lock(&allprison_mtx);
 	mtx_lock(&pr->pr_mtx);
 	pr->pr_ref--;
@@ -264,15 +265,30 @@
 		mtx_unlock(&pr->pr_mtx);
 		prisoncount--;
 		mtx_unlock(&allprison_mtx);
-		vrele(pr->pr_root);
-		mtx_destroy(&pr->pr_mtx);
-		if (pr->pr_linux != NULL)
-			FREE(pr->pr_linux, M_PRISON);
-		FREE(pr, M_PRISON);
+
+		TASK_INIT(&pr->pr_task, 0, prison_complete, pr);
+		taskqueue_enqueue(taskqueue_swi, &pr->pr_task);
 		return;
 	}
 	mtx_unlock(&pr->pr_mtx);
 	mtx_unlock(&allprison_mtx);
+}
+
+static void
+prison_complete(void *context, int pending)
+{
+	struct prison *pr;
+
+	pr = (struct prison *)context;
+
+	mtx_lock(&Giant);
+	vrele(pr->pr_root);
+	mtx_unlock(&Giant);
+
+	mtx_destroy(&pr->pr_mtx);
+	if (pr->pr_linux != NULL)
+		FREE(pr->pr_linux, M_PRISON);
+	FREE(pr, M_PRISON);
 }
 
 void
Index: sys/_task.h
===================================================================
RCS file: sys/_task.h
diff -N sys/_task.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/_task.h	23 Jan 2004 19:07:24 -0000
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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 AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD: src/sys/sys/taskqueue.h,v 1.9 2003/09/05 23:09:22 sam Exp $
+ */
+
+#ifndef _SYS__TASK_H_
+#define _SYS__TASK_H_
+
+#ifndef _KERNEL
+#error "no user-servicable parts inside"
+#endif
+
+#include <sys/queue.h>
+
+/*
+ * Each task includes a function which is called from
+ * taskqueue_run().  The first argument is taken from the 'ta_context'
+ * field of struct task and the second argument is a count of how many
+ * times the task was enqueued before the call to taskqueue_run().
+ */
+typedef void task_fn_t(void *context, int pending);
+
+struct task {
+	STAILQ_ENTRY(task) ta_link;	/* link for queue */
+	int	ta_pending;		/* count times queued */
+	int	ta_priority;		/* priority of task in queue */
+	task_fn_t *ta_func;		/* task handler */
+	void	*ta_context;		/* argument for handler */
+};
+
+#endif /* !_SYS__TASK_H_ */
Index: sys/jail.h
===================================================================
RCS file: /data/ncvs/src/sys/sys/jail.h,v
retrieving revision 1.18
diff -u -r1.18 jail.h
--- sys/jail.h	9 Apr 2003 02:55:18 -0000	1.18
+++ sys/jail.h	23 Jan 2004 19:08:16 -0000
@@ -39,6 +39,7 @@
 #include <sys/queue.h>
 #include <sys/_lock.h>
 #include <sys/_mutex.h>
+#include <sys/_task.h>
 
 #define JAIL_MAX	999999
 
@@ -56,8 +57,8 @@
  *   (p) locked by pr_mutex
  *   (c) set only during creation before the structure is shared, no mutex
  *       required to read
+ *   (d) set only during destruction of jail, no mutex needed
  */
-struct mtx;
 struct prison {
 	LIST_ENTRY(prison) pr_list;			/* (a) all prisons */
 	int		 pr_id;				/* (c) prison id */
@@ -68,6 +69,7 @@
 	u_int32_t	 pr_ip;				/* (c) ip addr host */
 	void		*pr_linux;			/* (p) linux abi */
 	int		 pr_securelevel;		/* (p) securelevel */
+	struct task	 pr_task;			/* (d) destroy task */
 	struct mtx	 pr_mtx;
 };
 
Index: sys/taskqueue.h
===================================================================
RCS file: /data/ncvs/src/sys/sys/taskqueue.h,v
retrieving revision 1.9
diff -u -r1.9 taskqueue.h
--- sys/taskqueue.h	5 Sep 2003 23:09:22 -0000	1.9
+++ sys/taskqueue.h	23 Jan 2004 19:07:52 -0000
@@ -34,18 +34,11 @@
 #endif
 
 #include <sys/queue.h>
+#include <sys/_task.h>
 
 struct taskqueue;
 
 /*
- * Each task includes a function which is called from
- * taskqueue_run().  The first argument is taken from the 'ta_context'
- * field of struct task and the second argument is a count of how many
- * times the task was enqueued before the call to taskqueue_run().
- */
-typedef void task_fn_t(void *context, int pending);
-
-/*
  * A notification callback function which is called from
  * taskqueue_enqueue().  The context argument is given in the call to
  * taskqueue_create().  This function would normally be used to allow the
@@ -53,14 +46,6 @@
  * interrupt or waking a kernel thread).
  */
 typedef void (*taskqueue_enqueue_fn)(void *context);
-
-struct task {
-	STAILQ_ENTRY(task) ta_link;	/* link for queue */
-	int	ta_pending;		/* count times queued */
-	int	ta_priority;		/* priority of task in queue */
-	task_fn_t *ta_func;		/* task handler */
-	void	*ta_context;		/* argument for handler */
-};
 
 struct taskqueue *taskqueue_create(const char *name, int mflags,
 				    taskqueue_enqueue_fn enqueue,
