Commit af36f906 authored by Tejun Heo's avatar Tejun Heo

memcg: always create memsw files if CONFIG_CGROUP_MEM_RES_CTLR_SWAP

Instead of conditioning creation of memsw files on do_swap_account,
always create the files if compiled-in and fail read/write attempts
with -EOPNOTSUPP if !do_swap_account.

This is suggested by KAMEZAWA to simplify memcg file creation so that
it can use cgroup->subsys_cftypes.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Acked-by: default avatarLi Zefan <lizf@cn.fujitsu.com>
parent 4baf6e33
...@@ -3879,14 +3879,21 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap) ...@@ -3879,14 +3879,21 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
return val << PAGE_SHIFT; return val << PAGE_SHIFT;
} }
static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
{ {
struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
char str[64];
u64 val; u64 val;
int type, name; int type, name, len;
type = MEMFILE_TYPE(cft->private); type = MEMFILE_TYPE(cft->private);
name = MEMFILE_ATTR(cft->private); name = MEMFILE_ATTR(cft->private);
if (!do_swap_account && type == _MEMSWAP)
return -EOPNOTSUPP;
switch (type) { switch (type) {
case _MEM: case _MEM:
if (name == RES_USAGE) if (name == RES_USAGE)
...@@ -3903,7 +3910,9 @@ static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) ...@@ -3903,7 +3910,9 @@ static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
default: default:
BUG(); BUG();
} }
return val;
len = scnprintf(str, sizeof(str), "%llu\n", (unsigned long long)val);
return simple_read_from_buffer(buf, nbytes, ppos, str, len);
} }
/* /*
* The user of this function is... * The user of this function is...
...@@ -3919,6 +3928,10 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft, ...@@ -3919,6 +3928,10 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
type = MEMFILE_TYPE(cft->private); type = MEMFILE_TYPE(cft->private);
name = MEMFILE_ATTR(cft->private); name = MEMFILE_ATTR(cft->private);
if (!do_swap_account && type == _MEMSWAP)
return -EOPNOTSUPP;
switch (name) { switch (name) {
case RES_LIMIT: case RES_LIMIT:
if (mem_cgroup_is_root(memcg)) { /* Can't set limit on root */ if (mem_cgroup_is_root(memcg)) { /* Can't set limit on root */
...@@ -3984,12 +3997,15 @@ static void memcg_get_hierarchical_limit(struct mem_cgroup *memcg, ...@@ -3984,12 +3997,15 @@ static void memcg_get_hierarchical_limit(struct mem_cgroup *memcg,
static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
{ {
struct mem_cgroup *memcg; struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
int type, name; int type, name;
memcg = mem_cgroup_from_cont(cont);
type = MEMFILE_TYPE(event); type = MEMFILE_TYPE(event);
name = MEMFILE_ATTR(event); name = MEMFILE_ATTR(event);
if (!do_swap_account && type == _MEMSWAP)
return -EOPNOTSUPP;
switch (name) { switch (name) {
case RES_MAX_USAGE: case RES_MAX_USAGE:
if (type == _MEM) if (type == _MEM)
...@@ -4655,7 +4671,7 @@ static struct cftype mem_cgroup_files[] = { ...@@ -4655,7 +4671,7 @@ static struct cftype mem_cgroup_files[] = {
{ {
.name = "usage_in_bytes", .name = "usage_in_bytes",
.private = MEMFILE_PRIVATE(_MEM, RES_USAGE), .private = MEMFILE_PRIVATE(_MEM, RES_USAGE),
.read_u64 = mem_cgroup_read, .read = mem_cgroup_read,
.register_event = mem_cgroup_usage_register_event, .register_event = mem_cgroup_usage_register_event,
.unregister_event = mem_cgroup_usage_unregister_event, .unregister_event = mem_cgroup_usage_unregister_event,
}, },
...@@ -4663,25 +4679,25 @@ static struct cftype mem_cgroup_files[] = { ...@@ -4663,25 +4679,25 @@ static struct cftype mem_cgroup_files[] = {
.name = "max_usage_in_bytes", .name = "max_usage_in_bytes",
.private = MEMFILE_PRIVATE(_MEM, RES_MAX_USAGE), .private = MEMFILE_PRIVATE(_MEM, RES_MAX_USAGE),
.trigger = mem_cgroup_reset, .trigger = mem_cgroup_reset,
.read_u64 = mem_cgroup_read, .read = mem_cgroup_read,
}, },
{ {
.name = "limit_in_bytes", .name = "limit_in_bytes",
.private = MEMFILE_PRIVATE(_MEM, RES_LIMIT), .private = MEMFILE_PRIVATE(_MEM, RES_LIMIT),
.write_string = mem_cgroup_write, .write_string = mem_cgroup_write,
.read_u64 = mem_cgroup_read, .read = mem_cgroup_read,
}, },
{ {
.name = "soft_limit_in_bytes", .name = "soft_limit_in_bytes",
.private = MEMFILE_PRIVATE(_MEM, RES_SOFT_LIMIT), .private = MEMFILE_PRIVATE(_MEM, RES_SOFT_LIMIT),
.write_string = mem_cgroup_write, .write_string = mem_cgroup_write,
.read_u64 = mem_cgroup_read, .read = mem_cgroup_read,
}, },
{ {
.name = "failcnt", .name = "failcnt",
.private = MEMFILE_PRIVATE(_MEM, RES_FAILCNT), .private = MEMFILE_PRIVATE(_MEM, RES_FAILCNT),
.trigger = mem_cgroup_reset, .trigger = mem_cgroup_reset,
.read_u64 = mem_cgroup_read, .read = mem_cgroup_read,
}, },
{ {
.name = "stat", .name = "stat",
...@@ -4721,14 +4737,11 @@ static struct cftype mem_cgroup_files[] = { ...@@ -4721,14 +4737,11 @@ static struct cftype mem_cgroup_files[] = {
.mode = S_IRUGO, .mode = S_IRUGO,
}, },
#endif #endif
};
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
static struct cftype memsw_cgroup_files[] = {
{ {
.name = "memsw.usage_in_bytes", .name = "memsw.usage_in_bytes",
.private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE), .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
.read_u64 = mem_cgroup_read, .read = mem_cgroup_read,
.register_event = mem_cgroup_usage_register_event, .register_event = mem_cgroup_usage_register_event,
.unregister_event = mem_cgroup_usage_unregister_event, .unregister_event = mem_cgroup_usage_unregister_event,
}, },
...@@ -4736,35 +4749,22 @@ static struct cftype memsw_cgroup_files[] = { ...@@ -4736,35 +4749,22 @@ static struct cftype memsw_cgroup_files[] = {
.name = "memsw.max_usage_in_bytes", .name = "memsw.max_usage_in_bytes",
.private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE), .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE),
.trigger = mem_cgroup_reset, .trigger = mem_cgroup_reset,
.read_u64 = mem_cgroup_read, .read = mem_cgroup_read,
}, },
{ {
.name = "memsw.limit_in_bytes", .name = "memsw.limit_in_bytes",
.private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT), .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT),
.write_string = mem_cgroup_write, .write_string = mem_cgroup_write,
.read_u64 = mem_cgroup_read, .read = mem_cgroup_read,
}, },
{ {
.name = "memsw.failcnt", .name = "memsw.failcnt",
.private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT), .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT),
.trigger = mem_cgroup_reset, .trigger = mem_cgroup_reset,
.read_u64 = mem_cgroup_read, .read = mem_cgroup_read,
}, },
};
static int register_memsw_files(struct cgroup *cont, struct cgroup_subsys *ss)
{
if (!do_swap_account)
return 0;
return cgroup_add_files(cont, ss, memsw_cgroup_files,
ARRAY_SIZE(memsw_cgroup_files));
};
#else
static int register_memsw_files(struct cgroup *cont, struct cgroup_subsys *ss)
{
return 0;
}
#endif #endif
};
static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node) static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
{ {
...@@ -5046,9 +5046,6 @@ static int mem_cgroup_populate(struct cgroup_subsys *ss, ...@@ -5046,9 +5046,6 @@ static int mem_cgroup_populate(struct cgroup_subsys *ss,
ret = cgroup_add_files(cont, ss, mem_cgroup_files, ret = cgroup_add_files(cont, ss, mem_cgroup_files,
ARRAY_SIZE(mem_cgroup_files)); ARRAY_SIZE(mem_cgroup_files));
if (!ret)
ret = register_memsw_files(cont, ss);
if (!ret) if (!ret)
ret = register_kmem_files(cont, ss); ret = register_kmem_files(cont, ss);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment