2014-07-02 23:51:03

by Tejun Heo

[permalink] [raw]
Subject: [PATCHSET cgroup/for-3.17] cgroup: distinguish the default and legacy hierarchies when handling cftypes

Hello,

Until now, cftype arrays carried files for both the default and legacy
hierarchies and the files which needed to be used on only one of them
were flagged with either CFTYPE_ONLY_ON_DFL or CFTYPE_INSANE. This
gets confusing very quickly and we may end up exposing interface files
to the default hierarchy without thinking it through.

This patchset makes cgroup core provide separate sets of interfaces
for cftype handling so that the cftypes for the default and legacy
hierarchies are clearly distinguished. This makes all the existing
subsystem interface files legacy-only by default and all subsystems
will have no interface file created when enabled on the default
hierarchy. Each subsystem should explicitly review and compose the
interface for the default hierarchy.

This patchset contains the following five patches.

0001-cgroup-split-cgroup_base_files-into-cgroup_-dfl-lega.patch
0002-cgroup-rename-cgroup_subsys-base_cftypes-to-legacy_c.patch
0003-cgroup-replace-cgroup_add_cftypes-with-cgroup_add_le.patch
0004-cgroup-distinguish-the-default-and-legacy-hierarchie.patch
0005-cgroup-make-CFTYPE_ONLY_ON_DFL-and-CFTYPE_NO_-intern.patch

This patchset is on top of

a497c3ba1d97 ("Linux 3.16-rc2")
+ [1] [PATCHSET cgroup/for-3.17] cgroup: remove sane_behavior support on non-default hierarchies

and available in the following git branch.

git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git review-dfl_files

diffstat follows. Thanks.

block/blk-cgroup.c | 5 -
include/linux/cgroup.h | 17 +++--
kernel/cgroup.c | 146 ++++++++++++++++++++++++++++++++-----------
kernel/cgroup_freezer.c | 2
kernel/cpuset.c | 2
kernel/sched/core.c | 2
kernel/sched/cpuacct.c | 2
mm/hugetlb_cgroup.c | 5 -
mm/memcontrol.c | 6 -
net/core/netclassid_cgroup.c | 2
net/core/netprio_cgroup.c | 2
net/ipv4/tcp_memcontrol.c | 2
security/device_cgroup.c | 2
13 files changed, 139 insertions(+), 56 deletions(-)

--
tejun

[1] http://lkml.kernel.org/g/[email protected]


2014-07-02 23:51:06

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 3/5] cgroup: replace cgroup_add_cftypes() with cgroup_add_legacy_cftypes()

Currently, cftypes added by cgroup_add_cftypes() are used for both the
unified default hierarchy and legacy ones and subsystems can mark each
file with either CFTYPE_ONLY_ON_DFL or CFTYPE_INSANE if it has to
appear only on one of them. This is quite hairy and error-prone.
Also, we may end up exposing interface files to the default hierarchy
without thinking it through.

cgroup_subsys will grow two separate cftype addition functions and
apply each only on the hierarchies of the matching type. This will
allow organizing cftypes in a lot clearer way and encourage subsystems
to scrutinize the interface which is being exposed in the new default
hierarchy.

In preparation, this patch adds cgroup_add_legacy_cftypes() which
currently is a simple wrapper around cgroup_add_cftypes() and replaces
all cgroup_add_cftypes() usages with it.

While at it, this patch drops a completely spurious return from
__hugetlb_cgroup_file_init().

This patch doesn't introduce any functional differences.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Neil Horman <[email protected]>
Cc: Aneesh Kumar K.V <[email protected]>
---
block/blk-cgroup.c | 3 ++-
include/linux/cgroup.h | 2 +-
kernel/cgroup.c | 7 ++++++-
mm/hugetlb_cgroup.c | 5 ++---
mm/memcontrol.c | 3 ++-
net/ipv4/tcp_memcontrol.c | 2 +-
6 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index d8a331d..3885775 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1116,7 +1116,8 @@ int __init blkcg_policy_register(struct blkcg_policy *pol)

/* everything is in place, add intf files for the new policy */
if (pol->cftypes)
- WARN_ON(cgroup_add_cftypes(&blkio_cgrp_subsys, pol->cftypes));
+ WARN_ON(cgroup_add_legacy_cftypes(&blkio_cgrp_subsys,
+ pol->cftypes));
ret = 0;
out_unlock:
mutex_unlock(&blkcg_pol_mutex);
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index c75742c..a75a37f 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -582,7 +582,7 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp)

char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);

-int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
+int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
int cgroup_rm_cftypes(struct cftype *cfts);

bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 51b67fc..311d42b 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -3060,7 +3060,7 @@ int cgroup_rm_cftypes(struct cftype *cfts)
* function currently returns 0 as long as @cfts registration is successful
* even if some file creation attempts on existing cgroups fail.
*/
-int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
+static int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
{
int ret;

@@ -3085,6 +3085,11 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
return ret;
}

+int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
+{
+ return cgroup_add_cftypes(ss, cfts);
+}
+
/**
* cgroup_task_count - count the number of tasks in a cgroup.
* @cgrp: the cgroup in question
diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c
index 493f758..9aae6f4 100644
--- a/mm/hugetlb_cgroup.c
+++ b/mm/hugetlb_cgroup.c
@@ -358,9 +358,8 @@ static void __init __hugetlb_cgroup_file_init(int idx)
cft = &h->cgroup_files[4];
memset(cft, 0, sizeof(*cft));

- WARN_ON(cgroup_add_cftypes(&hugetlb_cgrp_subsys, h->cgroup_files));
-
- return;
+ WARN_ON(cgroup_add_legacy_cftypes(&hugetlb_cgrp_subsys,
+ h->cgroup_files));
}

void __init hugetlb_cgroup_file_init(void)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 0dd9378..a629611 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -7041,7 +7041,8 @@ __setup("swapaccount=", enable_swap_account);

static void __init memsw_file_init(void)
{
- WARN_ON(cgroup_add_cftypes(&memory_cgrp_subsys, memsw_cgroup_files));
+ WARN_ON(cgroup_add_legacy_cftypes(&memory_cgrp_subsys,
+ memsw_cgroup_files));
}

static void __init enable_swap_cgroup(void)
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c
index f7a2ec3..3af5226 100644
--- a/net/ipv4/tcp_memcontrol.c
+++ b/net/ipv4/tcp_memcontrol.c
@@ -222,7 +222,7 @@ static struct cftype tcp_files[] = {

static int __init tcp_memcontrol_init(void)
{
- WARN_ON(cgroup_add_cftypes(&memory_cgrp_subsys, tcp_files));
+ WARN_ON(cgroup_add_legacy_cftypes(&memory_cgrp_subsys, tcp_files));
return 0;
}
__initcall(tcp_memcontrol_init);
--
1.9.3

2014-07-02 23:51:09

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 5/5] cgroup: make CFTYPE_ONLY_ON_DFL and CFTYPE_NO_ internal to cgroup core

cgroup now distinguishes cftypes for the default and legacy
hierarchies more explicitly by using separate arrays and
CFTYPE_ONLY_ON_DFL and CFTYPE_INSANE should be and are used only
inside cgroup core proper. Let's make it clear that the flags are
internal by prefixing them with double underscores.

CFTYPE_INSANE is renamed to __CFTYPE_NOT_ON_DFL for consistency. The
two flags are also collected and assigned bits >= 16 so that they
aren't mixed with the published flags.

Signed-off-by: Tejun Heo <[email protected]>
---
include/linux/cgroup.h | 6 ++++--
kernel/cgroup.c | 8 ++++----
2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 62a2be1..c047887c 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -376,9 +376,11 @@ struct css_set {
enum {
CFTYPE_ONLY_ON_ROOT = (1 << 0), /* only create on root cgrp */
CFTYPE_NOT_ON_ROOT = (1 << 1), /* don't create on root cgrp */
- CFTYPE_INSANE = (1 << 2), /* don't create if sane_behavior */
CFTYPE_NO_PREFIX = (1 << 3), /* (DON'T USE FOR NEW FILES) no subsys prefix */
- CFTYPE_ONLY_ON_DFL = (1 << 4), /* only on default hierarchy */
+
+ /* internal flags, do not use outside cgroup core proper */
+ __CFTYPE_ONLY_ON_DFL = (1 << 16), /* only on default hierarchy */
+ __CFTYPE_NOT_ON_DFL = (1 << 17), /* not on default hierarchy */
};

