Author: trasz
Date: Tue Mar  6 11:05:50 2012
New Revision: 232598
URL: http://svn.freebsd.org/changeset/base/232598

Log:
  Make racct and rctl correctly handle jail renaming.  Previously
  they would continue using old name, the one jail was created with.
  
  PR:           bin/165207

Modified:
  head/sys/kern/kern_jail.c
  head/sys/kern/kern_racct.c
  head/sys/sys/racct.h

Modified: head/sys/kern/kern_jail.c
==============================================================================
--- head/sys/kern/kern_jail.c   Tue Mar  6 10:51:53 2012        (r232597)
+++ head/sys/kern/kern_jail.c   Tue Mar  6 11:05:50 2012        (r232598)
@@ -130,6 +130,7 @@ static char *prison_path(struct prison *
 static void prison_remove_one(struct prison *pr);
 #ifdef RACCT
 static void prison_racct_attach(struct prison *pr);
+static void prison_racct_modify(struct prison *pr);
 static void prison_racct_detach(struct prison *pr);
 #endif
 #ifdef INET
@@ -1830,6 +1831,12 @@ kern_jail_set(struct thread *td, struct 
                if (!(flags & JAIL_ATTACH))
                        sx_sunlock(&allprison_lock);
        }
+
+#ifdef RACCT
+       if (!created)
+               prison_racct_modify(pr);
+#endif
+
        td->td_retval[0] = pr->pr_id;
        goto done_errmsg;
 
@@ -4427,24 +4434,32 @@ prison_racct_hold(struct prison_racct *p
        refcount_acquire(&prr->prr_refcount);
 }
 
+static void
+prison_racct_free_locked(struct prison_racct *prr)
+{
+
+       sx_assert(&allprison_lock, SA_XLOCKED);
+
+       if (refcount_release(&prr->prr_refcount)) {
+               racct_destroy(&prr->prr_racct);
+               LIST_REMOVE(prr, prr_next);
+               free(prr, M_PRISON_RACCT);
+       }
+}
+
 void
 prison_racct_free(struct prison_racct *prr)
 {
        int old;
 
+       sx_assert(&allprison_lock, SA_UNLOCKED);
+
        old = prr->prr_refcount;
        if (old > 1 && atomic_cmpset_int(&prr->prr_refcount, old, old - 1))
                return;
 
        sx_xlock(&allprison_lock);
-       if (refcount_release(&prr->prr_refcount)) {
-               racct_destroy(&prr->prr_racct);
-               LIST_REMOVE(prr, prr_next);
-               sx_xunlock(&allprison_lock);
-               free(prr, M_PRISON_RACCT);
-
-               return;
-       }
+       prison_racct_free_locked(prr);
        sx_xunlock(&allprison_lock);
 }
 
@@ -4454,15 +4469,63 @@ prison_racct_attach(struct prison *pr)
 {
        struct prison_racct *prr;
 
+       sx_assert(&allprison_lock, SA_XLOCKED);
+
        prr = prison_racct_find_locked(pr->pr_name);
        KASSERT(prr != NULL, ("cannot find prison_racct"));
 
        pr->pr_prison_racct = prr;
 }
 
+/*
+ * Handle jail renaming.  From the racct point of view, renaming means
+ * moving from one prison_racct to another.
+ */
+static void
+prison_racct_modify(struct prison *pr)
+{
+       struct proc *p;
+       struct ucred *cred;
+       struct prison_racct *oldprr;
+
+       sx_slock(&allproc_lock);
+       sx_xlock(&allprison_lock);
+
+       if (strcmp(pr->pr_name, pr->pr_prison_racct->prr_name) == 0)
+               return;
+
+       oldprr = pr->pr_prison_racct;
+       pr->pr_prison_racct = NULL;
+
+       prison_racct_attach(pr);
+
+       /*
+        * Move resource utilisation records.
+        */
+       racct_move(pr->pr_prison_racct->prr_racct, oldprr->prr_racct);
+
+       /*
+        * Force rctl to reattach rules to processes.
+        */
+       FOREACH_PROC_IN_SYSTEM(p) {
+               PROC_LOCK(p);
+               cred = crhold(p->p_ucred);
+               PROC_UNLOCK(p);
+               racct_proc_ucred_changed(p, cred, cred);
+               crfree(cred);
+       }
+
+       sx_sunlock(&allproc_lock);
+       prison_racct_free_locked(oldprr);
+       sx_xunlock(&allprison_lock);
+}
+
 static void
 prison_racct_detach(struct prison *pr)
 {
+
+       sx_assert(&allprison_lock, SA_UNLOCKED);
+
        prison_racct_free(pr->pr_prison_racct);
        pr->pr_prison_racct = NULL;
 }

Modified: head/sys/kern/kern_racct.c
==============================================================================
--- head/sys/kern/kern_racct.c  Tue Mar  6 10:51:53 2012        (r232597)
+++ head/sys/kern/kern_racct.c  Tue Mar  6 11:05:50 2012        (r232598)
@@ -697,6 +697,18 @@ racct_proc_ucred_changed(struct proc *p,
 #endif
 }
 
+void
+racct_move(struct racct *dest, struct racct *src)
+{
+
+       mtx_lock(&racct_lock);
+
+       racct_add_racct(dest, src);
+       racct_sub_racct(src, src);
+
+       mtx_unlock(&racct_lock);
+}
+
 static void
 racctd(void)
 {

Modified: head/sys/sys/racct.h
==============================================================================
--- head/sys/sys/racct.h        Tue Mar  6 10:51:53 2012        (r232597)
+++ head/sys/sys/racct.h        Tue Mar  6 11:05:50 2012        (r232598)
@@ -142,5 +142,6 @@ void        racct_proc_exit(struct proc *p);
 
 void   racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
            struct ucred *newcred);
+void   racct_move(struct racct *dest, struct racct *src);
 
 #endif /* !_RACCT_H_ */
_______________________________________________
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