diff options
author | csjp <csjp@FreeBSD.org> | 2005-09-28 00:30:56 +0000 |
---|---|---|
committer | csjp <csjp@FreeBSD.org> | 2005-09-28 00:30:56 +0000 |
commit | af34ae34d05ea33d9e054fcdc6249ee0cff5a5ad (patch) | |
tree | d3966ee35bb5338e552588acefc927c6e9aa314f /sys/kern/kern_jail.c | |
parent | 9f3c495c7b023a93b35ec459d98fd9477de9cc91 (diff) | |
download | FreeBSD-src-af34ae34d05ea33d9e054fcdc6249ee0cff5a5ad.zip FreeBSD-src-af34ae34d05ea33d9e054fcdc6249ee0cff5a5ad.tar.gz |
Push Giant down in jails. Pass the MPSAFE flag to NDINIT, and keep track
of whether or not Giant was picked up by the filesystem. Add VFS_LOCK_GIANT
macros around vrele as it's possible that this can call in the VOP_INACTIVE
filesystem specific code. Also while we are here, remove the Giant assertion.
from the sysctl handler, we do not actually require Giant here so we
shouldn't assert it. Doing so will just complicate things when Giant is removed
from the sysctl framework.
Diffstat (limited to 'sys/kern/kern_jail.c')
-rw-r--r-- | sys/kern/kern_jail.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index c3d1f9a..9be8487 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -106,7 +106,7 @@ jail(struct thread *td, struct jail_args *uap) struct prison *pr, *tpr; struct jail j; struct jail_attach_args jaa; - int error, tryprid; + int vfslocked, error, tryprid; error = copyin(uap->jail, &j, sizeof(j)); if (error) @@ -120,17 +120,16 @@ jail(struct thread *td, struct jail_args *uap) error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0); if (error) goto e_killmtx; - mtx_lock(&Giant); - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, pr->pr_path, td); + NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF, UIO_SYSSPACE, + pr->pr_path, td); error = namei(&nd); - if (error) { - mtx_unlock(&Giant); + if (error) goto e_killmtx; - } + vfslocked = NDHASGIANT(&nd); pr->pr_root = nd.ni_vp; VOP_UNLOCK(nd.ni_vp, 0, td); NDFREE(&nd, NDF_ONLY_PNBUF); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); if (error) goto e_dropvnref; @@ -174,9 +173,9 @@ e_dropprref: prisoncount--; mtx_unlock(&allprison_mtx); e_dropvnref: - mtx_lock(&Giant); + vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); vrele(pr->pr_root); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); e_killmtx: mtx_destroy(&pr->pr_mtx); FREE(pr, M_PRISON); @@ -196,7 +195,7 @@ jail_attach(struct thread *td, struct jail_attach_args *uap) struct proc *p; struct ucred *newcred, *oldcred; struct prison *pr; - int error; + int vfslocked, error; /* * XXX: Note that there is a slight race here if two threads @@ -221,7 +220,7 @@ jail_attach(struct thread *td, struct jail_attach_args *uap) mtx_unlock(&pr->pr_mtx); mtx_unlock(&allprison_mtx); - mtx_lock(&Giant); + vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY, td); if ((error = change_dir(pr->pr_root, td)) != 0) goto e_unlock; @@ -231,7 +230,7 @@ jail_attach(struct thread *td, struct jail_attach_args *uap) #endif VOP_UNLOCK(pr->pr_root, 0, td); change_root(pr->pr_root, td); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); newcred = crget(); PROC_LOCK(p); @@ -245,7 +244,7 @@ jail_attach(struct thread *td, struct jail_attach_args *uap) return (0); e_unlock: VOP_UNLOCK(pr->pr_root, 0, td); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); mtx_lock(&pr->pr_mtx); pr->pr_ref--; mtx_unlock(&pr->pr_mtx); @@ -295,12 +294,13 @@ static void prison_complete(void *context, int pending) { struct prison *pr; + int vfslocked; pr = (struct prison *)context; - mtx_lock(&Giant); + vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); vrele(pr->pr_root); - mtx_unlock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); mtx_destroy(&pr->pr_mtx); if (pr->pr_linux != NULL) @@ -530,7 +530,6 @@ sysctl_jail_list(SYSCTL_HANDLER_ARGS) struct prison *pr; int count, error; - mtx_assert(&Giant, MA_OWNED); if (jailed(req->td->td_ucred)) return (0); retry: |