linux-kernel-test/include/linux/mm_inline.h
Rik van Riel 556adecba1 vmscan: second chance replacement for anonymous pages
We avoid evicting and scanning anonymous pages for the most part, but
under some workloads we can end up with most of memory filled with
anonymous pages.  At that point, we suddenly need to clear the referenced
bits on all of memory, which can take ages on very large memory systems.

We can reduce the maximum number of pages that need to be scanned by not
taking the referenced state into account when deactivating an anonymous
page.  After all, every anonymous page starts out referenced, so why
check?

If an anonymous page gets referenced again before it reaches the end of
the inactive list, we move it back to the active list.

To keep the maximum amount of necessary work reasonable, we scale the
active to inactive ratio with the size of memory, using the formula
active:inactive ratio = sqrt(memory in GB * 10).

Kswapd CPU use now seems to scale by the amount of pageout bandwidth,
instead of by the amount of memory present in the system.

[kamezawa.hiroyu@jp.fujitsu.com: fix OOM with memcg]
[kamezawa.hiroyu@jp.fujitsu.com: memcg: lru scan fix]
Signed-off-by: Rik van Riel <riel@redhat.com>
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-10-20 08:50:25 -07:00

140 lines
3.4 KiB
C

#ifndef LINUX_MM_INLINE_H
#define LINUX_MM_INLINE_H
/**
* page_is_file_cache - should the page be on a file LRU or anon LRU?
* @page: the page to test
*
* Returns LRU_FILE if @page is page cache page backed by a regular filesystem,
* or 0 if @page is anonymous, tmpfs or otherwise ram or swap backed.
* Used by functions that manipulate the LRU lists, to sort a page
* onto the right LRU list.
*
* We would like to get this info without a page flag, but the state
* needs to survive until the page is last deleted from the LRU, which
* could be as far down as __page_cache_release.
*/
static inline int page_is_file_cache(struct page *page)
{
if (PageSwapBacked(page))
return 0;
/* The page is page cache backed by a normal filesystem. */
return LRU_FILE;
}
static inline void
add_page_to_lru_list(struct zone *zone, struct page *page, enum lru_list l)
{
list_add(&page->lru, &zone->lru[l].list);
__inc_zone_state(zone, NR_LRU_BASE + l);
}
static inline void
del_page_from_lru_list(struct zone *zone, struct page *page, enum lru_list l)
{
list_del(&page->lru);
__dec_zone_state(zone, NR_LRU_BASE + l);
}
static inline void
add_page_to_inactive_anon_list(struct zone *zone, struct page *page)
{
add_page_to_lru_list(zone, page, LRU_INACTIVE_ANON);
}
static inline void
add_page_to_active_anon_list(struct zone *zone, struct page *page)
{
add_page_to_lru_list(zone, page, LRU_ACTIVE_ANON);
}
static inline void
add_page_to_inactive_file_list(struct zone *zone, struct page *page)
{
add_page_to_lru_list(zone, page, LRU_INACTIVE_FILE);
}
static inline void
add_page_to_active_file_list(struct zone *zone, struct page *page)
{
add_page_to_lru_list(zone, page, LRU_ACTIVE_FILE);
}
static inline void
del_page_from_inactive_anon_list(struct zone *zone, struct page *page)
{
del_page_from_lru_list(zone, page, LRU_INACTIVE_ANON);
}
static inline void
del_page_from_active_anon_list(struct zone *zone, struct page *page)
{
del_page_from_lru_list(zone, page, LRU_ACTIVE_ANON);
}
static inline void
del_page_from_inactive_file_list(struct zone *zone, struct page *page)
{
del_page_from_lru_list(zone, page, LRU_INACTIVE_FILE);
}
static inline void
del_page_from_active_file_list(struct zone *zone, struct page *page)
{
del_page_from_lru_list(zone, page, LRU_INACTIVE_FILE);
}
static inline void
del_page_from_lru(struct zone *zone, struct page *page)
{
enum lru_list l = LRU_BASE;
list_del(&page->lru);
if (PageActive(page)) {
__ClearPageActive(page);
l += LRU_ACTIVE;
}
l += page_is_file_cache(page);
__dec_zone_state(zone, NR_LRU_BASE + l);
}
/**
* page_lru - which LRU list should a page be on?
* @page: the page to test
*
* Returns the LRU list a page should be on, as an index
* into the array of LRU lists.
*/
static inline enum lru_list page_lru(struct page *page)
{
enum lru_list lru = LRU_BASE;
if (PageActive(page))
lru += LRU_ACTIVE;
lru += page_is_file_cache(page);
return lru;
}
/**
* inactive_anon_is_low - check if anonymous pages need to be deactivated
* @zone: zone to check
*
* Returns true if the zone does not have enough inactive anon pages,
* meaning some active anon pages need to be deactivated.
*/
static inline int inactive_anon_is_low(struct zone *zone)
{
unsigned long active, inactive;
active = zone_page_state(zone, NR_ACTIVE_ANON);
inactive = zone_page_state(zone, NR_INACTIVE_ANON);
if (inactive * zone->inactive_ratio < active)
return 1;
return 0;
}
#endif