[Devel] [PATCH 9/9] Interface with process container patchset

Srivatsa Vaddagiri vatsa at in.ibm.com
Thu Apr 12 11:01:27 PDT 2007


This patch registers cpu controller as a subsystem in process container
patches.

How to use the controller:


        1. Apply these patches first on top of 2.6.20 kernel
                http://lkml.org/lkml/2007/4/6/301
                http://lkml.org/lkml/2007/4/6/300
                http://marc.info/?l=ckrm-tech&m=117590464104300&w=2

        2. Apply all patches in this thread (from 1 - 9)

        3. Select CONFIG_CPUMETER and build kernel

After bootup:

        # mkdir /dev/cpuctl
        # mount -t container -o cpuctl none /dev/cpuctl
        # cd /dev/cpuctl
        # mkdir a       # Create group A
        # mkdir b       # Create group B

        # echo 80 > a/quota     # Give 80% quota to A
        # echo 20 > b/quota     # Give 20% quota to B

        # echo some_pid > a/tasks       # Move some_pid to Group A

        # echo another_pid > b/tasks    # move another task to Group B


some_pid and another_pid should share CPU in the ratio of 80:20 now

Signed-off-by : Srivatsa Vaddagiri <vatsa at in.ibm.com>


---

 linux-2.6.20-vatsa/include/linux/container_subsys.h |    6 


---


diff -puN include/linux/container_subsys.h~container_if include/linux/container_subsys.h
--- linux-2.6.20/include/linux/container_subsys.h~container_if	2007-04-12 09:10:40.000000000 +0530
+++ linux-2.6.20-vatsa/include/linux/container_subsys.h	2007-04-12 09:10:40.000000000 +0530
@@ -17,4 +17,10 @@ SUBSYS(cpuacct)
 
 /* */
 
+#ifdef CONFIG_CPUMETER
+SUBSYS(cpuctlr)
+#endif
+
+/* */
+
 /* */
diff -puN kernel/sched.c~container_if kernel/sched.c
--- linux-2.6.20/kernel/sched.c~container_if	2007-04-12 09:10:40.000000000 +0530
+++ linux-2.6.20-vatsa/kernel/sched.c	2007-04-12 11:07:10.000000000 +0530
@@ -53,6 +53,8 @@
 #include <linux/kprobes.h>
 #include <linux/delayacct.h>
 #include <linux/cpu_acct.h>
+#include <linux/container.h>
+#include <linux/fs.h>
 #include <asm/tlb.h>
 
 #include <asm/unistd.h>
