diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memcontrol.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0f1d92163f30..cb1c9dedf9b6 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -92,16 +92,18 @@ enum mem_cgroup_stat_index { | |||
92 | /* | 92 | /* |
93 | * For MEM_CONTAINER_TYPE_ALL, usage = pagecache + rss. | 93 | * For MEM_CONTAINER_TYPE_ALL, usage = pagecache + rss. |
94 | */ | 94 | */ |
95 | MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */ | 95 | MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */ |
96 | MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */ | 96 | MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */ |
97 | MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */ | 97 | MEM_CGROUP_STAT_RSS_HUGE, /* # of pages charged as anon huge */ |
98 | MEM_CGROUP_STAT_SWAP, /* # of pages, swapped out */ | 98 | MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */ |
99 | MEM_CGROUP_STAT_SWAP, /* # of pages, swapped out */ | ||
99 | MEM_CGROUP_STAT_NSTATS, | 100 | MEM_CGROUP_STAT_NSTATS, |
100 | }; | 101 | }; |
101 | 102 | ||
102 | static const char * const mem_cgroup_stat_names[] = { | 103 | static const char * const mem_cgroup_stat_names[] = { |
103 | "cache", | 104 | "cache", |
104 | "rss", | 105 | "rss", |
106 | "rss_huge", | ||
105 | "mapped_file", | 107 | "mapped_file", |
106 | "swap", | 108 | "swap", |
107 | }; | 109 | }; |
@@ -917,6 +919,7 @@ static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg, | |||
917 | } | 919 | } |
918 | 920 | ||
919 | static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg, | 921 | static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg, |
922 | struct page *page, | ||
920 | bool anon, int nr_pages) | 923 | bool anon, int nr_pages) |
921 | { | 924 | { |
922 | preempt_disable(); | 925 | preempt_disable(); |
@@ -932,6 +935,10 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg, | |||
932 | __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_CACHE], | 935 | __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_CACHE], |
933 | nr_pages); | 936 | nr_pages); |
934 | 937 | ||
938 | if (PageTransHuge(page)) | ||
939 | __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_RSS_HUGE], | ||
940 | nr_pages); | ||
941 | |||
935 | /* pagein of a big page is an event. So, ignore page size */ | 942 | /* pagein of a big page is an event. So, ignore page size */ |
936 | if (nr_pages > 0) | 943 | if (nr_pages > 0) |
937 | __this_cpu_inc(memcg->stat->events[MEM_CGROUP_EVENTS_PGPGIN]); | 944 | __this_cpu_inc(memcg->stat->events[MEM_CGROUP_EVENTS_PGPGIN]); |
@@ -2914,7 +2921,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg, | |||
2914 | else | 2921 | else |
2915 | anon = false; | 2922 | anon = false; |
2916 | 2923 | ||
2917 | mem_cgroup_charge_statistics(memcg, anon, nr_pages); | 2924 | mem_cgroup_charge_statistics(memcg, page, anon, nr_pages); |
2918 | unlock_page_cgroup(pc); | 2925 | unlock_page_cgroup(pc); |
2919 | 2926 | ||
2920 | /* | 2927 | /* |
@@ -3708,16 +3715,21 @@ void mem_cgroup_split_huge_fixup(struct page *head) | |||
3708 | { | 3715 | { |
3709 | struct page_cgroup *head_pc = lookup_page_cgroup(head); | 3716 | struct page_cgroup *head_pc = lookup_page_cgroup(head); |
3710 | struct page_cgroup *pc; | 3717 | struct page_cgroup *pc; |
3718 | struct mem_cgroup *memcg; | ||
3711 | int i; | 3719 | int i; |
3712 | 3720 | ||
3713 | if (mem_cgroup_disabled()) | 3721 | if (mem_cgroup_disabled()) |
3714 | return; | 3722 | return; |
3723 | |||
3724 | memcg = head_pc->mem_cgroup; | ||
3715 | for (i = 1; i < HPAGE_PMD_NR; i++) { | 3725 | for (i = 1; i < HPAGE_PMD_NR; i++) { |
3716 | pc = head_pc + i; | 3726 | pc = head_pc + i; |
3717 | pc->mem_cgroup = head_pc->mem_cgroup; | 3727 | pc->mem_cgroup = memcg; |
3718 | smp_wmb();/* see __commit_charge() */ | 3728 | smp_wmb();/* see __commit_charge() */ |
3719 | pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT; | 3729 | pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT; |
3720 | } | 3730 | } |
3731 | __this_cpu_sub(memcg->stat->count[MEM_CGROUP_STAT_RSS_HUGE], | ||
3732 | HPAGE_PMD_NR); | ||
3721 | } | 3733 | } |
3722 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | 3734 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
3723 | 3735 | ||
@@ -3773,11 +3785,11 @@ static int mem_cgroup_move_account(struct page *page, | |||
3773 | __this_cpu_inc(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]); | 3785 | __this_cpu_inc(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]); |
3774 | preempt_enable(); | 3786 | preempt_enable(); |
3775 | } | 3787 | } |
3776 | mem_cgroup_charge_statistics(from, anon, -nr_pages); | 3788 | mem_cgroup_charge_statistics(from, page, anon, -nr_pages); |
3777 | 3789 | ||
3778 | /* caller should have done css_get */ | 3790 | /* caller should have done css_get */ |
3779 | pc->mem_cgroup = to; | 3791 | pc->mem_cgroup = to; |
3780 | mem_cgroup_charge_statistics(to, anon, nr_pages); | 3792 | mem_cgroup_charge_statistics(to, page, anon, nr_pages); |
3781 | move_unlock_mem_cgroup(from, &flags); | 3793 | move_unlock_mem_cgroup(from, &flags); |
3782 | ret = 0; | 3794 | ret = 0; |
3783 | unlock: | 3795 | unlock: |
@@ -4152,7 +4164,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype, | |||
4152 | break; | 4164 | break; |
4153 | } | 4165 | } |
4154 | 4166 | ||
4155 | mem_cgroup_charge_statistics(memcg, anon, -nr_pages); | 4167 | mem_cgroup_charge_statistics(memcg, page, anon, -nr_pages); |
4156 | 4168 | ||
4157 | ClearPageCgroupUsed(pc); | 4169 | ClearPageCgroupUsed(pc); |
4158 | /* | 4170 | /* |
@@ -4502,7 +4514,7 @@ void mem_cgroup_replace_page_cache(struct page *oldpage, | |||
4502 | lock_page_cgroup(pc); | 4514 | lock_page_cgroup(pc); |
4503 | if (PageCgroupUsed(pc)) { | 4515 | if (PageCgroupUsed(pc)) { |
4504 | memcg = pc->mem_cgroup; | 4516 | memcg = pc->mem_cgroup; |
4505 | mem_cgroup_charge_statistics(memcg, false, -1); | 4517 | mem_cgroup_charge_statistics(memcg, oldpage, false, -1); |
4506 | ClearPageCgroupUsed(pc); | 4518 | ClearPageCgroupUsed(pc); |
4507 | } | 4519 | } |
4508 | unlock_page_cgroup(pc); | 4520 | unlock_page_cgroup(pc); |
@@ -5030,6 +5042,10 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap) | |||
5030 | return res_counter_read_u64(&memcg->memsw, RES_USAGE); | 5042 | return res_counter_read_u64(&memcg->memsw, RES_USAGE); |
5031 | } | 5043 | } |
5032 | 5044 | ||
5045 | /* | ||
5046 | * Transparent hugepages are still accounted for in MEM_CGROUP_STAT_RSS | ||
5047 | * as well as in MEM_CGROUP_STAT_RSS_HUGE. | ||
5048 | */ | ||
5033 | val = mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_CACHE); | 5049 | val = mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_CACHE); |
5034 | val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_RSS); | 5050 | val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_RSS); |
5035 | 5051 | ||