Commit b24028572fb69e9dd6de8c359eba2b2c66baa889

Authored by KAMEZAWA Hiroyuki
Committed by Linus Torvalds
1 parent ca464d69b1

memcg: remove PCG_CACHE page_cgroup flag

We record 'the page is cache' with the PCG_CACHE bit in page_cgroup.
Here, "CACHE" means anonymous user pages (and SwapCache).  This doesn't
include shmem.

Considering callers, at charge/uncharge, the caller should know what the
page is and we don't need to record it by using one bit per page.

This patch removes PCG_CACHE bit and make callers of
mem_cgroup_charge_statistics() to specify what the page is.

About page migration: Mapping of the used page is not touched during migra
tion (see page_remove_rmap) so we can rely on it and push the correct
charge type down to __mem_cgroup_uncharge_common from end_migration for
unused page.  The force flag was misleading was abused for skipping the
needless page_mapped() / PageCgroupMigration() check, as we know the
unused page is no longer mapped and cleared the migration flag just a few
lines up.  But doing the checks is no biggie and it's not worth adding
another flag just to skip them.

[akpm@linux-foundation.org: checkpatch fixes]
[hughd@google.com: fix PageAnon uncharging]
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Acked-by: Michal Hocko <mhocko@suse.cz>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Ying Han <yinghan@google.com>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 33 additions and 32 deletions Side-by-side Diff

include/linux/page_cgroup.h
... ... @@ -4,7 +4,6 @@
4 4 enum {
5 5 /* flags for mem_cgroup */
6 6 PCG_LOCK, /* Lock for pc->mem_cgroup and following bits. */
7   - PCG_CACHE, /* charged as cache */
8 7 PCG_USED, /* this object is in use. */
9 8 PCG_MIGRATION, /* under page migration */
10 9 /* flags for mem_cgroup and file and I/O status */
... ... @@ -64,11 +63,6 @@
64 63 static inline int TestClearPageCgroup##uname(struct page_cgroup *pc) \
65 64 { return test_and_clear_bit(PCG_##lname, &pc->flags); }
66 65  
67   -/* Cache flag is set only once (at allocation) */
68   -TESTPCGFLAG(Cache, CACHE)
69   -CLEARPCGFLAG(Cache, CACHE)
70   -SETPCGFLAG(Cache, CACHE)
71   -
72 66 TESTPCGFLAG(Used, USED)
73 67 CLEARPCGFLAG(Used, USED)
74 68 SETPCGFLAG(Used, USED)
... ... @@ -85,7 +79,7 @@
85 79 {
86 80 /*
87 81 * Don't take this lock in IRQ context.
88   - * This lock is for pc->mem_cgroup, USED, CACHE, MIGRATION
  82 + * This lock is for pc->mem_cgroup, USED, MIGRATION
89 83 */
90 84 bit_spin_lock(PCG_LOCK, &pc->flags);
91 85 }
... ... @@ -690,15 +690,19 @@
690 690 }
691 691  
692 692 static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg,
693   - bool file, int nr_pages)
  693 + bool anon, int nr_pages)
694 694 {
695 695 preempt_disable();
696 696  
697   - if (file)
698   - __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_CACHE],
  697 + /*
  698 + * Here, RSS means 'mapped anon' and anon's SwapCache. Shmem/tmpfs is
  699 + * counted as CACHE even if it's on ANON LRU.
  700 + */
  701 + if (anon)
  702 + __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_RSS],
699 703 nr_pages);
700 704 else
701   - __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_RSS],
  705 + __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_CACHE],