@@ -226,6 +228,7 @@ static DEFINE_PER_CPU(struct task_grp_rq
 
 /* task-group object - maintains information about each task-group */
 struct task_grp {
+	struct container_subsys_state css;
 	unsigned short ticks, long_ticks; /* bandwidth given to task-group */
  	int left_over_pct;
  	int total_dont_care_grps;
@@ -430,10 +433,8 @@ static inline void finish_lock_switch(st
 /* return the task-group to which a task belongs */
 static inline struct task_grp *task_grp(struct task_struct *p)
 {
-	/* Simply return the default group for now. A later patch modifies
-	 * this function.
-	 */
-	return &init_task_grp;
+	return container_of(task_subsys_state(p, cpuctlr_subsys_id),
+		struct task_grp, css);
 }
 
 /*
@@ -7487,6 +7488,12 @@ void set_curr_task(int cpu, struct task_
 
 #ifdef CONFIG_CPUMETER
 
+static struct task_grp *container_tg(struct container *cont)
+{
+	return container_of(container_subsys_state(cont, cpuctlr_subsys_id),
+				struct task_grp, css);
+}
+
 /* Distribute left over bandwidth equally to all "dont care" task groups */
 static void recalc_dontcare(struct task_grp *tg_root)
 {
@@ -7511,16 +7518,26 @@ static void recalc_dontcare(struct task_
 }
 
 /* Allocate runqueue structures for the new task-group */
-static int sched_create_group(struct task_grp *tg_parent)
+static int sched_create_group(struct container_subsys *ss,
+				struct container *cont)
 {
-	struct task_grp *tg;
+	struct task_grp *tg, *tg_parent;
 	struct task_grp_rq *tgrq;
 	int i;
 
-	if (tg_parent->parent)
+	if (!cont->parent) {
+		/* This is early initialization for the top container */
+		cont->subsys[cpuctlr_subsys_id] = &init_task_grp.css;
+		init_task_grp.css.container = cont;
+		return 0;
+	}
+
+	if (cont->parent->parent)
 		/* We don't support hierarchical CPU res mgmt (yet) */
 		return -EINVAL;
 
+	tg_parent = container_tg(cont->parent);
+
 	tg = kzalloc(sizeof(*tg), GFP_KERNEL);
 	if (!tg)
 		return -ENOMEM;
@@ -7549,7 +7566,9 @@ static int sched_create_group(struct tas
 		list_add_tail(&tg->list, &tg->dont_care_list);
 	}
 
-	/* A later patch will make 'tg' accessible beyond this function */
+	cont->subsys[cpuctlr_subsys_id] = &tg->css;
+	tg->css.container = cont;
+
 	return 0;
 oom:
 	while (i--)
@@ -7560,9 +7579,11 @@ oom:
 }
 
 /* Deallocate runqueue structures */
-static void sched_destroy_group(struct task_grp *tg)
+static void sched_destroy_group(struct container_subsys *ss,
+				 struct container *cont)
 {
 	int i;
+	struct task_grp *tg = container_tg(cont);
 	struct task_grp *tg_root = tg->parent;
 
 	if (!tg_root)
@@ -7581,10 +7602,22 @@ static void sched_destroy_group(struct t
 }
 
 /* Assign quota to this group */
-static int sched_set_quota(struct task_grp *tg, int quota)
+static ssize_t sched_set_quota(struct container *cont, struct cftype *cft,
+			struct file *file, const char __user *userbuf,
+			size_t nbytes, loff_t *ppos)
 {
+	struct task_grp *tg = container_tg(cont);
 	int i, old_quota = 0;
 	struct task_grp *tg_root = tg->parent;
+	int quota;
+	char buffer[64];
+
+	if (copy_from_user(buffer, userbuf, sizeof(quota)))
+                return -EFAULT;
+
+	buffer[sizeof(quota)] = 0;
+
+	quota = simple_strtoul(buffer, NULL, 10);
 
 	if (!tg_root)
 		tg_root = tg;
@@ -7611,16 +7644,29 @@ static int sched_set_quota(struct task_g
 	tg_root->left_over_pct -= (quota - old_quota);
 	recalc_dontcare(tg_root);
 
-	return 0;
+	return nbytes;
 }
 
 /* Return assigned quota for this group */
-static int sched_get_quota(struct task_grp *tg)
-{
+static ssize_t sched_get_quota(struct container *cont, struct cftype *cft,
+			struct file *file, char __user *buf, size_t nbytes,
+			loff_t *ppos)
+{
+	struct task_grp *tg = container_tg(cont);
+	char quotabuf[64];
+	char *s = quotabuf;
+	int quota;
+
 	if (tg->dont_care)
-		return 0;
+		quota = 0;
 	else
-		return cpu_quota(tg);
+		quota = cpu_quota(tg);
+
+	s += sprintf(s, "%d\n", quota);
+
+	return simple_read_from_buffer(buf, nbytes, ppos, quotabuf,
+					 s - quotabuf);
+
 }
 
 /*
@@ -7628,23 +7674,35 @@ static int sched_get_quota(struct task_g
  * runqueue, this involves removing the task from its old group's runqueue
  * and adding to its new group's runqueue.
  */
-static void sched_move_task(struct task_grp *tg_new, struct task_grp *tg_old,
-					struct task_struct *tsk)
+static void sched_move_task(struct container_subsys *ss, struct container *cont,
+			struct container *old_cont, struct task_struct *tsk)
 {
 	struct rq *rq;
 	unsigned long flags;
 
-	if (tg_new == tg_old)
-		return;
-
 	rq = task_rq_lock(tsk, &flags);
 
 	if (tsk->array) {
-		/* Set tsk->group to tg_old here */
+		struct task_grp *tg_old, *tg_new;
+
+		task_lock(tsk);
+
+		tg_old = container_tg(old_cont);
+		tg_new = container_tg(cont);
+
+		/* deactivate_task and activate_task rely on
+		 * tsk->containers->subsys[cpuctlr_subsys_id] to know the
+		 * appropritate group from which the task has to be dequeued
+		 * and queued. Modify that appropriately before invoking them
+		 */
+		tsk->containers->subsys[cpuctlr_subsys_id] = &tg_old->css;
 		deactivate_task(tsk, rq);
-		/* Set tsk->group to tg_new here */
+
+		tsk->containers->subsys[cpuctlr_subsys_id] = &tg_new->css;
 		set_load_weight(tsk);
 		__activate_task(tsk, rq);
+
+		task_unlock(tsk);
 	}
 
 	task_rq_unlock(rq, &flags);
@@ -7652,4 +7710,49 @@ static void sched_move_task(struct task_
 	return;
 }
 
+static struct cftype cft_quota = {
+	.name = "quota",
+	.read = sched_get_quota,
+	.write = sched_set_quota,
+};
+
+static int sched_populate(struct container_subsys *ss, struct container *cont)
+{
+	int err;
+
+	if ((err = container_add_file(cont, &cft_quota)))
+		return err;
+
+	return err;
+}
+
+static void sched_exit_task(struct container_subsys *ss, struct task_struct *p)
+{
+	struct rq *rq;
+	unsigned long flags;
+
+	rq = task_rq_lock(p, &flags);
+
+	if (p->array) {
+		struct task_grp_rq *init_tgrq = init_task_grp.rq[task_cpu(p)];
+
+		dequeue_task(p, p->array);
+		enqueue_task(p, init_tgrq->active);
+	}
+
+	task_rq_unlock(rq, &flags);
+}
+
+
+struct container_subsys cpuctlr_subsys = {
+	.name = "cpuctl",
+	.create = sched_create_group,
+	.destroy  = sched_destroy_group,
+	.attach = sched_move_task,
+	.populate = sched_populate,
+	.subsys_id = cpuctlr_subsys_id,
+	.exit = sched_exit_task,
+	.early_init = 1,
+};
+
 #endif /* CONFIG_CPUMETER */
_

-- 
Regards,
vatsa
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers




More information about the Devel mailing list