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 <[EMAIL PROTECTED]>


---

 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

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
ckrm-tech mailing list
https://lists.sourceforge.net/lists/listinfo/ckrm-tech

Reply via email to