Skip to content

Commit 08e552c

Browse files
hkamezawatorvalds
authored andcommitted
memcg: synchronized LRU
A big patch for changing memcg's LRU semantics. Now, - page_cgroup is linked to mem_cgroup's its own LRU (per zone). - LRU of page_cgroup is not synchronous with global LRU. - page and page_cgroup is one-to-one and statically allocated. - To find page_cgroup is on what LRU, you have to check pc->mem_cgroup as - lru = page_cgroup_zoneinfo(pc, nid_of_pc, zid_of_pc); - SwapCache is handled. And, when we handle LRU list of page_cgroup, we do following. pc = lookup_page_cgroup(page); lock_page_cgroup(pc); .....................(1) mz = page_cgroup_zoneinfo(pc); spin_lock(&mz->lru_lock); .....add to LRU spin_unlock(&mz->lru_lock); unlock_page_cgroup(pc); But (1) is spin_lock and we have to be afraid of dead-lock with zone->lru_lock. So, trylock() is used at (1), now. Without (1), we can't trust "mz" is correct. This is a trial to remove this dirty nesting of locks. This patch changes mz->lru_lock to be zone->lru_lock. Then, above sequence will be written as spin_lock(&zone->lru_lock); # in vmscan.c or swap.c via global LRU mem_cgroup_add/remove/etc_lru() { pc = lookup_page_cgroup(page); mz = page_cgroup_zoneinfo(pc); if (PageCgroupUsed(pc)) { ....add to LRU } spin_lock(&zone->lru_lock); # in vmscan.c or swap.c via global LRU This is much simpler. (*) We're safe even if we don't take lock_page_cgroup(pc). Because.. 1. When pc->mem_cgroup can be modified. - at charge. - at account_move(). 2. at charge the PCG_USED bit is not set before pc->mem_cgroup is fixed. 3. at account_move() the page is isolated and not on LRU. Pros. - easy for maintenance. - memcg can make use of laziness of pagevec. - we don't have to duplicated LRU/Active/Unevictable bit in page_cgroup. - LRU status of memcg will be synchronized with global LRU's one. - # of locks are reduced. - account_move() is simplified very much. Cons. - may increase cost of LRU rotation. (no impact if memcg is not configured.) Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 8c7c6e3 commit 08e552c

File tree

8 files changed

+178
-206
lines changed

8 files changed

+178
-206
lines changed

fs/splice.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/file.h>
2222
#include <linux/pagemap.h>
2323
#include <linux/splice.h>
24+
#include <linux/memcontrol.h>
2425
#include <linux/mm_inline.h>
2526
#include <linux/swap.h>
2627
#include <linux/writeback.h>

include/linux/memcontrol.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ extern void mem_cgroup_cancel_charge_swapin(struct mem_cgroup *ptr);
4040

4141
extern int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
4242
gfp_t gfp_mask);
43-
extern void mem_cgroup_move_lists(struct page *page, enum lru_list lru);
43+
extern void mem_cgroup_add_lru_list(struct page *page, enum lru_list lru);
44+
extern void mem_cgroup_del_lru_list(struct page *page, enum lru_list lru);
45+
extern void mem_cgroup_rotate_lru_list(struct page *page, enum lru_list lru);
46+
extern void mem_cgroup_del_lru(struct page *page);
47+
extern void mem_cgroup_move_lists(struct page *page,
48+
enum lru_list from, enum lru_list to);
4449
extern void mem_cgroup_uncharge_page(struct page *page);
4550
extern void mem_cgroup_uncharge_cache_page(struct page *page);
4651
extern int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask);
@@ -131,7 +136,27 @@ static inline int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask)
131136
return 0;
132137
}
133138

134-
static inline void mem_cgroup_move_lists(struct page *page, bool active)
139+
static inline void mem_cgroup_add_lru_list(struct page *page, int lru)
140+
{
141+
}
142+
143+
static inline void mem_cgroup_del_lru_list(struct page *page, int lru)
144+
{
145+
return ;
146+
}
147+
148+
static inline void mem_cgroup_rotate_lru_list(struct page *page, int lru)
149+
{
150+
return ;
151+
}
152+
153+
static inline void mem_cgroup_del_lru(struct page *page)
154+
{
155+
return ;
156+
}
157+
158+
static inline void
159+
mem_cgroup_move_lists(struct page *page, enum lru_list from, enum lru_list to)
135160
{
136161
}
137162

include/linux/mm_inline.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ add_page_to_lru_list(struct zone *zone, struct page *page, enum lru_list l)
2828
{
2929
list_add(&page->lru, &zone->lru[l].list);
3030
__inc_zone_state(zone, NR_LRU_BASE + l);
31+
mem_cgroup_add_lru_list(page, l);
3132
}
3233

3334
static inline void
3435
del_page_from_lru_list(struct zone *zone, struct page *page, enum lru_list l)
3536
{
3637
list_del(&page->lru);
3738
__dec_zone_state(zone, NR_LRU_BASE + l);
39+
mem_cgroup_del_lru_list(page, l);
3840
}
3941

4042
static inline void
@@ -54,6 +56,7 @@ del_page_from_lru(struct zone *zone, struct page *page)
5456
l += page_is_file_cache(page);
5557
}
5658
__dec_zone_state(zone, NR_LRU_BASE + l);
59+
mem_cgroup_del_lru_list(page, l);
5760
}
5861

5962
/**

include/linux/page_cgroup.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ enum {
2626
PCG_LOCK, /* page cgroup is locked */
2727
PCG_CACHE, /* charged as cache */
2828
PCG_USED, /* this object is in use. */
29-
/* flags for LRU placement */
30-
PCG_ACTIVE, /* page is active in this cgroup */
31-
PCG_FILE, /* page is file system backed */
32-
PCG_UNEVICTABLE, /* page is unevictableable */
3329
};
3430

3531
#define TESTPCGFLAG(uname, lname) \
@@ -50,19 +46,6 @@ TESTPCGFLAG(Cache, CACHE)
5046
TESTPCGFLAG(Used, USED)
5147
CLEARPCGFLAG(Used, USED)
5248

53-
/* LRU management flags (from global-lru definition) */
54-
TESTPCGFLAG(File, FILE)
55-
SETPCGFLAG(File, FILE)
56-
CLEARPCGFLAG(File, FILE)
57-
58-
TESTPCGFLAG(Active, ACTIVE)
59-
SETPCGFLAG(Active, ACTIVE)
60-
CLEARPCGFLAG(Active, ACTIVE)
61-
62-
TESTPCGFLAG(Unevictable, UNEVICTABLE)
63-
SETPCGFLAG(Unevictable, UNEVICTABLE)
64-
CLEARPCGFLAG(Unevictable, UNEVICTABLE)
65-
6649
static inline int page_cgroup_nid(struct page_cgroup *pc)
6750
{
6851
return page_to_nid(pc->page);

0 commit comments

Comments
 (0)