#define MAX_CFTYPE_NAME 64
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 94cdb7b..028ebf1 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2921,9 +2921,9 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],

for (cft = cfts; cft->name[0] != '\0'; cft++) {
/* does cft->flags tell us to skip this file on @cgrp? */
- if ((cft->flags & CFTYPE_ONLY_ON_DFL) && !cgroup_on_dfl(cgrp))
+ if ((cft->flags & __CFTYPE_ONLY_ON_DFL) && !cgroup_on_dfl(cgrp))
continue;
- if ((cft->flags & CFTYPE_INSANE) && cgroup_on_dfl(cgrp))
+ if ((cft->flags & __CFTYPE_NOT_ON_DFL) && cgroup_on_dfl(cgrp))
continue;
if ((cft->flags & CFTYPE_NOT_ON_ROOT) && !cgroup_parent(cgrp))
continue;
@@ -3104,7 +3104,7 @@ int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
struct cftype *cft;

for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
- cft->flags |= CFTYPE_ONLY_ON_DFL;
+ cft->flags |= __CFTYPE_ONLY_ON_DFL;
return cgroup_add_cftypes(ss, cfts);
}

@@ -3121,7 +3121,7 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
struct cftype *cft;

for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
- cft->flags |= CFTYPE_INSANE;
+ cft->flags |= __CFTYPE_NOT_ON_DFL;
return cgroup_add_cftypes(ss, cfts);
}

--
1.9.3

2014-07-02 23:51:49

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 4/5] cgroup: distinguish the default and legacy hierarchies when handling cftypes

Until now, cftype arrays carried files for both the default and legacy
hierarchies and the files which needed to be used on only one of them
were flagged with either CFTYPE_ONLY_ON_DFL or CFTYPE_INSANE. This
gets confusing very quickly and we may end up exposing interface files
to the default hierarchy without thinking it through.

This patch makes cgroup core provide separate sets of interfaces for
cftype handling so that the cftypes for the default and legacy
hierarchies are clearly distinguished. The previous two patches
renamed the existing ones so that they clearly indicate that they're
for the legacy hierarchies. This patch adds the interface for the
default hierarchy and apply them selectively depending on the
hierarchy type.

* cftypes added through cgroup_subsys->dfl_cftypes and
cgroup_add_dfl_cftypes() only show up on the default hierarchy.

* cftypes added through cgroup_subsys->legacy_cftypes and
cgroup_add_legacy_cftypes() only show up on the legacy hierarchies.

* cgroup_subsys->dfl_cftypes and ->legacy_cftypes can point to the
same array for the cases where the interface files are identical on
both types of hierarchies.

* This makes all the existing subsystem interface files legacy-only by
default and all subsystems will have no interface file created when
enabled on the default hierarchy. Each subsystem should explicitly
review and compose the interface for the default hierarchy.

* A boot param "cgroup__DEVEL__legacy_files_on_dfl" is added which
makes subsystems which haven't decided the interface files for the
default hierarchy to present the legacy files on the default
hierarchy so that its behavior on the default hierarchy can be
tested. As the awkward name suggests, this is for development only.

* memcg's CFTYPE_INSANE on "use_hierarchy" is noop now as the whole
array isn't used on the default hierarchy. The flag is removed.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Li Zefan <[email protected]>
Cc: Vivek Goyal <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Aristeu Rozanski <[email protected]>
Cc: Neil Horman <[email protected]>
Cc: Aneesh Kumar K.V <[email protected]>
---
include/linux/cgroup.h | 9 ++++++--
kernel/cgroup.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++---
mm/memcontrol.c | 1 -
3 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index a75a37f..62a2be1 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -582,6 +582,7 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp)

char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);

+int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
int cgroup_rm_cftypes(struct cftype *cfts);

@@ -662,8 +663,12 @@ struct cgroup_subsys {
*/
struct list_head cfts;

- /* base cftypes, automatically registered with subsys itself */
- struct cftype *legacy_cftypes; /* used on the legacy hierarchies */
+ /*
+ * Base cftypes which are automatically registered. The two can
+ * point to the same array.
+ */
+ struct cftype *dfl_cftypes; /* for the default hierarchy */
+ struct cftype *legacy_cftypes; /* for the legacy hierarchies */
};

#define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 311d42b..94cdb7b 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -149,6 +149,12 @@ struct cgroup_root cgrp_dfl_root;
*/
static bool cgrp_dfl_root_visible;

+/*
+ * Set by the boot param of the same name and makes subsystems with NULL
+ * ->dfl_files to use ->legacy_files on the default hierarchy.
+ */
+static bool cgroup_legacy_files_on_dfl;
+
/* some controllers are not supported in the default hierarchy */
static const unsigned int cgrp_dfl_root_inhibit_ss_mask = 0
#ifdef CONFIG_CGROUP_DEBUG
@@ -3085,8 +3091,37 @@ static int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
return ret;
}

