[PATCH] memcg: Do not create memsw files if swap accounting isdisabled

From: Michal Hocko
Date: Mon Jan 21 2013 - 05:33:26 EST


Zhouping Liu has reported that memsw files are exported even though
swap accounting is runtime disabled if CONFIG_MEMCG_SWAP is enabled.
This behavior has been introduced by af36f906 (memcg: always create
memsw files if CONFIG_CGROUP_MEM_RES_CTLR_SWAP) and it causes any
attempt to open the file to return EOPNOTSUPP. Although EOPNOTSUPP
should say be clear that memsw operations are not supported in the given
configuration it is fair to say that this behavior could be quite
confusing.

Let's tear memsw files out of default cgroup files and add
them only if the swap accounting is really enabled (either by
CONFIG_MEMCG_SWAP_ENABLED or swapaccount=1 boot parameter). We can
hook into mem_cgroup_init which is called when the memcg subsystem is
initialized and which happens after boot command line is processed.

Reported-by: Zhouping Liu <zliu@xxxxxxxxxx>
Signed-off-by: Michal Hocko <mhocko@xxxxxxx>
---
mm/memcontrol.c | 94 ++++++++++++++++++++++++++++++++-----------------------
1 file changed, 54 insertions(+), 40 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 3817460..a2800db 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5988,33 +5988,6 @@ static struct cftype mem_cgroup_files[] = {
.read_seq_string = memcg_numa_stat_show,
},
#endif
-#ifdef CONFIG_MEMCG_SWAP
- {
- .name = "memsw.usage_in_bytes",
- .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
- .read = mem_cgroup_read,
- .register_event = mem_cgroup_usage_register_event,
- .unregister_event = mem_cgroup_usage_unregister_event,
- },
- {
- .name = "memsw.max_usage_in_bytes",
- .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE),
- .trigger = mem_cgroup_reset,
- .read = mem_cgroup_read,
- },
- {
- .name = "memsw.limit_in_bytes",
- .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT),
- .write_string = mem_cgroup_write,
- .read = mem_cgroup_read,
- },
- {
- .name = "memsw.failcnt",
- .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT),
- .trigger = mem_cgroup_reset,
- .read = mem_cgroup_read,
- },
-#endif
#ifdef CONFIG_MEMCG_KMEM
{
.name = "kmem.limit_in_bytes",
@@ -6057,6 +6030,36 @@ static struct cftype mem_cgroup_files[] = {
{ }, /* terminate */
};

+#ifdef CONFIG_MEMCG_SWAP
+static struct cftype memsw_cgroup_files[] = {
+ {
+ .name = "memsw.usage_in_bytes",
+ .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
+ .read = mem_cgroup_read,
+ .register_event = mem_cgroup_usage_register_event,
+ .unregister_event = mem_cgroup_usage_unregister_event,
+ },
+ {
+ .name = "memsw.max_usage_in_bytes",
+ .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE),
+ .trigger = mem_cgroup_reset,
+ .read = mem_cgroup_read,
+ },
+ {
+ .name = "memsw.limit_in_bytes",
+ .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT),
+ .write_string = mem_cgroup_write,
+ .read = mem_cgroup_read,
+ },
+ {
+ .name = "memsw.failcnt",
+ .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT),
+ .trigger = mem_cgroup_reset,
+ .read = mem_cgroup_read,
+ },
+ { }, /* terminate */
+};
+#endif
static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
{
struct mem_cgroup_per_node *pn;
@@ -6959,19 +6962,6 @@ struct cgroup_subsys mem_cgroup_subsys = {
.use_id = 1,
};

-/*
- * The rest of init is performed during ->css_alloc() for root css which
- * happens before initcalls. hotcpu_notifier() can't be done together as
- * it would introduce circular locking by adding cgroup_lock -> cpu hotplug
- * dependency. Do it from a subsys_initcall().
- */
-static int __init mem_cgroup_init(void)
-{
- hotcpu_notifier(memcg_cpu_hotplug_callback, 0);
- return 0;
-}
-subsys_initcall(mem_cgroup_init);
-
#ifdef CONFIG_MEMCG_SWAP
static int __init enable_swap_account(char *s)
{
@@ -6984,4 +6974,28 @@ static int __init enable_swap_account(char *s)
}
__setup("swapaccount=", enable_swap_account);

+static void __init memsw_file_init(void)
+{
+ if (really_do_swap_account)
+ WARN_ON(cgroup_add_cftypes(&mem_cgroup_subsys,
+ memsw_cgroup_files));
+}
+#else
+static void __init memsw_file_init(void)
+{
+}
#endif
+
+/*
+ * The rest of init is performed during ->css_alloc() for root css which
+ * happens before initcalls. hotcpu_notifier() can't be done together as
+ * it would introduce circular locking by adding cgroup_lock -> cpu hotplug
+ * dependency. Do it from a subsys_initcall().
+ */
+static int __init mem_cgroup_init(void)
+{
+ hotcpu_notifier(memcg_cpu_hotplug_callback, 0);
+ memsw_file_init();
+ return 0;
+}
+subsys_initcall(mem_cgroup_init);
--
1.7.10.4

--
Michal Hocko
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/