Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

memcg: limit change shrink usage

Shrinking memory usage at limit change.

[akpm@linux-foundation.org: coding-style fixes]
Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Acked-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Paul Menage <menage@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

KAMEZAWA Hiroyuki and committed by
Linus Torvalds
628f4235 12b98044

+45 -6
+1 -2
Documentation/controllers/memory.txt
··· 242 242 1. Add support for accounting huge pages (as a separate controller) 243 243 2. Make per-cgroup scanner reclaim not-shared pages first 244 244 3. Teach controller to account for shared-pages 245 - 4. Start reclamation when the limit is lowered 246 - 5. Start reclamation in the background when the limit is 245 + 4. Start reclamation in the background when the limit is 247 246 not yet hit but the usage is getting closer 248 247 249 248 Summary
+44 -4
mm/memcontrol.c
··· 812 812 return 0; 813 813 } 814 814 815 + int mem_cgroup_resize_limit(struct mem_cgroup *memcg, unsigned long long val) 816 + { 817 + 818 + int retry_count = MEM_CGROUP_RECLAIM_RETRIES; 819 + int progress; 820 + int ret = 0; 821 + 822 + while (res_counter_set_limit(&memcg->res, val)) { 823 + if (signal_pending(current)) { 824 + ret = -EINTR; 825 + break; 826 + } 827 + if (!retry_count) { 828 + ret = -EBUSY; 829 + break; 830 + } 831 + progress = try_to_free_mem_cgroup_pages(memcg, GFP_KERNEL); 832 + if (!progress) 833 + retry_count--; 834 + } 835 + return ret; 836 + } 837 + 838 + 815 839 /* 816 840 * This routine traverse page_cgroup in given list and drop them all. 817 841 * *And* this routine doesn't reclaim page itself, just removes page_cgroup. ··· 920 896 return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res, 921 897 cft->private); 922 898 } 923 - 899 + /* 900 + * The user of this function is... 901 + * RES_LIMIT. 902 + */ 924 903 static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft, 925 904 const char *buffer) 926 905 { 927 - return res_counter_write(&mem_cgroup_from_cont(cont)->res, 928 - cft->private, buffer, 929 - res_counter_memparse_write_strategy); 906 + struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); 907 + unsigned long long val; 908 + int ret; 909 + 910 + switch (cft->private) { 911 + case RES_LIMIT: 912 + /* This function does all necessary parse...reuse it */ 913 + ret = res_counter_memparse_write_strategy(buffer, &val); 914 + if (!ret) 915 + ret = mem_cgroup_resize_limit(memcg, val); 916 + break; 917 + default: 918 + ret = -EINVAL; /* should be BUG() ? */ 919 + break; 920 + } 921 + return ret; 930 922 } 931 923 932 924 static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)