702 706 nr_pages);
703 707  
704 708 /* pagein of a big page is an event. So, ignore page size */
... ... @@ -2442,6 +2446,7 @@
2442 2446 {
2443 2447 struct zone *uninitialized_var(zone);
2444 2448 bool was_on_lru = false;
  2449 + bool anon;
2445 2450  
2446 2451 lock_page_cgroup(pc);
2447 2452 if (unlikely(PageCgroupUsed(pc))) {
... ... @@ -2477,19 +2482,7 @@
2477 2482 * See mem_cgroup_add_lru_list(), etc.
2478 2483 */
2479 2484 smp_wmb();
2480   - switch (ctype) {
2481   - case MEM_CGROUP_CHARGE_TYPE_CACHE:
2482   - case MEM_CGROUP_CHARGE_TYPE_SHMEM:
2483   - SetPageCgroupCache(pc);
2484   - SetPageCgroupUsed(pc);
2485   - break;
2486   - case MEM_CGROUP_CHARGE_TYPE_MAPPED:
2487   - ClearPageCgroupCache(pc);
2488   - SetPageCgroupUsed(pc);
2489   - break;
2490   - default:
2491   - break;
2492   - }
  2485 + SetPageCgroupUsed(pc);
2493 2486  
2494 2487 if (lrucare) {
2495 2488 if (was_on_lru) {
... ... @@ -2500,7 +2493,12 @@
2500 2493 spin_unlock_irq(&zone->lru_lock);
2501 2494 }
2502 2495  
2503   - mem_cgroup_charge_statistics(memcg, PageCgroupCache(pc), nr_pages);
  2496 + if (ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED)
  2497 + anon = true;
  2498 + else
  2499 + anon = false;
  2500 +
  2501 + mem_cgroup_charge_statistics(memcg, anon, nr_pages);
2504 2502 unlock_page_cgroup(pc);
2505 2503  
2506 2504 /*
... ... @@ -2565,6 +2563,7 @@
2565 2563 {
2566 2564 unsigned long flags;
2567 2565 int ret;
  2566 + bool anon = PageAnon(page);
2568 2567  
2569 2568 VM_BUG_ON(from == to);
2570 2569 VM_BUG_ON(PageLRU(page));
2571 2570  
... ... @@ -2593,14 +2592,14 @@
2593 2592 __this_cpu_inc(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]);
2594 2593 preempt_enable();
2595 2594 }
2596   - mem_cgroup_charge_statistics(from, PageCgroupCache(pc), -nr_pages);
  2595 + mem_cgroup_charge_statistics(from, anon, -nr_pages);
2597 2596 if (uncharge)
2598 2597 /* This is not "cancel", but cancel_charge does all we need. */
2599 2598 __mem_cgroup_cancel_charge(from, nr_pages);
2600 2599  
2601 2600 /* caller should have done css_get */
2602 2601 pc->mem_cgroup = to;
2603   - mem_cgroup_charge_statistics(to, PageCgroupCache(pc), nr_pages);
  2602 + mem_cgroup_charge_statistics(to, anon, nr_pages);
2604 2603 /*
2605 2604 * We charges against "to" which may not have any tasks. Then, "to"
2606 2605 * can be under rmdir(). But in current implementation, caller of
... ... @@ -2921,6 +2920,7 @@
2921 2920 struct mem_cgroup *memcg = NULL;
2922 2921 unsigned int nr_pages = 1;
2923 2922 struct page_cgroup *pc;
  2923 + bool anon;
2924 2924  
2925 2925 if (mem_cgroup_disabled())
2926 2926 return NULL;
2927 2927  
... ... @@ -2946,8 +2946,12 @@
2946 2946 if (!PageCgroupUsed(pc))
2947 2947 goto unlock_out;
2948 2948  
  2949 + anon = PageAnon(page);
  2950 +
2949 2951 switch (ctype) {
2950 2952 case MEM_CGROUP_CHARGE_TYPE_MAPPED:
  2953 + anon = true;
  2954 + /* fallthrough */
2951 2955 case MEM_CGROUP_CHARGE_TYPE_DROP:
2952 2956 /* See mem_cgroup_prepare_migration() */
2953 2957 if (page_mapped(page) || PageCgroupMigration(pc))
... ... @@ -2964,7 +2968,7 @@
2964 2968 break;
2965 2969 }
2966 2970  
2967   - mem_cgroup_charge_statistics(memcg, PageCgroupCache(pc), -nr_pages);
  2971 + mem_cgroup_charge_statistics(memcg, anon, -nr_pages);
2968 2972  
2969 2973 ClearPageCgroupUsed(pc);
2970 2974 /*
... ... @@ -3271,6 +3275,7 @@
3271 3275 {
3272 3276 struct page *used, *unused;
3273 3277 struct page_cgroup *pc;
  3278 + bool anon;
3274 3279  
3275 3280 if (!memcg)
3276 3281 return;
3277 3282  
... ... @@ -3292,9 +3297,11 @@
3292 3297 lock_page_cgroup(pc);
3293 3298 ClearPageCgroupMigration(pc);
3294 3299 unlock_page_cgroup(pc);
  3300 + anon = PageAnon(used);
  3301 + __mem_cgroup_uncharge_common(unused,
  3302 + anon ? MEM_CGROUP_CHARGE_TYPE_MAPPED
  3303 + : MEM_CGROUP_CHARGE_TYPE_CACHE);
3295 3304  
3296   - __mem_cgroup_uncharge_common(unused, MEM_CGROUP_CHARGE_TYPE_FORCE);
3297   -
3298 3305 /*
3299 3306 * If a page is a file cache, radix-tree replacement is very atomic
3300 3307 * and we can skip this check. When it was an Anon page, its mapcount
... ... @@ -3303,7 +3310,7 @@
3303 3310 * and USED bit check in mem_cgroup_uncharge_page() will do enough
3304 3311 * check. (see prepare_charge() also)
3305 3312 */
3306   - if (PageAnon(used))
  3313 + if (anon)
3307 3314 mem_cgroup_uncharge_page(used);
3308 3315 /*
3309 3316 * At migration, we may charge account against cgroup which has no
... ... @@ -3333,7 +3340,7 @@
3333 3340 /* fix accounting on old pages */
3334 3341 lock_page_cgroup(pc);
3335 3342 memcg = pc->mem_cgroup;
3336   - mem_cgroup_charge_statistics(memcg, PageCgroupCache(pc), -1);
  3343 + mem_cgroup_charge_statistics(memcg, false, -1);
3337 3344 ClearPageCgroupUsed(pc);
3338 3345 unlock_page_cgroup(pc);
3339 3346