aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2012-03-06 11:05:50 +0000
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2012-03-06 11:05:50 +0000
commitc34bbd2ada0556d2a3ac22f75d8d5867abde4937 (patch)
tree7a64374cfdc1339c1dbffde31e6953e9da0dd06f
parent8b7b8e14a8698814ae2ffb678f5af4bb6236dbc7 (diff)
downloadsrc-c34bbd2ada0556d2a3ac22f75d8d5867abde4937.tar.gz
src-c34bbd2ada0556d2a3ac22f75d8d5867abde4937.zip
Make racct and rctl correctly handle jail renaming. Previously
they would continue using old name, the one jail was created with. PR: bin/165207
Notes
Notes: svn path=/head/; revision=232598
-rw-r--r--sys/kern/kern_jail.c79
-rw-r--r--sys/kern/kern_racct.c12
-rw-r--r--sys/sys/racct.h1
3 files changed, 84 insertions, 8 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index c96d271a20cd..b782b977500e 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -130,6 +130,7 @@ static char *prison_path(struct prison *pr1, struct prison *pr2);
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 uio *optuio, int flags)
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 *prr)
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;
}
diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c
index ac0e98d8bb4e..b1008bc490d1 100644
--- a/sys/kern/kern_racct.c
+++ b/sys/kern/kern_racct.c
@@ -697,6 +697,18 @@ racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
#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)
{
diff --git a/sys/sys/racct.h b/sys/sys/racct.h
index 095932c22f9a..b4aeee8d21f8 100644
--- a/sys/sys/racct.h
+++ b/sys/sys/racct.h
@@ -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_ */