+/**
+ * cgroup_add_dfl_cftypes - add an array of cftypes for default hierarchy
+ * @ss: target cgroup subsystem
+ * @cfts: zero-length name terminated array of cftypes
+ *
+ * Similar to cgroup_add_cftypes() but the added files are only used for
+ * the default hierarchy.
+ */
+int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
+{
+ struct cftype *cft;
+
+ for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
+ cft->flags |= CFTYPE_ONLY_ON_DFL;
+ return cgroup_add_cftypes(ss, cfts);
+}
+
+/**
+ * cgroup_add_legacy_cftypes - add an array of cftypes for legacy hierarchies
+ * @ss: target cgroup subsystem
+ * @cfts: zero-length name terminated array of cftypes
+ *
+ * Similar to cgroup_add_cftypes() but the added files are only used for
+ * the legacy hierarchies.
+ */
int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
{
+ struct cftype *cft;
+
+ for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
+ cft->flags |= CFTYPE_INSANE;
return cgroup_add_cftypes(ss, cfts);
}

@@ -4775,9 +4810,19 @@ int __init cgroup_init(void)
* disabled flag and cftype registration needs kmalloc,
* both of which aren't available during early_init.
*/
- if (!ss->disabled) {
- cgrp_dfl_root.subsys_mask |= 1 << ss->id;
- WARN_ON(cgroup_add_cftypes(ss, ss->legacy_cftypes));
+ if (ss->disabled)
+ continue;
+
+ cgrp_dfl_root.subsys_mask |= 1 << ss->id;
+
+ if (cgroup_legacy_files_on_dfl && !ss->dfl_cftypes)
+ ss->dfl_cftypes = ss->legacy_cftypes;
+
+ if (ss->dfl_cftypes == ss->legacy_cftypes) {
+ WARN_ON(cgroup_add_cftypes(ss, ss->dfl_cftypes));
+ } else {
+ WARN_ON(cgroup_add_dfl_cftypes(ss, ss->dfl_cftypes));
+ WARN_ON(cgroup_add_legacy_cftypes(ss, ss->legacy_cftypes));
}
}

@@ -5173,6 +5218,13 @@ static int __init cgroup_disable(char *str)
}
__setup("cgroup_disable=", cgroup_disable);

+static int __init cgroup_set_legacy_files_on_dfl(char *str)
+{
+ cgroup_legacy_files_on_dfl = true;
+ return 0;
+}
+__setup("cgroup__DEVEL__legacy_files_on_dfl", cgroup_set_legacy_files_on_dfl);
+
/**
* css_tryget_online_from_dir - get corresponding css from a cgroup dentry
* @dentry: directory dentry of interest
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a629611..3b37586 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -6003,7 +6003,6 @@ static struct cftype mem_cgroup_files[] = {
},
{
.name = "use_hierarchy",
- .flags = CFTYPE_INSANE,
.write_u64 = mem_cgroup_hierarchy_write,
.read_u64 = mem_cgroup_hierarchy_read,
},
--
1.9.3

2014-07-02 23:52:24

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 2/5] cgroup: rename cgroup_subsys->base_cftypes to ->legacy_cftypes

Currently, cgroup_subsys->base_cftypes is used for both the unified
default hierarchy and legacy ones and subsystems can mark each file
with either CFTYPE_ONLY_ON_DFL or CFTYPE_INSANE if it has to appear
only on one of them. This is quite hairy and error-prone. Also, we
may end up exposing interface files to the default hierarchy without
thinking it through.

cgroup_subsys will grow two separate cftype arrays and apply each only
on the hierarchies of the matching type. This will allow organizing
cftypes in a lot clearer way and encourage subsystems to scrutinize
the interface which is being exposed in the new default hierarchy.

In preparation, this patch renames cgroup_subsys->base_cftypes to
cgroup_subsys->legacy_cftypes. This patch is pure rename.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Li Zefan <[email protected]>
Cc: Vivek Goyal <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Aristeu Rozanski <[email protected]>
Cc: Neil Horman <[email protected]>
Cc: Aneesh Kumar K.V <[email protected]>
---
block/blk-cgroup.c | 2 +-
include/linux/cgroup.h | 2 +-
kernel/cgroup.c | 4 ++--
kernel/cgroup_freezer.c | 2 +-
kernel/cpuset.c | 2 +-
kernel/sched/core.c | 2 +-
kernel/sched/cpuacct.c | 2 +-
mm/memcontrol.c | 2 +-
net/core/netclassid_cgroup.c | 2 +-
net/core/netprio_cgroup.c | 2 +-
security/device_cgroup.c | 2 +-
11 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 069bc20..d8a331d 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -924,7 +924,7 @@ struct cgroup_subsys blkio_cgrp_subsys = {
.css_offline = blkcg_css_offline,
.css_free = blkcg_css_free,
.can_attach = blkcg_can_attach,
- .base_cftypes = blkcg_files,
+ .legacy_cftypes = blkcg_files,
};
EXPORT_SYMBOL_GPL(blkio_cgrp_subsys);

diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 46e4661..c75742c 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -663,7 +663,7 @@ struct cgroup_subsys {
struct list_head cfts;

/* base cftypes, automatically registered with subsys itself */
- struct cftype *base_cftypes;
+ struct cftype *legacy_cftypes; /* used on the legacy hierarchies */
};

#define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 7210b3f..51b67fc 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4772,7 +4772,7 @@ int __init cgroup_init(void)
*/
if (!ss->disabled) {
cgrp_dfl_root.subsys_mask |= 1 << ss->id;
- WARN_ON(cgroup_add_cftypes(ss, ss->base_cftypes));
+ WARN_ON(cgroup_add_cftypes(ss, ss->legacy_cftypes));
}
}

