2017-02-07

1. 问题引入

linux-3.10.86/mm/vmscan.c

static inline int is_page_cache_freeable(struct page *page)
{

    /*
     * A freeable page cache page is referenced only by the caller
     * that isolated the page, the page cache radix tree and
     * optional buffer heads at page->private.
     */
    return page_count(page) - page_has_private(page) == 2;

}

为何是== 2?

2. 解

调用路径:

shrink_inactive_list
|--lru_add_drain
|--isolate_lru_pages
|   |--get_page_unless_zero  //引用计数
|--shrink_page_list   (shrink_page_list不会被shrink_active_list调用.)
|   |--pageout
|   |   |--is_page_cache_freeable

2.1 isolated the page

2.2 buddy system

注释中提到"the page cache radix tree"的引用计数, 这个注释并不准确, 应该是从buddy system分配产生的引用计数.

buddy system的get:

page_cache_alloc_cold -> __alloc_pages_nodemask
|   |--get_page_from_freelist
|   |   |--buffered_rmqueue 
|   |   |   |--prep_new_page
|   |   |   |   |--set_page_refcounted -> set_page_count(page, 1);

并不是radix tree的get的理由如下:
以dogenericfile_read 为例, 看下page cache的get:

do_generic_file_read
|--no_cached_page: page_cache_alloc_cold -> __alloc_pages_nodemask
|   |--get_page_from_freelist
|   |   |--buffered_rmqueue 
|   |   |   |--prep_new_page
|   |   |   |   |--set_page_refcounted -> set_page_count(page, 1);
|--add_to_page_cache_lru
|   |--add_to_page_cache -> add_to_page_cache_locked
|   |   |   |--page_cache_get //引用计数A
|   |   |   |--radix_tree_insert
|   |--lru_cache_add_file -> __lru_cache_add
|--readpage: mapping->a_ops->readpage(filp, page)
|--ret = actor(desc, page, offset, nr);//比如file_read_actor()
|--page_cache_release(page); //引用计数B

使用完后, 修改引用计数, 故这里对引用计数没有影响.

lru的计数呢?
答:加入pagevec中会get page, 清空pagevec放入lru时, 会put page.

2.3 buffer_head

若pagehasprivate()返回1, 则page_count为3

buffer_head时的get page:

grow_dev_page
|--find_or_create_page
|--alloc_page_buffers
|--link_dev_buffers(page, bh) -> attach_page_buffers
|   |--page_cache_get
|   |--set_page_private
|--page_cache_release(page);  //和find_or_create_page中的get 对应

本文地址: https://awakening-fong.github.io/posts/mm/reclaim_05_page_count

转载请注明出处: https://awakening-fong.github.io


若无法评论, 请打开JavaScript, 并通过proxy.


blog comments powered by Disqus