Commit e9f8974f2f559b00c87ccfba67bca3903f913d50
Committed by
Linus Torvalds
1 parent
7ec99d6213
Exists in
master
and in
7 other branches
memcg: break out event counters from other stats
For increasing and decreasing per-cpu cgroup usage counters it makes sense to use signed types, as single per-cpu values might go negative during updates. But this is not the case for only-ever-increasing event counters. All the counters have been signed 64-bit so far, which was enough to count events even with the sign bit wasted. This patch: - divides s64 counters into signed usage counters and unsigned monotonically increasing event counters. - converts unsigned event counters into 'unsigned long' rather than 'u64'. This matches the type used by the /proc/vmstat event counters. The next patch narrows the signed usage counters type (on 32-bit CPUs, that is). Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Signed-off-by: Greg Thelen <gthelen@google.com> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 37 additions and 12 deletions Side-by-side Diff
mm/memcontrol.c
... | ... | @@ -93,19 +93,22 @@ |
93 | 93 | MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */ |
94 | 94 | MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */ |
95 | 95 | MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */ |
96 | - MEM_CGROUP_STAT_PGPGIN_COUNT, /* # of pages paged in */ | |
97 | - MEM_CGROUP_STAT_PGPGOUT_COUNT, /* # of pages paged out */ | |
98 | 96 | MEM_CGROUP_STAT_SWAPOUT, /* # of pages, swapped out */ |
99 | 97 | MEM_CGROUP_STAT_DATA, /* end of data requires synchronization */ |
100 | - /* incremented at every pagein/pageout */ | |
101 | - MEM_CGROUP_EVENTS = MEM_CGROUP_STAT_DATA, | |
102 | 98 | MEM_CGROUP_ON_MOVE, /* someone is moving account between groups */ |
103 | - | |
104 | 99 | MEM_CGROUP_STAT_NSTATS, |
105 | 100 | }; |
106 | 101 | |
102 | +enum mem_cgroup_events_index { | |
103 | + MEM_CGROUP_EVENTS_PGPGIN, /* # of pages paged in */ | |
104 | + MEM_CGROUP_EVENTS_PGPGOUT, /* # of pages paged out */ | |
105 | + MEM_CGROUP_EVENTS_COUNT, /* # of pages paged in/out */ | |
106 | + MEM_CGROUP_EVENTS_NSTATS, | |
107 | +}; | |
108 | + | |
107 | 109 | struct mem_cgroup_stat_cpu { |
108 | 110 | s64 count[MEM_CGROUP_STAT_NSTATS]; |
111 | + unsigned long events[MEM_CGROUP_EVENTS_NSTATS]; | |
109 | 112 | }; |
110 | 113 | |
111 | 114 | /* |
... | ... | @@ -577,6 +580,22 @@ |
577 | 580 | this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_SWAPOUT], val); |
578 | 581 | } |
579 | 582 | |
583 | +static unsigned long mem_cgroup_read_events(struct mem_cgroup *mem, | |
584 | + enum mem_cgroup_events_index idx) | |
585 | +{ | |
586 | + unsigned long val = 0; | |
587 | + int cpu; | |
588 | + | |
589 | + for_each_online_cpu(cpu) | |
590 | + val += per_cpu(mem->stat->events[idx], cpu); | |
591 | +#ifdef CONFIG_HOTPLUG_CPU | |
592 | + spin_lock(&mem->pcp_counter_lock); | |
593 | + val += mem->nocpu_base.events[idx]; | |
594 | + spin_unlock(&mem->pcp_counter_lock); | |
595 | +#endif | |
596 | + return val; | |
597 | +} | |
598 | + | |
580 | 599 | static void mem_cgroup_charge_statistics(struct mem_cgroup *mem, |
581 | 600 | bool file, int nr_pages) |
582 | 601 | { |
583 | 602 | |
584 | 603 | |
... | ... | @@ -589,13 +608,13 @@ |
589 | 608 | |
590 | 609 | /* pagein of a big page is an event. So, ignore page size */ |
591 | 610 | if (nr_pages > 0) |
592 | - __this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGIN_COUNT]); | |
611 | + __this_cpu_inc(mem->stat->events[MEM_CGROUP_EVENTS_PGPGIN]); | |
593 | 612 | else { |
594 | - __this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGOUT_COUNT]); | |
613 | + __this_cpu_inc(mem->stat->events[MEM_CGROUP_EVENTS_PGPGOUT]); | |
595 | 614 | nr_pages = -nr_pages; /* for event */ |
596 | 615 | } |
597 | 616 | |
598 | - __this_cpu_add(mem->stat->count[MEM_CGROUP_EVENTS], nr_pages); | |
617 | + __this_cpu_add(mem->stat->events[MEM_CGROUP_EVENTS_COUNT], nr_pages); | |
599 | 618 | |
600 | 619 | preempt_enable(); |
601 | 620 | } |
602 | 621 | |
... | ... | @@ -617,9 +636,9 @@ |
617 | 636 | |
618 | 637 | static bool __memcg_event_check(struct mem_cgroup *mem, int event_mask_shift) |
619 | 638 | { |
620 | - s64 val; | |
639 | + unsigned long val; | |
621 | 640 | |
622 | - val = this_cpu_read(mem->stat->count[MEM_CGROUP_EVENTS]); | |
641 | + val = this_cpu_read(mem->stat->events[MEM_CGROUP_EVENTS_COUNT]); | |
623 | 642 | |
624 | 643 | return !(val & ((1 << event_mask_shift) - 1)); |
625 | 644 | } |
... | ... | @@ -1773,6 +1792,12 @@ |
1773 | 1792 | per_cpu(mem->stat->count[i], cpu) = 0; |
1774 | 1793 | mem->nocpu_base.count[i] += x; |
1775 | 1794 | } |
1795 | + for (i = 0; i < MEM_CGROUP_EVENTS_NSTATS; i++) { | |
1796 | + unsigned long x = per_cpu(mem->stat->events[i], cpu); | |
1797 | + | |
1798 | + per_cpu(mem->stat->events[i], cpu) = 0; | |
1799 | + mem->nocpu_base.events[i] += x; | |
1800 | + } | |
1776 | 1801 | /* need to clear ON_MOVE value, works as a kind of lock. */ |
1777 | 1802 | per_cpu(mem->stat->count[MEM_CGROUP_ON_MOVE], cpu) = 0; |
1778 | 1803 | spin_unlock(&mem->pcp_counter_lock); |
1779 | 1804 | |
... | ... | @@ -3725,9 +3750,9 @@ |
3725 | 3750 | s->stat[MCS_RSS] += val * PAGE_SIZE; |
3726 | 3751 | val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_FILE_MAPPED); |
3727 | 3752 | s->stat[MCS_FILE_MAPPED] += val * PAGE_SIZE; |
3728 | - val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_PGPGIN_COUNT); | |
3753 | + val = mem_cgroup_read_events(mem, MEM_CGROUP_EVENTS_PGPGIN); | |
3729 | 3754 | s->stat[MCS_PGPGIN] += val; |
3730 | - val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_PGPGOUT_COUNT); | |
3755 | + val = mem_cgroup_read_events(mem, MEM_CGROUP_EVENTS_PGPGOUT); | |
3731 | 3756 | s->stat[MCS_PGPGOUT] += val; |
3732 | 3757 | if (do_swap_account) { |
3733 | 3758 | val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_SWAPOUT); |