aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>2009-01-07 21:08:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-08 11:31:08 -0500
commit3e2f41f1f64744f7942980d93cc93dd3e5924560 (patch)
tree7b605c407b7470877fd9c5c853407f75edcbeb49
parenta3d8e0549d913e30968fa02e505dfe02c0a23e0d (diff)
memcg: add zone_reclaim_stat
Introduce mem_cgroup_per_zone::reclaim_stat member and its statics collecting function. Now, get_scan_ratio() can calculate correct value on memcg reclaim. [hugh@veritas.com: avoid reclaim_stat oops when disabled] Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: Rik van Riel <riel@redhat.com> Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Cc: Hugh Dickins <hugh@veritas.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/memcontrol.h16
-rw-r--r--mm/memcontrol.c29
-rw-r--r--mm/swap.c34
-rw-r--r--mm/vmscan.c27
4 files changed, 83 insertions, 23 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index b1defd6a2783..36b8ebb39b82 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -105,6 +105,10 @@ int mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg,
105unsigned long mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg, 105unsigned long mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg,
106 struct zone *zone, 106 struct zone *zone,
107 enum lru_list lru); 107 enum lru_list lru);
108struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg,
109 struct zone *zone);
110struct zone_reclaim_stat*
111mem_cgroup_get_reclaim_stat_from_page(struct page *page);
108 112
109#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP 113#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
110extern int do_swap_account; 114extern int do_swap_account;
@@ -271,6 +275,18 @@ mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg, struct zone *zone,
271} 275}
272 276
273 277
278static inline struct zone_reclaim_stat*
279mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg, struct zone *zone)
280{
281 return NULL;
282}
283
284static inline struct zone_reclaim_stat*
285mem_cgroup_get_reclaim_stat_from_page(struct page *page)
286{
287 return NULL;
288}
289
274#endif /* CONFIG_CGROUP_MEM_CONT */ 290#endif /* CONFIG_CGROUP_MEM_CONT */
275 291
276#endif /* _LINUX_MEMCONTROL_H */ 292#endif /* _LINUX_MEMCONTROL_H */
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 313247e6c503..7b7f4dc05035 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -103,6 +103,8 @@ struct mem_cgroup_per_zone {
103 */ 103 */
104 struct list_head lists[NR_LRU_LISTS]; 104 struct list_head lists[NR_LRU_LISTS];
105 unsigned long count[NR_LRU_LISTS]; 105 unsigned long count[NR_LRU_LISTS];
106
107 struct zone_reclaim_stat reclaim_stat;
106}; 108};
107/* Macro for accessing counter */ 109/* Macro for accessing counter */
108#define MEM_CGROUP_ZSTAT(mz, idx) ((mz)->count[(idx)]) 110#define MEM_CGROUP_ZSTAT(mz, idx) ((mz)->count[(idx)])
@@ -458,6 +460,33 @@ unsigned long mem_cgroup_zone_nr_pages(struct mem_cgroup *memcg,
458 return MEM_CGROUP_ZSTAT(mz, lru); 460 return MEM_CGROUP_ZSTAT(mz, lru);
459} 461}
460 462
463struct zone_reclaim_stat *mem_cgroup_get_reclaim_stat(struct mem_cgroup *memcg,
464 struct zone *zone)
465{
466 int nid = zone->zone_pgdat->node_id;
467 int zid = zone_idx(zone);
468 struct mem_cgroup_per_zone *mz = mem_cgroup_zoneinfo(memcg, nid, zid);
469
470 return &mz->reclaim_stat;
471}
472
473struct zone_reclaim_stat *
474mem_cgroup_get_reclaim_stat_from_page(struct page *page)
475{
476 struct page_cgroup *pc;
477 struct mem_cgroup_per_zone *mz;
478
479 if (mem_cgroup_disabled())
480 return NULL;
481
482 pc = lookup_page_cgroup(page);
483 mz = page_cgroup_zoneinfo(pc);
484 if (!mz)
485 return NULL;
486
487 return &mz->reclaim_stat;
488}
489
461unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, 490unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
462 struct list_head *dst, 491 struct list_head *dst,
463 unsigned long *scanned, int order, 492 unsigned long *scanned, int order,
diff --git a/mm/swap.c b/mm/swap.c
index 26b07e7bc3d3..8adb9feb61e1 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -151,13 +151,32 @@ void rotate_reclaimable_page(struct page *page)
151 } 151 }
152} 152}
153 153
154static void update_page_reclaim_stat(struct zone *zone, struct page *page,
155 int file, int rotated)
156{
157 struct zone_reclaim_stat *reclaim_stat = &zone->reclaim_stat;
158 struct zone_reclaim_stat *memcg_reclaim_stat;
159
160 memcg_reclaim_stat = mem_cgroup_get_reclaim_stat_from_page(page);
161
162 reclaim_stat->recent_scanned[file]++;
163 if (rotated)
164 reclaim_stat->recent_rotated[file]++;
165
166 if (!memcg_reclaim_stat)
167 return;
168
169 memcg_reclaim_stat->recent_scanned[file]++;
170 if (rotated)
171 memcg_reclaim_stat->recent_rotated[file]++;
172}
173
154/* 174/*
155 * FIXME: speed this up? 175 * FIXME: speed this up?
156 */ 176 */
157void activate_page(struct page *page) 177void activate_page(struct page *page)
158{ 178{
159 struct zone *zone = page_zone(page); 179 struct zone *zone = page_zone(page);
160 struct zone_reclaim_stat *reclaim_stat = &zone->reclaim_stat;
161 180
162 spin_lock_irq(&zone->lru_lock); 181 spin_lock_irq(&zone->lru_lock);
163 if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) { 182 if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
@@ -170,8 +189,7 @@ void activate_page(struct page *page)
170 add_page_to_lru_list(zone, page, lru); 189 add_page_to_lru_list(zone, page, lru);
171 __count_vm_event(PGACTIVATE); 190 __count_vm_event(PGACTIVATE);
172 191
173 reclaim_stat->recent_rotated[!!file]++; 192 update_page_reclaim_stat(zone, page, !!file, 1);
174 reclaim_stat->recent_scanned[!!file]++;
175 } 193 }
176 spin_unlock_irq(&zone->lru_lock); 194 spin_unlock_irq(&zone->lru_lock);
177} 195}
@@ -386,7 +404,6 @@ void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru)
386{ 404{
387 int i; 405 int i;
388 struct zone *zone = NULL; 406 struct zone *zone = NULL;
389 struct zone_reclaim_stat *reclaim_stat = NULL;
390 407
391 VM_BUG_ON(is_unevictable_lru(lru)); 408 VM_BUG_ON(is_unevictable_lru(lru));
392 409
@@ -394,24 +411,23 @@ void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru)
394 struct page *page = pvec->pages[i]; 411 struct page *page = pvec->pages[i];
395 struct zone *pagezone = page_zone(page); 412 struct zone *pagezone = page_zone(page);
396 int file; 413 int file;
414 int active;
397 415
398 if (pagezone != zone) { 416 if (pagezone != zone) {
399 if (zone) 417 if (zone)
400 spin_unlock_irq(&zone->lru_lock); 418 spin_unlock_irq(&zone->lru_lock);
401 zone = pagezone; 419 zone = pagezone;
402 reclaim_stat = &zone->reclaim_stat;
403 spin_lock_irq(&zone->lru_lock); 420 spin_lock_irq(&zone->lru_lock);
404 } 421 }
405 VM_BUG_ON(PageActive(page)); 422 VM_BUG_ON(PageActive(page));
406 VM_BUG_ON(PageUnevictable(page)); 423 VM_BUG_ON(PageUnevictable(page));
407 VM_BUG_ON(PageLRU(page)); 424 VM_BUG_ON(PageLRU(page));
408 SetPageLRU(page); 425 SetPageLRU(page);
426 active = is_active_lru(lru);
409 file = is_file_lru(lru); 427 file = is_file_lru(lru);
410 reclaim_stat->recent_scanned[file]++; 428 if (active)
411 if (is_active_lru(lru)) {
412 SetPageActive(page); 429 SetPageActive(page);
413 reclaim_stat->recent_rotated[file]++; 430 update_page_reclaim_stat(zone, page, file, active);
414 }
415 add_page_to_lru_list(zone, page, lru); 431 add_page_to_lru_list(zone, page, lru);
416 } 432 }
417 if (zone) 433 if (zone)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d958d624d3ae..56fc7abe4d23 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -133,6 +133,9 @@ static DECLARE_RWSEM(shrinker_rwsem);
133static struct zone_reclaim_stat *get_reclaim_stat(struct zone *zone, 133static struct zone_reclaim_stat *get_reclaim_stat(struct zone *zone,
134 struct scan_control *sc) 134 struct scan_control *sc)
135{ 135{
136 if (!scan_global_lru(sc))
137 return mem_cgroup_get_reclaim_stat(sc->mem_cgroup, zone);
138
136 return &zone->reclaim_stat; 139 return &zone->reclaim_stat;
137} 140}
138 141
@@ -1087,17 +1090,14 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
1087 __mod_zone_page_state(zone, NR_INACTIVE_ANON, 1090 __mod_zone_page_state(zone, NR_INACTIVE_ANON,
1088 -count[LRU_INACTIVE_ANON]); 1091 -count[LRU_INACTIVE_ANON]);
1089 1092
1090 if (scan_global_lru(sc)) { 1093 if (scan_global_lru(sc))
1091 zone->pages_scanned += nr_scan; 1094 zone->pages_scanned += nr_scan;
1092 reclaim_stat->recent_scanned[0] += 1095
1093 count[LRU_INACTIVE_ANON]; 1096 reclaim_stat->recent_scanned[0] += count[LRU_INACTIVE_ANON];
1094 reclaim_stat->recent_scanned[0] += 1097 reclaim_stat->recent_scanned[0] += count[LRU_ACTIVE_ANON];
1095 count[LRU_ACTIVE_ANON]; 1098 reclaim_stat->recent_scanned[1] += count[LRU_INACTIVE_FILE];
1096 reclaim_stat->recent_scanned[1] += 1099 reclaim_stat->recent_scanned[1] += count[LRU_ACTIVE_FILE];
1097 count[LRU_INACTIVE_FILE]; 1100
1098 reclaim_stat->recent_scanned[1] +=
1099 count[LRU_ACTIVE_FILE];
1100 }
1101 spin_unlock_irq(&zone->lru_lock); 1101 spin_unlock_irq(&zone->lru_lock);
1102 1102
1103 nr_scanned += nr_scan; 1103 nr_scanned += nr_scan;
@@ -1155,7 +1155,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
1155 SetPageLRU(page); 1155 SetPageLRU(page);
1156 lru = page_lru(page); 1156 lru = page_lru(page);
1157 add_page_to_lru_list(zone, page, lru); 1157 add_page_to_lru_list(zone, page, lru);
1158 if (PageActive(page) && scan_global_lru(sc)) { 1158 if (PageActive(page)) {
1159 int file = !!page_is_file_cache(page); 1159 int file = !!page_is_file_cache(page);
1160 reclaim_stat->recent_rotated[file]++; 1160 reclaim_stat->recent_rotated[file]++;
1161 } 1161 }
@@ -1230,8 +1230,8 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
1230 */ 1230 */
1231 if (scan_global_lru(sc)) { 1231 if (scan_global_lru(sc)) {
1232 zone->pages_scanned += pgscanned; 1232 zone->pages_scanned += pgscanned;
1233 reclaim_stat->recent_scanned[!!file] += pgmoved;
1234 } 1233 }
1234 reclaim_stat->recent_scanned[!!file] += pgmoved;
1235 1235
1236 if (file) 1236 if (file)
1237 __mod_zone_page_state(zone, NR_ACTIVE_FILE, -pgmoved); 1237 __mod_zone_page_state(zone, NR_ACTIVE_FILE, -pgmoved);
@@ -1272,8 +1272,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
1272 * This helps balance scan pressure between file and anonymous 1272 * This helps balance scan pressure between file and anonymous
1273 * pages in get_scan_ratio. 1273 * pages in get_scan_ratio.
1274 */ 1274 */
1275 if (scan_global_lru(sc)) 1275 reclaim_stat->recent_rotated[!!file] += pgmoved;
1276 reclaim_stat->recent_rotated[!!file] += pgmoved;
1277 1276
1278 while (!list_empty(&l_inactive)) { 1277 while (!list_empty(&l_inactive)) {
1279 page = lru_to_page(&l_inactive); 1278 page = lru_to_page(&l_inactive);