summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2004-01-23 20:44:26 +0000
committerrwatson <rwatson@FreeBSD.org>2004-01-23 20:44:26 +0000
commit718d82cd61f270ab6f5586658e3d6204b35e4f64 (patch)
treecad255f8a586699981e032637c52523632e2f1bc /sys/kern
parentcd37a854086191ba3b4fc2e379dc71b33a8ca0ec (diff)
downloadFreeBSD-src-718d82cd61f270ab6f5586658e3d6204b35e4f64.zip
FreeBSD-src-718d82cd61f270ab6f5586658e3d6204b35e4f64.tar.gz
Defer the vrele() on a jail's root vnode reference from prison_free()
to a new prison_complete() task run by a task queue. This removes a requirement for grabbing Giant in crfree(). Embed the 'struct task' in 'struct prison' so that we don't have to allocate memory from prison_free() (which means we also defer the FREE()). With this change, I believe grabbing Giant from crfree() can now be removed, but need to check the uidinfo code paths. To avoid header pollution, move the definition of 'struct task' to _task.h, and recursively include from taskqueue.h and jail.h; much preferably to all files including jail.h picking up a requirement to include taskqueue.h. Bumped into by: sam Reviewed by: bde, tjr
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_jail.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 2241dd6..79be249 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -18,6 +18,7 @@ __FBSDID("$FreeBSD$");
#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 lastprid = 0;
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 @@ void
prison_free(struct prison *pr)
{
- mtx_assert(&Giant, MA_OWNED);
mtx_lock(&allprison_mtx);
mtx_lock(&pr->pr_mtx);
pr->pr_ref--;
@@ -264,17 +265,32 @@ prison_free(struct prison *pr)
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
prison_hold(struct prison *pr)
{
OpenPOWER on IntegriCloud