diff options
author | Balbir Singh <balbir@linux.vnet.ibm.com> | 2008-02-07 03:13:57 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-07 11:42:18 -0500 |
commit | 0eea10301708c64a6b793894c156e21ddd15eb64 (patch) | |
tree | a0dcbe47d48d35ec0554faa5f86068cfab94ca6e /mm | |
parent | 66e1707bc34609f626e2e7b4fe7e454c9748bad5 (diff) |
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 <balbir@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelianov <xemul@openvz.org>
Cc: Paul Menage <menage@google.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Kirill Korotaev <dev@sw.ru>
Cc: Herbert Poetzl <herbert@13thfloor.at>
Cc: David Rientjes <rientjes@google.com>
Cc: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memcontrol.c | 35 |
1 files changed, 25 insertions, 10 deletions
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: | |||
302 | * If we created the page_cgroup, we should free it on exceeding | 302 | * If we created the page_cgroup, we should free it on exceeding |
303 | * the cgroup limit. | 303 | * the cgroup limit. |
304 | */ | 304 | */ |
305 | while (res_counter_charge(&mem->res, 1)) { | 305 | while (res_counter_charge(&mem->res, PAGE_SIZE)) { |
306 | if (try_to_free_mem_cgroup_pages(mem)) | 306 | if (try_to_free_mem_cgroup_pages(mem)) |
307 | continue; | 307 | continue; |
308 | 308 | ||
@@ -341,7 +341,7 @@ retry: | |||
341 | kfree(pc); | 341 | kfree(pc); |
342 | pc = race_pc; | 342 | pc = race_pc; |
343 | atomic_inc(&pc->ref_cnt); | 343 | atomic_inc(&pc->ref_cnt); |
344 | res_counter_uncharge(&mem->res, 1); | 344 | res_counter_uncharge(&mem->res, PAGE_SIZE); |
345 | css_put(&mem->css); | 345 | css_put(&mem->css); |
346 | goto done; | 346 | goto done; |
347 | } | 347 | } |
@@ -384,7 +384,7 @@ void mem_cgroup_uncharge(struct page_cgroup *pc) | |||
384 | css_put(&mem->css); | 384 | css_put(&mem->css); |
385 | page_assign_page_cgroup(page, NULL); | 385 | page_assign_page_cgroup(page, NULL); |
386 | unlock_page_cgroup(page); | 386 | unlock_page_cgroup(page); |
387 | res_counter_uncharge(&mem->res, 1); | 387 | res_counter_uncharge(&mem->res, PAGE_SIZE); |
388 | 388 | ||
389 | spin_lock_irqsave(&mem->lru_lock, flags); | 389 | spin_lock_irqsave(&mem->lru_lock, flags); |
390 | list_del_init(&pc->lru); | 390 | list_del_init(&pc->lru); |
@@ -393,12 +393,26 @@ void mem_cgroup_uncharge(struct page_cgroup *pc) | |||
393 | } | 393 | } |
394 | } | 394 | } |
395 | 395 | ||
396 | static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft, | 396 | int mem_cgroup_write_strategy(char *buf, unsigned long long *tmp) |
397 | struct file *file, char __user *userbuf, size_t nbytes, | 397 | { |
398 | loff_t *ppos) | 398 | *tmp = memparse(buf, &buf); |
399 | if (*buf != '\0') | ||
400 | return -EINVAL; | ||
401 | |||
402 | /* | ||
403 | * Round up the value to the closest page size | ||
404 | */ | ||
405 | *tmp = ((*tmp + PAGE_SIZE - 1) >> PAGE_SHIFT) << PAGE_SHIFT; | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static ssize_t mem_cgroup_read(struct cgroup *cont, | ||
410 | struct cftype *cft, struct file *file, | ||
411 | char __user *userbuf, size_t nbytes, loff_t *ppos) | ||
399 | { | 412 | { |
400 | return res_counter_read(&mem_cgroup_from_cont(cont)->res, | 413 | return res_counter_read(&mem_cgroup_from_cont(cont)->res, |
401 | cft->private, userbuf, nbytes, ppos); | 414 | cft->private, userbuf, nbytes, ppos, |
415 | NULL); | ||
402 | } | 416 | } |
403 | 417 | ||
404 | static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, | 418 | 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, | |||
406 | size_t nbytes, loff_t *ppos) | 420 | size_t nbytes, loff_t *ppos) |
407 | { | 421 | { |
408 | return res_counter_write(&mem_cgroup_from_cont(cont)->res, | 422 | return res_counter_write(&mem_cgroup_from_cont(cont)->res, |
409 | cft->private, userbuf, nbytes, ppos); | 423 | cft->private, userbuf, nbytes, ppos, |
424 | mem_cgroup_write_strategy); | ||
410 | } | 425 | } |
411 | 426 | ||
412 | static struct cftype mem_cgroup_files[] = { | 427 | static struct cftype mem_cgroup_files[] = { |
413 | { | 428 | { |
414 | .name = "usage", | 429 | .name = "usage_in_bytes", |
415 | .private = RES_USAGE, | 430 | .private = RES_USAGE, |
416 | .read = mem_cgroup_read, | 431 | .read = mem_cgroup_read, |
417 | }, | 432 | }, |
418 | { | 433 | { |
419 | .name = "limit", | 434 | .name = "limit_in_bytes", |
420 | .private = RES_LIMIT, | 435 | .private = RES_LIMIT, |
421 | .write = mem_cgroup_write, | 436 | .write = mem_cgroup_write, |
422 | .read = mem_cgroup_read, | 437 | .read = mem_cgroup_read, |