@@ -5362,6 +5362,6 @@ static struct cftype debug_files[] = {
struct cgroup_subsys debug_cgrp_subsys = {
.css_alloc = debug_css_alloc,
.css_free = debug_css_free,
- .base_cftypes = debug_files,
+ .legacy_cftypes = debug_files,
};
#endif /* CONFIG_CGROUP_DEBUG */
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index a79e40f..92b98cc 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -480,5 +480,5 @@ struct cgroup_subsys freezer_cgrp_subsys = {
.css_free = freezer_css_free,
.attach = freezer_attach,
.fork = freezer_fork,
- .base_cftypes = files,
+ .legacy_cftypes = files,
};
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index f9d4807..3d3150c 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1953,7 +1953,7 @@ struct cgroup_subsys cpuset_cgrp_subsys = {
.can_attach = cpuset_can_attach,
.cancel_attach = cpuset_cancel_attach,
.attach = cpuset_attach,
- .base_cftypes = files,
+ .legacy_cftypes = files,
.early_init = 1,
};

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 3bdf01b..6628e80 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8088,7 +8088,7 @@ struct cgroup_subsys cpu_cgrp_subsys = {
.can_attach = cpu_cgroup_can_attach,
.attach = cpu_cgroup_attach,
.exit = cpu_cgroup_exit,
- .base_cftypes = cpu_files,
+ .legacy_cftypes = cpu_files,
.early_init = 1,
};

diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
index 9cf350c..dd7cbb5 100644
--- a/kernel/sched/cpuacct.c
+++ b/kernel/sched/cpuacct.c
@@ -278,6 +278,6 @@ void cpuacct_account_field(struct task_struct *p, int index, u64 val)
struct cgroup_subsys cpuacct_cgrp_subsys = {
.css_alloc = cpuacct_css_alloc,
.css_free = cpuacct_css_free,
- .base_cftypes = files,
+ .legacy_cftypes = files,
.early_init = 1,
};
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index f986671..0dd9378 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -7024,7 +7024,7 @@ struct cgroup_subsys memory_cgrp_subsys = {
.cancel_attach = mem_cgroup_cancel_attach,
.attach = mem_cgroup_move_task,
.bind = mem_cgroup_bind,
- .base_cftypes = mem_cgroup_files,
+ .legacy_cftypes = mem_cgroup_files,
.early_init = 0,
};

diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c
index 30d903b..1f2a126 100644
--- a/net/core/netclassid_cgroup.c
+++ b/net/core/netclassid_cgroup.c
@@ -107,5 +107,5 @@ struct cgroup_subsys net_cls_cgrp_subsys = {
.css_online = cgrp_css_online,
.css_free = cgrp_css_free,
.attach = cgrp_attach,
- .base_cftypes = ss_files,
+ .legacy_cftypes = ss_files,
};
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index 2f385b9..cbd0a19 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -249,7 +249,7 @@ struct cgroup_subsys net_prio_cgrp_subsys = {
.css_online = cgrp_css_online,
.css_free = cgrp_css_free,
.attach = net_prio_attach,
- .base_cftypes = ss_files,
+ .legacy_cftypes = ss_files,
};

static int netprio_device_event(struct notifier_block *unused,
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index d9d69e6..188c1d2 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -796,7 +796,7 @@ struct cgroup_subsys devices_cgrp_subsys = {
.css_free = devcgroup_css_free,
.css_online = devcgroup_online,
.css_offline = devcgroup_offline,
- .base_cftypes = dev_cgroup_files,
+ .legacy_cftypes = dev_cgroup_files,
};

/**
--
1.9.3

2014-07-02 23:52:58

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 1/5] cgroup: split cgroup_base_files[] into cgroup_{dfl|legacy}_base_files[]

Currently cgroup_base_files[] contains the cgroup core interface files
for both legacy and default hierarchies with each file tagged with
CFTYPE_INSANE and CFTYPE_ONLY_ON_DFL. This is difficult to read.

Let's separate it out to two separate tables, cgroup_dfl_base_files[]
and cgroup_legacy_base_files[], and use the appropriate one in
cgroup_mkdir() depending on the hierarchy type. This makes tagging
each file unnecessary.

This patch doesn't introduce any behavior changes.

Signed-off-by: Tejun Heo <[email protected]>
---
kernel/cgroup.c | 75 ++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 47 insertions(+), 28 deletions(-)

diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 1c56924..7210b3f 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -180,7 +180,8 @@ static u64 css_serial_nr_next = 1;
*/
static int need_forkexit_callback __read_mostly;

-static struct cftype cgroup_base_files[];
+static struct cftype cgroup_dfl_base_files[];
+static struct cftype cgroup_legacy_base_files[];

static void cgroup_put(struct cgroup *cgrp);
static int rebind_subsystems(struct cgroup_root *dst_root,
@@ -1558,6 +1559,7 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned int ss_mask)
{
LIST_HEAD(tmp_links);
struct cgroup *root_cgrp = &root->cgrp;
+ struct cftype *base_files;
struct css_set *cset;
int i, ret;

@@ -1595,7 +1597,12 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned int ss_mask)
}
root_cgrp->kn = root->kf_root->kn;

- ret = cgroup_addrm_files(root_cgrp, cgroup_base_files, true);
+ if (root == &cgrp_dfl_root)
+ base_files = cgroup_dfl_base_files;
+ else
+ base_files = cgroup_legacy_base_files;
+
+ ret = cgroup_addrm_files(root_cgrp, base_files, true);
if (ret)
goto destroy_root;

@@ -3985,7 +3992,8 @@ static int cgroup_clone_children_write(struct cgroup_subsys_state *css,
return 0;
}

-static struct cftype cgroup_base_files[] = {
+/* cgroup core interface files for the default hierarchy */
+static struct cftype cgroup_dfl_base_files[] = {
{
.name = "cgroup.procs",
.seq_start = cgroup_pidlist_start,
@@ -3997,46 +4005,51 @@ static struct cftype cgroup_base_files[] = {
.mode = S_IRUGO | S_IWUSR,
},
{
- .name = "cgroup.clone_children",
- .flags = CFTYPE_INSANE,
- .read_u64 = cgroup_clone_children_read,
- .write_u64 = cgroup_clone_children_write,
- },
- {
- .name = "cgroup.sane_behavior",
- .flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT,
- .seq_show = cgroup_sane_behavior_show,
- },
- {
.name = "cgroup.controllers",
- .flags = CFTYPE_ONLY_ON_DFL | CFTYPE_ONLY_ON_ROOT,
+ .flags = CFTYPE_ONLY_ON_ROOT,
.seq_show = cgroup_root_controllers_show,
},
{
.name = "cgroup.controllers",
- .flags = CFTYPE_ONLY_ON_DFL | CFTYPE_NOT_ON_ROOT,
+ .flags = CFTYPE_NOT_ON_ROOT,
.seq_show = cgroup_controllers_show,
},
{
.name = "cgroup.subtree_control",
- .flags = CFTYPE_ONLY_ON_DFL,
.seq_show = cgroup_subtree_control_show,
.write = cgroup_subtree_control_write,
},
{
.name = "cgroup.populated",
- .flags = CFTYPE_ONLY_ON_DFL | CFTYPE_NOT_ON_ROOT,
+ .flags = CFTYPE_NOT_ON_ROOT,
.seq_show = cgroup_populated_show,
},
+};

- /*
- * Historical crazy stuff. These don't have "cgroup." prefix and
- * don't exist if sane_behavior. If you're depending on these, be
- * prepared to be burned.
- */
+/* cgroup core interface files for the legacy hierarchies */
+static struct cftype cgroup_legacy_base_files[] = {
+ {
+ .name = "cgroup.procs",
+ .seq_start = cgroup_pidlist_start,
+ .seq_next = cgroup_pidlist_next,
+ .seq_stop = cgroup_pidlist_stop,
+ .seq_show = cgroup_pidlist_show,
+ .private = CGROUP_FILE_PROCS,
+ .write = cgroup_procs_write,
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ {
+ .name = "cgroup.clone_children",
+ .read_u64 = cgroup_clone_children_read,
+ .write_u64 = cgroup_clone_children_write,
+ },
+ {
+ .name = "cgroup.sane_behavior",
+ .flags = CFTYPE_ONLY_ON_ROOT,
+ .seq_show = cgroup_sane_behavior_show,
+ },
{
.name = "tasks",
- .flags = CFTYPE_INSANE, /* use "procs" instead */
.seq_start = cgroup_pidlist_start,
.seq_next = cgroup_pidlist_next,
.seq_stop = cgroup_pidlist_stop,
@@ -4047,13 +4060,12 @@ static struct cftype cgroup_base_files[] = {
},
{
.name = "notify_on_release",
- .flags = CFTYPE_INSANE,
.read_u64 = cgroup_read_notify_on_release,
.write_u64 = cgroup_write_notify_on_release,
},
{
.name = "release_agent",
- .flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT,
+ .flags = CFTYPE_ONLY_ON_ROOT,
.seq_show = cgroup_release_agent_show,
.write = cgroup_release_agent_write,
.max_write_len = PATH_MAX - 1,
@@ -4330,6 +4342,7 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
struct cgroup_root *root;
struct cgroup_subsys *ss;
struct kernfs_node *kn;
+ struct cftype *base_files;
int ssid, ret;

parent = cgroup_kn_lock_live(parent_kn);
@@ -4400,7 +4413,12 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
if (ret)
goto out_destroy;

- ret = cgroup_addrm_files(cgrp, cgroup_base_files, true);
+ if (cgroup_on_dfl(cgrp))
+ base_files = cgroup_dfl_base_files;
+ else
+ base_files = cgroup_legacy_base_files;
+
+ ret = cgroup_addrm_files(cgrp, base_files, true);
if (ret)
goto out_destroy;

@@ -4719,7 +4737,8 @@ int __init cgroup_init(void)
unsigned long key;
int ssid, err;

- BUG_ON(cgroup_init_cftypes(NULL, cgroup_base_files));
+ BUG_ON(cgroup_init_cftypes(NULL, cgroup_dfl_base_files));
+ BUG_ON(cgroup_init_cftypes(NULL, cgroup_legacy_base_files));

mutex_lock(&cgroup_mutex);

--
1.9.3

2014-07-03 11:03:11

by Neil Horman

[permalink] [raw]
Subject: Re: [PATCH 2/5] cgroup: rename cgroup_subsys->base_cftypes to ->legacy_cftypes

On Wed, Jul 02, 2014 at 07:50:52PM -0400, Tejun Heo wrote:
> Currently, cgroup_subsys->base_cftypes is used for both the unified
> default hierarchy and legacy ones and subsystems can mark each file
> with either CFTYPE_ONLY_ON_DFL or CFTYPE_INSANE if it has to appear
> only on one of them. This is quite hairy and error-prone. Also, we
> may end up exposing interface files to the default hierarchy without
> thinking it through.
>
> cgroup_subsys will grow two separate cftype arrays and apply each only
> on the hierarchies of the matching type. This will allow organizing
> cftypes in a lot clearer way and encourage subsystems to scrutinize
> the interface which is being exposed in the new default hierarchy.
>
> In preparation, this patch renames cgroup_subsys->base_cftypes to
> cgroup_subsys->legacy_cftypes. This patch is pure rename.
>
> Signed-off-by: Tejun Heo <[email protected]>
> Cc: Johannes Weiner <[email protected]>
> Cc: Michal Hocko <[email protected]>
> Cc: Li Zefan <[email protected]>
> Cc: Vivek Goyal <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> Cc: Arnaldo Carvalho de Melo <[email protected]>
> Cc: Aristeu Rozanski <[email protected]>
> Cc: Neil Horman <[email protected]>
> Cc: Aneesh Kumar K.V <[email protected]>
Acked-by: Neil Horman <[email protected]>

2014-07-03 11:08:21

by Neil Horman

[permalink] [raw]
Subject: Re: [PATCH 3/5] cgroup: replace cgroup_add_cftypes() with cgroup_add_legacy_cftypes()

On Wed, Jul 02, 2014 at 07:50:53PM -0400, Tejun Heo wrote:
> Currently, cftypes added by cgroup_add_cftypes() are used for both the
> unified default hierarchy and legacy ones and subsystems can mark each
> file with either CFTYPE_ONLY_ON_DFL or CFTYPE_INSANE if it has to
> appear only on one of them. This is quite hairy and error-prone.
> Also, we may end up exposing interface files to the default hierarchy
> without thinking it through.
>
> cgroup_subsys will grow two separate cftype addition functions and
> apply each only on the hierarchies of the matching type. This will
> allow organizing cftypes in a lot clearer way and encourage subsystems
> to scrutinize the interface which is being exposed in the new default
> hierarchy.
>
> In preparation, this patch adds cgroup_add_legacy_cftypes() which
> currently is a simple wrapper around cgroup_add_cftypes() and replaces
> all cgroup_add_cftypes() usages with it.
>
> While at it, this patch drops a completely spurious return from
> __hugetlb_cgroup_file_init().
>
> This patch doesn't introduce any functional differences.
>
> Signed-off-by: Tejun Heo <[email protected]>
> Cc: Johannes Weiner <[email protected]>
> Cc: Michal Hocko <[email protected]>
> Cc: Neil Horman <[email protected]>
> Cc: Aneesh Kumar K.V <[email protected]>
Acked-by: Neil Horman <[email protected]>

2014-07-03 11:14:54

by Neil Horman

[permalink] [raw]
Subject: Re: [PATCH 4/5] cgroup: distinguish the default and legacy hierarchies when handling cftypes

On Wed, Jul 02, 2014 at 07:50:54PM -0400, Tejun Heo wrote:
> Until now, cftype arrays carried files for both the default and legacy
> hierarchies and the files which needed to be used on only one of them
> were flagged with either CFTYPE_ONLY_ON_DFL or CFTYPE_INSANE. This
> gets confusing very quickly and we may end up exposing interface files
> to the default hierarchy without thinking it through.
>
> This patch makes cgroup core provide separate sets of interfaces for
> cftype handling so that the cftypes for the default and legacy
> hierarchies are clearly distinguished. The previous two patches
> renamed the existing ones so that they clearly indicate that they're
> for the legacy hierarchies. This patch adds the interface for the
> default hierarchy and apply them selectively depending on the
> hierarchy type.
>
> * cftypes added through cgroup_subsys->dfl_cftypes and
> cgroup_add_dfl_cftypes() only show up on the default hierarchy.
>
> * cftypes added through cgroup_subsys->legacy_cftypes and
> cgroup_add_legacy_cftypes() only show up on the legacy hierarchies.
>
> * cgroup_subsys->dfl_cftypes and ->legacy_cftypes can point to the
> same array for the cases where the interface files are identical on
> both types of hierarchies.
>
> * This makes all the existing subsystem interface files legacy-only by
> default and all subsystems will have no interface file created when
> enabled on the default hierarchy. Each subsystem should explicitly
> review and compose the interface for the default hierarchy.
>
> * A boot param "cgroup__DEVEL__legacy_files_on_dfl" is added which
> makes subsystems which haven't decided the interface files for the
> default hierarchy to present the legacy files on the default
> hierarchy so that its behavior on the default hierarchy can be
> tested. As the awkward name suggests, this is for development only.
>
> * memcg's CFTYPE_INSANE on "use_hierarchy" is noop now as the whole
> array isn't used on the default hierarchy. The flag is removed.
>
> Signed-off-by: Tejun Heo <[email protected]>
> Cc: Johannes Weiner <[email protected]>
> Cc: Michal Hocko <[email protected]>
> Cc: Li Zefan <[email protected]>
> Cc: Vivek Goyal <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> Cc: Arnaldo Carvalho de Melo <[email protected]>
> Cc: Aristeu Rozanski <[email protected]>
> Cc: Neil Horman <[email protected]>
> Cc: Aneesh Kumar K.V <[email protected]>
Acked-by: Neil Horman <[email protected]>

2014-07-03 15:20:39

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH v2 4/5] cgroup: distinguish the default and legacy hierarchies when handling cftypes

Until now, cftype arrays carried files for both the default and legacy
hierarchies and the files which needed to be used on only one of them
were flagged with either CFTYPE_ONLY_ON_DFL or CFTYPE_INSANE. This
gets confusing very quickly and we may end up exposing interface files
to the default hierarchy without thinking it through.

This patch makes cgroup core provide separate sets of interfaces for
cftype handling so that the cftypes for the default and legacy
hierarchies are clearly distinguished. The previous two patches
renamed the existing ones so that they clearly indicate that they're
for the legacy hierarchies. This patch adds the interface for the
default hierarchy and apply them selectively depending on the
hierarchy type.

* cftypes added through cgroup_subsys->dfl_cftypes and
cgroup_add_dfl_cftypes() only show up on the default hierarchy.

* cftypes added through cgroup_subsys->legacy_cftypes and
cgroup_add_legacy_cftypes() only show up on the legacy hierarchies.

* cgroup_subsys->dfl_cftypes and ->legacy_cftypes can point to the
same array for the cases where the interface files are identical on
both types of hierarchies.

* This makes all the existing subsystem interface files legacy-only by
default and all subsystems will have no interface file created when
enabled on the default hierarchy. Each subsystem should explicitly
review and compose the interface for the default hierarchy.

* A boot param "cgroup__DEVEL__legacy_files_on_dfl" is added which
makes subsystems which haven't decided the interface files for the
default hierarchy to present the legacy files on the default
hierarchy so that its behavior on the default hierarchy can be
tested. As the awkward name suggests, this is for development only.

* memcg's CFTYPE_INSANE on "use_hierarchy" is noop now as the whole
array isn't used on the default hierarchy. The flag is removed.

v2: Updated documentation for cgroup__DEVEL__legacy_files_on_dfl.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Li Zefan <[email protected]>
Cc: Vivek Goyal <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Aristeu Rozanski <[email protected]>
Cc: Neil Horman <[email protected]>
Cc: Aneesh Kumar K.V <[email protected]>
---
Documentation/cgroups/unified-hierarchy.txt | 18 ++++++---
include/linux/cgroup.h | 9 ++++-
kernel/cgroup.c | 59 +++++++++++++++++++++++++++--
mm/memcontrol.c | 1 -
4 files changed, 75 insertions(+), 12 deletions(-)

diff --git a/Documentation/cgroups/unified-hierarchy.txt b/Documentation/cgroups/unified-hierarchy.txt
index 324b182..185c2d4 100644
--- a/Documentation/cgroups/unified-hierarchy.txt
+++ b/Documentation/cgroups/unified-hierarchy.txt
@@ -94,12 +94,18 @@ change soon.

mount -t cgroup -o __DEVEL__sane_behavior cgroup $MOUNT_POINT

-All controllers which are not bound to other hierarchies are
-automatically bound to unified hierarchy and show up at the root of
-it. Controllers which are enabled only in the root of unified
-hierarchy can be bound to other hierarchies at any time. This allows
-mixing unified hierarchy with the traditional multiple hierarchies in
-a fully backward compatible way.
+All controllers which support the unified hierarchy and are not bound
+to other hierarchies are automatically bound to unified hierarchy and
+show up at the root of it. Controllers which are enabled only in the
+root of unified hierarchy can be bound to other hierarchies at any
+time. This allows mixing unified hierarchy with the traditional
+multiple hierarchies in a fully backward compatible way.
+
+For development purposes, the following boot parameter makes all
+controllers to appear on the unified hierarchy whether supported or
+not.
+
+ cgroup__DEVEL__legacy_files_on_dfl


2-2. cgroup.subtree_control
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index a75a37f..62a2be1 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -582,6 +582,7 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp)

char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);

+int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
int cgroup_rm_cftypes(struct cftype *cfts);

@@ -662,8 +663,12 @@ struct cgroup_subsys {
*/
struct list_head cfts;

- /* base cftypes, automatically registered with subsys itself */
- struct cftype *legacy_cftypes; /* used on the legacy hierarchies */
+ /*
+ * Base cftypes which are automatically registered. The two can
+ * point to the same array.
+ */
+ struct cftype *dfl_cftypes; /* for the default hierarchy */
+ struct cftype *legacy_cftypes; /* for the legacy hierarchies */
};

#define SUBSYS(_x) extern struct cgroup_subsys _x ## _cgrp_subsys;
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 311d42b..650f514 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -149,6 +149,12 @@ struct cgroup_root cgrp_dfl_root;
*/
static bool cgrp_dfl_root_visible;

+/*
+ * Set by the boot param of the same name and makes subsystems with NULL
+ * ->dfl_files to use ->legacy_files on the default hierarchy.
+ */
+static bool cgroup_legacy_files_on_dfl;
+
/* some controllers are not supported in the default hierarchy */
static const unsigned int cgrp_dfl_root_inhibit_ss_mask = 0
#ifdef CONFIG_CGROUP_DEBUG
@@ -3085,8 +3091,37 @@ static int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
return ret;
}

+/**
+ * cgroup_add_dfl_cftypes - add an array of cftypes for default hierarchy
+ * @ss: target cgroup subsystem
+ * @cfts: zero-length name terminated array of cftypes
+ *
+ * Similar to cgroup_add_cftypes() but the added files are only used for
+ * the default hierarchy.
+ */
+int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
+{
+ struct cftype *cft;
+
+ for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
+ cft->flags |= CFTYPE_ONLY_ON_DFL;
+ return cgroup_add_cftypes(ss, cfts);
+}
+
+/**
+ * cgroup_add_legacy_cftypes - add an array of cftypes for legacy hierarchies
+ * @ss: target cgroup subsystem
+ * @cfts: zero-length name terminated array of cftypes
+ *
+ * Similar to cgroup_add_cftypes() but the added files are only used for
+ * the legacy hierarchies.
+ */
int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
{
+ struct cftype *cft;
+
+ for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
+ cft->flags |= CFTYPE_INSANE;
return cgroup_add_cftypes(ss, cfts);
}

@@ -4775,9 +4810,19 @@ int __init cgroup_init(void)
* disabled flag and cftype registration needs kmalloc,
* both of which aren't available during early_init.
*/
- if (!ss->disabled) {
- cgrp_dfl_root.subsys_mask |= 1 << ss->id;
- WARN_ON(cgroup_add_cftypes(ss, ss->legacy_cftypes));
+ if (ss->disabled)
+ continue;
+
+ cgrp_dfl_root.subsys_mask |= 1 << ss->id;
+
+ if (cgroup_legacy_files_on_dfl && !ss->dfl_cftypes)
+ ss->dfl_cftypes = ss->legacy_cftypes;
+
+ if (ss->dfl_cftypes == ss->legacy_cftypes) {
+ WARN_ON(cgroup_add_cftypes(ss, ss->dfl_cftypes));
+ } else {
+ WARN_ON(cgroup_add_dfl_cftypes(ss, ss->dfl_cftypes));
+ WARN_ON(cgroup_add_legacy_cftypes(ss, ss->legacy_cftypes));
}
}

@@ -5173,6 +5218,14 @@ static int __init cgroup_disable(char *str)
}
__setup("cgroup_disable=", cgroup_disable);

+static int __init cgroup_set_legacy_files_on_dfl(char *str)
+{
+ printk("cgroup: using legacy files on the default hierarchy\n");
+ cgroup_legacy_files_on_dfl = true;
+ return 0;
+}
+__setup("cgroup__DEVEL__legacy_files_on_dfl", cgroup_set_legacy_files_on_dfl);
+
/**
* css_tryget_online_from_dir - get corresponding css from a cgroup dentry
* @dentry: directory dentry of interest
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a629611..3b37586 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -6003,7 +6003,6 @@ static struct cftype mem_cgroup_files[] = {
},
{
.name = "use_hierarchy",
- .flags = CFTYPE_INSANE,
.write_u64 = mem_cgroup_hierarchy_write,
.read_u64 = mem_cgroup_hierarchy_read,
},
--
1.9.3

2014-07-03 15:21:21

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 6/5] cgroup: initialize cgrp_dfl_root_inhibit_ss_mask from !->dfl_files test

>From 29e5e8eac7ade8af5880020c91db9bc1c470596a Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Thu, 3 Jul 2014 11:18:31 -0400

cgrp_dfl_root_inhibit_ss_mask determines which subsystems are not
supported on the default hierarchy and is currently initialized
statically and just includes the debug subsystem. Now that there's
cgroup_subsys->dfl_files, we can easily tell which subsystems support
the default hierarchy or not.

Let's initialize cgrp_dfl_root_inhibit_ss_mask by testing whether
cgroup_subsys->dfl_files is NULL. After all, subsystems with NULL
->dfl_files aren't useable on the default hierarchy anyway.

Signed-off-by: Tejun Heo <[email protected]>
---
kernel/cgroup.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index bc38c75..a7fce52 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -156,11 +156,7 @@ static bool cgrp_dfl_root_visible;
static bool cgroup_legacy_files_on_dfl;

/* some controllers are not supported in the default hierarchy */
-static const unsigned int cgrp_dfl_root_inhibit_ss_mask = 0
-#ifdef CONFIG_CGROUP_DEBUG
- | (1 << debug_cgrp_id)
-#endif
- ;
+static unsigned int cgrp_dfl_root_inhibit_ss_mask;

/* The list of hierarchy roots */

@@ -4818,6 +4814,9 @@ int __init cgroup_init(void)
if (cgroup_legacy_files_on_dfl && !ss->dfl_cftypes)
ss->dfl_cftypes = ss->legacy_cftypes;

+ if (!ss->dfl_cftypes)
+ cgrp_dfl_root_inhibit_ss_mask |= 1 << ss->id;
+
if (ss->dfl_cftypes == ss->legacy_cftypes) {
WARN_ON(cgroup_add_cftypes(ss, ss->dfl_cftypes));
} else {
--
1.9.3

2014-07-04 17:11:19

by Tejun Heo

[permalink] [raw]
Subject: [PATCH v2 1/5] cgroup: split cgroup_base_files[] into cgroup_{dfl|legacy}_base_files[]

>From f41924c8f07dcda07a31a08117bac077fde13626 Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Fri, 4 Jul 2014 13:06:42 -0400

Currently cgroup_base_files[] contains the cgroup core interface files
for both legacy and default hierarchies with each file tagged with
CFTYPE_INSANE and CFTYPE_ONLY_ON_DFL. This is difficult to read.

Let's separate it out to two separate tables, cgroup_dfl_base_files[]
and cgroup_legacy_base_files[], and use the appropriate one in
cgroup_mkdir() depending on the hierarchy type. This makes tagging
each file unnecessary.

This patch doesn't introduce any behavior changes.

v2: cgroup_dfl_base_files[] was missing the termination entry
triggering WARN in cgroup_init_cftypes() for 0day kernel testing
robot. Fixed.

Signed-off-by: Tejun Heo <[email protected]>
Cc: Jet Chen <[email protected]>
---
kernel/cgroup.c | 76 ++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 48 insertions(+), 28 deletions(-)

diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 1c56924..50858ff 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -180,7 +180,8 @@ static u64 css_serial_nr_next = 1;
*/
static int need_forkexit_callback __read_mostly;

-static struct cftype cgroup_base_files[];
+static struct cftype cgroup_dfl_base_files[];
+static struct cftype cgroup_legacy_base_files[];

static void cgroup_put(struct cgroup *cgrp);
static int rebind_subsystems(struct cgroup_root *dst_root,
@@ -1558,6 +1559,7 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned int ss_mask)
{
LIST_HEAD(tmp_links);
struct cgroup *root_cgrp = &root->cgrp;
+ struct cftype *base_files;
struct css_set *cset;
int i, ret;

@@ -1595,7 +1597,12 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned int ss_mask)
}
root_cgrp->kn = root->kf_root->kn;

- ret = cgroup_addrm_files(root_cgrp, cgroup_base_files, true);
+ if (root == &cgrp_dfl_root)
+ base_files = cgroup_dfl_base_files;
+ else
+ base_files = cgroup_legacy_base_files;
+
+ ret = cgroup_addrm_files(root_cgrp, base_files, true);
if (ret)
goto destroy_root;

@@ -3985,7 +3992,8 @@ static int cgroup_clone_children_write(struct cgroup_subsys_state *css,
return 0;
}

-static struct cftype cgroup_base_files[] = {
+/* cgroup core interface files for the default hierarchy */
+static struct cftype cgroup_dfl_base_files[] = {
{
.name = "cgroup.procs",
.seq_start = cgroup_pidlist_start,
@@ -3997,46 +4005,52 @@ static struct cftype cgroup_base_files[] = {
.mode = S_IRUGO | S_IWUSR,
},
{
- .name = "cgroup.clone_children",
- .flags = CFTYPE_INSANE,
- .read_u64 = cgroup_clone_children_read,
- .write_u64 = cgroup_clone_children_write,
- },
- {
- .name = "cgroup.sane_behavior",
- .flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT,
- .seq_show = cgroup_sane_behavior_show,
- },
- {
.name = "cgroup.controllers",
- .flags = CFTYPE_ONLY_ON_DFL | CFTYPE_ONLY_ON_ROOT,
+ .flags = CFTYPE_ONLY_ON_ROOT,
.seq_show = cgroup_root_controllers_show,
},
{
.name = "cgroup.controllers",
- .flags = CFTYPE_ONLY_ON_DFL | CFTYPE_NOT_ON_ROOT,
+ .flags = CFTYPE_NOT_ON_ROOT,
.seq_show = cgroup_controllers_show,
},
{
.name = "cgroup.subtree_control",
- .flags = CFTYPE_ONLY_ON_DFL,
.seq_show = cgroup_subtree_control_show,
.write = cgroup_subtree_control_write,
},
{
.name = "cgroup.populated",
- .flags = CFTYPE_ONLY_ON_DFL | CFTYPE_NOT_ON_ROOT,
+ .flags = CFTYPE_NOT_ON_ROOT,
.seq_show = cgroup_populated_show,
},
+ { } /* terminate */
+};

- /*
- * Historical crazy stuff. These don't have "cgroup." prefix and
- * don't exist if sane_behavior. If you're depending on these, be
- * prepared to be burned.
- */
+/* cgroup core interface files for the legacy hierarchies */
+static struct cftype cgroup_legacy_base_files[] = {
+ {
+ .name = "cgroup.procs",
+ .seq_start = cgroup_pidlist_start,
+ .seq_next = cgroup_pidlist_next,
+ .seq_stop = cgroup_pidlist_stop,
+ .seq_show = cgroup_pidlist_show,
+ .private = CGROUP_FILE_PROCS,
+ .write = cgroup_procs_write,
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ {
+ .name = "cgroup.clone_children",
+ .read_u64 = cgroup_clone_children_read,
+ .write_u64 = cgroup_clone_children_write,
+ },
+ {
+ .name = "cgroup.sane_behavior",
+ .flags = CFTYPE_ONLY_ON_ROOT,
+ .seq_show = cgroup_sane_behavior_show,
+ },
{
.name = "tasks",
- .flags = CFTYPE_INSANE, /* use "procs" instead */
.seq_start = cgroup_pidlist_start,
.seq_next = cgroup_pidlist_next,
.seq_stop = cgroup_pidlist_stop,
@@ -4047,13 +4061,12 @@ static struct cftype cgroup_base_files[] = {
},
{
.name = "notify_on_release",
- .flags = CFTYPE_INSANE,
.read_u64 = cgroup_read_notify_on_release,
.write_u64 = cgroup_write_notify_on_release,
},
{
.name = "release_agent",
- .flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT,
+ .flags = CFTYPE_ONLY_ON_ROOT,
.seq_show = cgroup_release_agent_show,
.write = cgroup_release_agent_write,
.max_write_len = PATH_MAX - 1,
@@ -4330,6 +4343,7 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
struct cgroup_root *root;
struct cgroup_subsys *ss;
struct kernfs_node *kn;
+ struct cftype *base_files;
int ssid, ret;

parent = cgroup_kn_lock_live(parent_kn);
@@ -4400,7 +4414,12 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
if (ret)
goto out_destroy;

- ret = cgroup_addrm_files(cgrp, cgroup_base_files, true);
+ if (cgroup_on_dfl(cgrp))
+ base_files = cgroup_dfl_base_files;
+ else
+ base_files = cgroup_legacy_base_files;
+
+ ret = cgroup_addrm_files(cgrp, base_files, true);
if (ret)
goto out_destroy;

@@ -4719,7 +4738,8 @@ int __init cgroup_init(void)
unsigned long key;
int ssid, err;

- BUG_ON(cgroup_init_cftypes(NULL, cgroup_base_files));
+ BUG_ON(cgroup_init_cftypes(NULL, cgroup_dfl_base_files));
+ BUG_ON(cgroup_init_cftypes(NULL, cgroup_legacy_base_files));

mutex_lock(&cgroup_mutex);

--
1.9.3

2014-07-14 02:14:31

by Zefan Li

[permalink] [raw]
Subject: Re: [PATCH 4/5] cgroup: distinguish the default and legacy hierarchies when handling cftypes

> @@ -3085,8 +3091,37 @@ static int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
> return ret;
> }
>
> +/**
> + * cgroup_add_dfl_cftypes - add an array of cftypes for default hierarchy
> + * @ss: target cgroup subsystem
> + * @cfts: zero-length name terminated array of cftypes
> + *
> + * Similar to cgroup_add_cftypes() but the added files are only used for
> + * the default hierarchy.
> + */
> +int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
> +{
> + struct cftype *cft;
> +
> + for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
> + cft->flags |= CFTYPE_ONLY_ON_DFL;

I think we should remove this flag in cgroup_rm_cftypes_locked(). Otherwise
if we call cgroup_add_dlf_cftypes() and then cgroup_rm_cftypes() and then
cgroup_add_legacy_cftypes() for the same @cfts, both CFTYPE_ONLY_ON_DFL and
CFTYPE_INSANE are set.

> + return cgroup_add_cftypes(ss, cfts);
> +}
> +
> +/**
> + * cgroup_add_legacy_cftypes - add an array of cftypes for legacy hierarchies
> + * @ss: target cgroup subsystem
> + * @cfts: zero-length name terminated array of cftypes
> + *
> + * Similar to cgroup_add_cftypes() but the added files are only used for
> + * the legacy hierarchies.
> + */
> int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
> {
> + struct cftype *cft;
> +
> + for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
> + cft->flags |= CFTYPE_INSANE;
> return cgroup_add_cftypes(ss, cfts);
> }

2014-07-14 14:43:12

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 4/5] cgroup: distinguish the default and legacy hierarchies when handling cftypes

On Mon, Jul 14, 2014 at 10:13:27AM +0800, Li Zefan wrote:
> I think we should remove this flag in cgroup_rm_cftypes_locked(). Otherwise
> if we call cgroup_add_dlf_cftypes() and then cgroup_rm_cftypes() and then
> cgroup_add_legacy_cftypes() for the same @cfts, both CFTYPE_ONLY_ON_DFL and
> CFTYPE_INSANE are set.

Heh, that's unlikely to actually happen but yes clearing would be
better. Will update accordingly.

Thanks.

--
tejun