aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/memcontrol.c264
1 files changed, 125 insertions, 139 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index ebf1139f323e..c7a9cb627180 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -72,22 +72,13 @@ EXPORT_SYMBOL(memory_cgrp_subsys);
72#define MEM_CGROUP_RECLAIM_RETRIES 5 72#define MEM_CGROUP_RECLAIM_RETRIES 5
73static struct mem_cgroup *root_mem_cgroup __read_mostly; 73static struct mem_cgroup *root_mem_cgroup __read_mostly;
74 74
75/* Whether the swap controller is active */
75#ifdef CONFIG_MEMCG_SWAP 76#ifdef CONFIG_MEMCG_SWAP
76/* Turned on only when memory cgroup is enabled && really_do_swap_account = 1 */
77int do_swap_account __read_mostly; 77int do_swap_account __read_mostly;
78
79/* for remember boot option*/
80#ifdef CONFIG_MEMCG_SWAP_ENABLED
81static int really_do_swap_account __initdata = 1;
82#else
83static int really_do_swap_account __initdata;
84#endif
85
86#else 78#else
87#define do_swap_account 0 79#define do_swap_account 0
88#endif 80#endif
89 81
90
91static const char * const mem_cgroup_stat_names[] = { 82static const char * const mem_cgroup_stat_names[] = {
92 "cache", 83 "cache",
93 "rss", 84 "rss",
@@ -4373,34 +4364,6 @@ static struct cftype mem_cgroup_legacy_files[] = {
4373 { }, /* terminate */ 4364 { }, /* terminate */
4374}; 4365};
4375 4366
4376#ifdef CONFIG_MEMCG_SWAP
4377static struct cftype memsw_cgroup_files[] = {
4378 {
4379 .name = "memsw.usage_in_bytes",
4380 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
4381 .read_u64 = mem_cgroup_read_u64,
4382 },
4383 {
4384 .name = "memsw.max_usage_in_bytes",
4385 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE),
4386 .write = mem_cgroup_reset,
4387 .read_u64 = mem_cgroup_read_u64,
4388 },
4389 {
4390 .name = "memsw.limit_in_bytes",
4391 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT),
4392 .write = mem_cgroup_write,
4393 .read_u64 = mem_cgroup_read_u64,
4394 },
4395 {
4396 .name = "memsw.failcnt",
4397 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT),
4398 .write = mem_cgroup_reset,
4399 .read_u64 = mem_cgroup_read_u64,
4400 },
4401 { }, /* terminate */
4402};
4403#endif
4404static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node) 4367static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
4405{ 4368{
4406 struct mem_cgroup_per_node *pn; 4369 struct mem_cgroup_per_node *pn;
@@ -5391,37 +5354,6 @@ struct cgroup_subsys memory_cgrp_subsys = {
5391 .early_init = 0, 5354 .early_init = 0,
5392}; 5355};
5393 5356
5394#ifdef CONFIG_MEMCG_SWAP
5395static int __init enable_swap_account(char *s)
5396{
5397 if (!strcmp(s, "1"))
5398 really_do_swap_account = 1;
5399 else if (!strcmp(s, "0"))
5400 really_do_swap_account = 0;
5401 return 1;
5402}
5403__setup("swapaccount=", enable_swap_account);
5404
5405static void __init memsw_file_init(void)
5406{
5407 WARN_ON(cgroup_add_legacy_cftypes(&memory_cgrp_subsys,
5408 memsw_cgroup_files));
5409}
5410
5411static void __init enable_swap_cgroup(void)
5412{
5413 if (!mem_cgroup_disabled() && really_do_swap_account) {
5414 do_swap_account = 1;
5415 memsw_file_init();
5416 }
5417}
5418
5419#else
5420static void __init enable_swap_cgroup(void)
5421{
5422}
5423#endif
5424
5425/** 5357/**
5426 * mem_cgroup_events - count memory events against a cgroup 5358 * mem_cgroup_events - count memory events against a cgroup
5427 * @memcg: the memory cgroup 5359 * @memcg: the memory cgroup
@@ -5472,74 +5404,6 @@ bool mem_cgroup_low(struct mem_cgroup *root, struct mem_cgroup *memcg)
5472 return true; 5404 return true;
5473} 5405}
5474 5406
5475#ifdef CONFIG_MEMCG_SWAP
5476/**
5477 * mem_cgroup_swapout - transfer a memsw charge to swap
5478 * @page: page whose memsw charge to transfer
5479 * @entry: swap entry to move the charge to
5480 *
5481 * Transfer the memsw charge of @page to @entry.
5482 */
5483void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
5484{
5485 struct mem_cgroup *memcg;
5486 unsigned short oldid;
5487
5488 VM_BUG_ON_PAGE(PageLRU(page), page);
5489 VM_BUG_ON_PAGE(page_count(page), page);
5490
5491 if (!do_swap_account)
5492 return;
5493
5494 memcg = page->mem_cgroup;
5495
5496 /* Readahead page, never charged */
5497 if (!memcg)
5498 return;
5499
5500 oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg));
5501 VM_BUG_ON_PAGE(oldid, page);
5502 mem_cgroup_swap_statistics(memcg, true);
5503
5504 page->mem_cgroup = NULL;
5505
5506 if (!mem_cgroup_is_root(memcg))
5507 page_counter_uncharge(&memcg->memory, 1);
5508
5509 /* XXX: caller holds IRQ-safe mapping->tree_lock */
5510 VM_BUG_ON(!irqs_disabled());
5511
5512 mem_cgroup_charge_statistics(memcg, page, -1);
5513 memcg_check_events(memcg, page);
5514}
5515
5516/**
5517 * mem_cgroup_uncharge_swap - uncharge a swap entry
5518 * @entry: swap entry to uncharge
5519 *
5520 * Drop the memsw charge associated with @entry.
5521 */
5522void mem_cgroup_uncharge_swap(swp_entry_t entry)
5523{
5524 struct mem_cgroup *memcg;
5525 unsigned short id;
5526
5527 if (!do_swap_account)
5528 return;
5529
5530 id = swap_cgroup_record(entry, 0);
5531 rcu_read_lock();
5532 memcg = mem_cgroup_lookup(id);
5533 if (memcg) {
5534 if (!mem_cgroup_is_root(memcg))
5535 page_counter_uncharge(&memcg->memsw, 1);
5536 mem_cgroup_swap_statistics(memcg, false);
5537 css_put(&memcg->css);
5538 }
5539 rcu_read_unlock();
5540}
5541#endif
5542
5543/** 5407/**
5544 * mem_cgroup_try_charge - try charging a page 5408 * mem_cgroup_try_charge - try charging a page
5545 * @page: page to charge 5409 * @page: page to charge
@@ -5897,8 +5761,130 @@ static int __init mem_cgroup_init(void)
5897 soft_limit_tree.rb_tree_per_node[node] = rtpn; 5761 soft_limit_tree.rb_tree_per_node[node] = rtpn;
5898 } 5762 }
5899 5763
5900 enable_swap_cgroup();
5901
5902 return 0; 5764 return 0;
5903} 5765}
5904subsys_initcall(mem_cgroup_init); 5766subsys_initcall(mem_cgroup_init);
5767
5768#ifdef CONFIG_MEMCG_SWAP
5769/**
5770 * mem_cgroup_swapout - transfer a memsw charge to swap
5771 * @page: page whose memsw charge to transfer
5772 * @entry: swap entry to move the charge to
5773 *
5774 * Transfer the memsw charge of @page to @entry.
5775 */
5776void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
5777{
5778 struct mem_cgroup *memcg;
5779 unsigned short oldid;
5780
5781 VM_BUG_ON_PAGE(PageLRU(page), page);
5782 VM_BUG_ON_PAGE(page_count(page), page);
5783
5784 if (!do_swap_account)
5785 return;
5786
5787 memcg = page->mem_cgroup;
5788
5789 /* Readahead page, never charged */
5790 if (!memcg)
5791 return;
5792
5793 oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg));
5794 VM_BUG_ON_PAGE(oldid, page);
5795 mem_cgroup_swap_statistics(memcg, true);
5796
5797 page->mem_cgroup = NULL;
5798
5799 if (!mem_cgroup_is_root(memcg))
5800 page_counter_uncharge(&memcg->memory, 1);
5801
5802 /* XXX: caller holds IRQ-safe mapping->tree_lock */
5803 VM_BUG_ON(!irqs_disabled());
5804
5805 mem_cgroup_charge_statistics(memcg, page, -1);
5806 memcg_check_events(memcg, page);
5807}
5808
5809/**
5810 * mem_cgroup_uncharge_swap - uncharge a swap entry
5811 * @entry: swap entry to uncharge
5812 *
5813 * Drop the memsw charge associated with @entry.
5814 */
5815void mem_cgroup_uncharge_swap(swp_entry_t entry)
5816{
5817 struct mem_cgroup *memcg;
5818 unsigned short id;
5819
5820 if (!do_swap_account)
5821 return;
5822
5823 id = swap_cgroup_record(entry, 0);
5824 rcu_read_lock();
5825 memcg = mem_cgroup_lookup(id);
5826 if (memcg) {
5827 if (!mem_cgroup_is_root(memcg))
5828 page_counter_uncharge(&memcg->memsw, 1);
5829 mem_cgroup_swap_statistics(memcg, false);
5830 css_put(&memcg->css);
5831 }
5832 rcu_read_unlock();
5833}
5834
5835/* for remember boot option*/
5836#ifdef CONFIG_MEMCG_SWAP_ENABLED
5837static int really_do_swap_account __initdata = 1;
5838#else
5839static int really_do_swap_account __initdata;
5840#endif
5841
5842static int __init enable_swap_account(char *s)
5843{
5844 if (!strcmp(s, "1"))
5845 really_do_swap_account = 1;
5846 else if (!strcmp(s, "0"))
5847 really_do_swap_account = 0;
5848 return 1;
5849}
5850__setup("swapaccount=", enable_swap_account);
5851
5852static struct cftype memsw_cgroup_files[] = {
5853 {
5854 .name = "memsw.usage_in_bytes",
5855 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
5856 .read_u64 = mem_cgroup_read_u64,
5857 },
5858 {
5859 .name = "memsw.max_usage_in_bytes",
5860 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE),
5861 .write = mem_cgroup_reset,
5862 .read_u64 = mem_cgroup_read_u64,
5863 },
5864 {
5865 .name = "memsw.limit_in_bytes",
5866 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT),
5867 .write = mem_cgroup_write,
5868 .read_u64 = mem_cgroup_read_u64,
5869 },
5870 {
5871 .name = "memsw.failcnt",
5872 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT),
5873 .write = mem_cgroup_reset,
5874 .read_u64 = mem_cgroup_read_u64,
5875 },
5876 { }, /* terminate */
5877};
5878
5879static int __init mem_cgroup_swap_init(void)
5880{
5881 if (!mem_cgroup_disabled() && really_do_swap_account) {
5882 do_swap_account = 1;
5883 WARN_ON(cgroup_add_legacy_cftypes(&memory_cgrp_subsys,
5884 memsw_cgroup_files));
5885 }
5886 return 0;
5887}
5888subsys_initcall(mem_cgroup_swap_init);
5889
5890#endif /* CONFIG_MEMCG_SWAP */