From 0eea10301708c64a6b793894c156e21ddd15eb64 Mon Sep 17 00:00:00 2001 From: Balbir Singh Date: Thu, 7 Feb 2008 00:13:57 -0800 Subject: Memory controller improve user interface Change the interface to use bytes instead of pages. Page sizes can vary across platforms and configurations. A new strategy routine has been added to the resource counters infrastructure to format the data as desired. Suggested by David Rientjes, Andrew Morton and Herbert Poetzl Tested on a UML setup with the config for memory control enabled. [kamezawa.hiroyu@jp.fujitsu.com: possible race fix in res_counter] Signed-off-by: Balbir Singh Signed-off-by: Pavel Emelianov Cc: Paul Menage Cc: Peter Zijlstra Cc: "Eric W. Biederman" Cc: Nick Piggin Cc: Kirill Korotaev Cc: Herbert Poetzl Cc: David Rientjes Cc: Vaidyanathan Srinivasan Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memcontrol.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) (limited to 'mm') diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 9e9ff914c0f1..d73692279ab1 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -302,7 +302,7 @@ retry: * If we created the page_cgroup, we should free it on exceeding * the cgroup limit. */ - while (res_counter_charge(&mem->res, 1)) { + while (res_counter_charge(&mem->res, PAGE_SIZE)) { if (try_to_free_mem_cgroup_pages(mem)) continue; @@ -341,7 +341,7 @@ retry: kfree(pc); pc = race_pc; atomic_inc(&pc->ref_cnt); - res_counter_uncharge(&mem->res, 1); + res_counter_uncharge(&mem->res, PAGE_SIZE); css_put(&mem->css); goto done; } @@ -384,7 +384,7 @@ void mem_cgroup_uncharge(struct page_cgroup *pc) css_put(&mem->css); page_assign_page_cgroup(page, NULL); unlock_page_cgroup(page); - res_counter_uncharge(&mem->res, 1); + res_counter_uncharge(&mem->res, PAGE_SIZE); spin_lock_irqsave(&mem->lru_lock, flags); list_del_init(&pc->lru); @@ -393,12 +393,26 @@ void mem_cgroup_uncharge(struct page_cgroup *pc) } } -static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft, - struct file *file, char __user *userbuf, size_t nbytes, - loff_t *ppos) +int mem_cgroup_write_strategy(char *buf, unsigned long long *tmp) +{ + *tmp = memparse(buf, &buf); + if (*buf != '\0') + return -EINVAL; + + /* + * Round up the value to the closest page size + */ + *tmp = ((*tmp + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT; + return 0; +} + +static ssize_t mem_cgroup_read(struct cgroup *cont, + struct cftype *cft, struct file *file, + char __user *userbuf, size_t nbytes, loff_t *ppos) { return res_counter_read(&mem_cgroup_from_cont(cont)->res, - cft->private, userbuf, nbytes, ppos); + cft->private, userbuf, nbytes, ppos, + NULL); } static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, @@ -406,17 +420,18 @@ static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, size_t nbytes, loff_t *ppos) { return res_counter_write(&mem_cgroup_from_cont(cont)->res, - cft->private, userbuf, nbytes, ppos); + cft->private, userbuf, nbytes, ppos, + mem_cgroup_write_strategy); } static struct cftype mem_cgroup_files[] = { { - .name = "usage", + .name = "usage_in_bytes", .private = RES_USAGE, .read = mem_cgroup_read, }, { - .name = "limit", + .name = "limit_in_bytes", .private = RES_LIMIT, .write = mem_cgroup_write, .read = mem_cgroup_read, -- cgit v1.2.3