Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 26 Aug 2011 16:03:34 +0000 (UTC)
From:      Jamie Gritton <jamie@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r225191 - head/sys/kern
Message-ID:  <201108261603.p7QG3YbF061534@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jamie
Date: Fri Aug 26 16:03:34 2011
New Revision: 225191
URL: http://svn.freebsd.org/changeset/base/225191

Log:
  Delay the recursive decrement of pr_uref when jails are made invisible
  but not removed; decrement it instead when the child jail actually
  goes away. This avoids letting the counter go below zero in the case
  where dying (pr_uref==0) jails are "resurrected", and an associated
  KASSERT panic.
  
  Submitted by:	Steven Hartland
  Approved by:	re (bz)
  MFC after:	1 week

Modified:
  head/sys/kern/kern_jail.c

Modified: head/sys/kern/kern_jail.c
==============================================================================
--- head/sys/kern/kern_jail.c	Fri Aug 26 15:24:54 2011	(r225190)
+++ head/sys/kern/kern_jail.c	Fri Aug 26 16:03:34 2011	(r225191)
@@ -2470,32 +2470,11 @@ prison_deref(struct prison *pr, int flag
 
 	if (!(flags & PD_LOCKED))
 		mtx_lock(&pr->pr_mtx);
-	/* Decrement the user references in a separate loop. */
-	if (flags & PD_DEUREF) {
-		for (tpr = pr;; tpr = tpr->pr_parent) {
-			if (tpr != pr)
-				mtx_lock(&tpr->pr_mtx);
-			if (--tpr->pr_uref > 0)
-				break;
-			KASSERT(tpr != &prison0, ("prison0 pr_uref=0"));
-			mtx_unlock(&tpr->pr_mtx);
-		}
-		/* Done if there were only user references to remove. */
-		if (!(flags & PD_DEREF)) {
-			mtx_unlock(&tpr->pr_mtx);
-			if (flags & PD_LIST_SLOCKED)
-				sx_sunlock(&allprison_lock);
-			else if (flags & PD_LIST_XLOCKED)
-				sx_xunlock(&allprison_lock);
-			return;
-		}
-		if (tpr != pr) {
-			mtx_unlock(&tpr->pr_mtx);
-			mtx_lock(&pr->pr_mtx);
-		}
-	}
-
 	for (;;) {
+		if (flags & PD_DEUREF) {
+			pr->pr_uref--;
+			KASSERT(prison0.pr_uref != 0, ("prison0 pr_uref=0"));
+		}
 		if (flags & PD_DEREF)
 			pr->pr_ref--;
 		/* If the prison still has references, nothing else to do. */
@@ -2551,7 +2530,7 @@ prison_deref(struct prison *pr, int flag
 		/* Removing a prison frees a reference on its parent. */
 		pr = ppr;
 		mtx_lock(&pr->pr_mtx);
-		flags = PD_DEREF;
+		flags = PD_DEREF | PD_DEUREF;
 	}
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201108261603.p7QG3YbF061534>