summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorcsjp <csjp@FreeBSD.org>2005-09-28 00:30:56 +0000
committercsjp <csjp@FreeBSD.org>2005-09-28 00:30:56 +0000
commitaf34ae34d05ea33d9e054fcdc6249ee0cff5a5ad (patch)
treed3966ee35bb5338e552588acefc927c6e9aa314f /sys
parent9f3c495c7b023a93b35ec459d98fd9477de9cc91 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/kern/kern_jail.c31
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:
OpenPOWER on IntegriCloud