diff options
author | rwatson <rwatson@FreeBSD.org> | 2004-01-23 20:44:26 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2004-01-23 20:44:26 +0000 |
commit | 718d82cd61f270ab6f5586658e3d6204b35e4f64 (patch) | |
tree | cad255f8a586699981e032637c52523632e2f1bc /sys/kern | |
parent | cd37a854086191ba3b4fc2e379dc71b33a8ca0ec (diff) | |
download | FreeBSD-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.c | 28 |
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) { |