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;
        }
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to