内存页分配/释放

page alloc/free

create_empty_buffers
├─ alloc_page_buffers => alloc_buffer_head 
│ └─ kmem_cache_alloc
└─ attach_page_buffers
   ├─ get_page
   ├─ SetPagePrivate 
   └─ set_page_private

try_to_release_page
└─ try_to_free_buffers
   ├─ drop_buffers
   │ └─ __clear_page_buffers
   │    ├─ ClearPagePrivate
   │    ├─ set_page_private
   │    └─ put_page
   └─ free_buffer_head

kswapd  /* The background pageout daemon, started as a kernel thread from the init process. */
└─ balance_pgdat /* reclaim pages */
   └─ kswapd_shrink_node => shrink_node => shrink_node_memcg
      └─ shrink_inactive_list => shrink_page_list
         └─ try_to_release_page

kmem_cache_alloc
└─ ___slab_alloc => new_slab
   └─ __alloc_pages_nodemask
      ├─ get_page_from_freelist /* If fail, it will __alloc_pages_slowpath */
      └─ __alloc_pages_slowpath 
         └─__alloc_pages_direct_reclaim => __perform_reclaim
            └─ try_to_free_pages
               └─ shrink_node
struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
        int retry)
{
    struct buffer_head *bh, *head;
    long offset;

try_again:
    head = NULL;
    offset = PAGE_SIZE;
    while ((offset -= size) >= 0) {
        bh = alloc_buffer_head(GFP_NOFS);
        if (!bh)
            goto no_grow;

        bh->b_this_page = head; /* circular list of page's buffers */
        bh->b_blocknr = -1;
        head = bh;

        bh->b_size = size; /* for ntfs/fat, it is the sector size */

        /* Link the buffer to its page */
        set_bh_page(bh, page, offset);
    }
    return head;
/*
 * In case anything failed, we just free everything we got.
 */
no_grow:
......
}

void set_bh_page(struct buffer_head *bh,
        struct page *page, unsigned long offset)
{
    bh->b_page = page; /* the page this bh is mapped to */
    BUG_ON(offset >= PAGE_SIZE);
    if (PageHighMem(page))
        /*
         * This catches illegal uses and preserves the offset:
         */
        bh->b_data = (char *)(0 + offset);
    else
        bh->b_data = page_address(page) + offset; /* pointer to data within the page */
}
原文地址:https://www.cnblogs.com/sunnycindy/p/9099703.html