|
@@ -7159,7 +7159,6 @@ static void free_sched_group(struct task_group *tg)
|
|
|
struct task_group *sched_create_group(struct task_group *parent)
|
|
|
{
|
|
|
struct task_group *tg;
|
|
|
- unsigned long flags;
|
|
|
|
|
|
tg = kzalloc(sizeof(*tg), GFP_KERNEL);
|
|
|
if (!tg)
|
|
@@ -7171,6 +7170,17 @@ struct task_group *sched_create_group(struct task_group *parent)
|
|
|
if (!alloc_rt_sched_group(tg, parent))
|
|
|
goto err;
|
|
|
|
|
|
+ return tg;
|
|
|
+
|
|
|
+err:
|
|
|
+ free_sched_group(tg);
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+}
|
|
|
+
|
|
|
+void sched_online_group(struct task_group *tg, struct task_group *parent)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
spin_lock_irqsave(&task_group_lock, flags);
|
|
|
list_add_rcu(&tg->list, &task_groups);
|
|
|
|
|
@@ -7180,12 +7190,6 @@ struct task_group *sched_create_group(struct task_group *parent)
|
|
|
INIT_LIST_HEAD(&tg->children);
|
|
|
list_add_rcu(&tg->siblings, &parent->children);
|
|
|
spin_unlock_irqrestore(&task_group_lock, flags);
|
|
|
-
|
|
|
- return tg;
|
|
|
-
|
|
|
-err:
|
|
|
- free_sched_group(tg);
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
}
|
|
|
|
|
|
/* rcu callback to free various structures associated with a task group */
|
|
@@ -7197,6 +7201,12 @@ static void free_sched_group_rcu(struct rcu_head *rhp)
|
|
|
|
|
|
/* Destroy runqueue etc associated with a task group */
|
|
|
void sched_destroy_group(struct task_group *tg)
|
|
|
+{
|
|
|
+ /* wait for possible concurrent references to cfs_rqs complete */
|
|
|
+ call_rcu(&tg->rcu, free_sched_group_rcu);
|
|
|
+}
|
|
|
+
|
|
|
+void sched_offline_group(struct task_group *tg)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
int i;
|
|
@@ -7209,9 +7219,6 @@ void sched_destroy_group(struct task_group *tg)
|
|
|
list_del_rcu(&tg->list);
|
|
|
list_del_rcu(&tg->siblings);
|
|
|
spin_unlock_irqrestore(&task_group_lock, flags);
|
|
|
-
|
|
|
- /* wait for possible concurrent references to cfs_rqs complete */
|
|
|
- call_rcu(&tg->rcu, free_sched_group_rcu);
|
|
|
}
|
|
|
|
|
|
/* change task's runqueue when it moves between groups.
|
|
@@ -7563,6 +7570,19 @@ static struct cgroup_subsys_state *cpu_cgroup_css_alloc(struct cgroup *cgrp)
|
|
|
return &tg->css;
|
|
|
}
|
|
|
|
|
|
+static int cpu_cgroup_css_online(struct cgroup *cgrp)
|
|
|
+{
|
|
|
+ struct task_group *tg = cgroup_tg(cgrp);
|
|
|
+ struct task_group *parent;
|
|
|
+
|
|
|
+ if (!cgrp->parent)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ parent = cgroup_tg(cgrp->parent);
|
|
|
+ sched_online_group(tg, parent);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void cpu_cgroup_css_free(struct cgroup *cgrp)
|
|
|
{
|
|
|
struct task_group *tg = cgroup_tg(cgrp);
|
|
@@ -7570,6 +7590,13 @@ static void cpu_cgroup_css_free(struct cgroup *cgrp)
|
|
|
sched_destroy_group(tg);
|
|
|
}
|
|
|
|
|
|
+static void cpu_cgroup_css_offline(struct cgroup *cgrp)
|
|
|
+{
|
|
|
+ struct task_group *tg = cgroup_tg(cgrp);
|
|
|
+
|
|
|
+ sched_offline_group(tg);
|
|
|
+}
|
|
|
+
|
|
|
static int cpu_cgroup_can_attach(struct cgroup *cgrp,
|
|
|
struct cgroup_taskset *tset)
|
|
|
{
|
|
@@ -7925,6 +7952,8 @@ struct cgroup_subsys cpu_cgroup_subsys = {
|
|
|
.name = "cpu",
|
|
|
.css_alloc = cpu_cgroup_css_alloc,
|
|
|
.css_free = cpu_cgroup_css_free,
|
|
|
+ .css_online = cpu_cgroup_css_online,
|
|
|
+ .css_offline = cpu_cgroup_css_offline,
|
|
|
.can_attach = cpu_cgroup_can_attach,
|
|
|
.attach = cpu_cgroup_attach,
|
|
|
.exit = cpu_cgroup_exit,
|