页面缓存的实现基于基数树,缓存属于内核中性能要求最苛刻的部分之一,而且广泛用于内核的所有子系统,实现也比较简单。举两个例子,其他的暂时不做分析了。
分配页面用于加入地址空间
-
- static inline struct page *page_cache_alloc(struct address_space *x)
- {
- return __page_cache_alloc(mapping_gfp_mask(x));
- }
|
分配完了添加到基数树中
-
-
-
-
- static inline int add_to_page_cache(struct page *page,
- struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
- {
- int error;
-
- __set_page_locked(page);
-
- error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
- if (unlikely(error))
- __clear_page_locked(page);
- return error;
- }
|
-
-
-
-
-
-
-
-
-
-
- int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
- pgoff_t offset, gfp_t gfp_mask)
- {
- int error;
-
- VM_BUG_ON(!PageLocked(page));
-
- error = mem_cgroup_cache_charge(page, current->mm,
- gfp_mask & GFP_RECLAIM_MASK);
- if (error)
- goto out;
-
- error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
- if (error == 0) {
- page_cache_get(page);
- page->mapping = mapping;
- page->index = offset;
-
- spin_lock_irq(&mapping->tree_lock);
-
- error = radix_tree_insert(&mapping->page_tree, offset, page);
- if (likely(!error)) {
- mapping->nrpages++;
- __inc_zone_page_state(page, NR_FILE_PAGES);
- if (PageSwapBacked(page))
- __inc_zone_page_state(page, NR_SHMEM);
- spin_unlock_irq(&mapping->tree_lock);
- } else {
- page->mapping = NULL;
- spin_unlock_irq(&mapping->tree_lock);
- mem_cgroup_uncharge_cache_page(page);
- page_cache_release(page);
- }
- radix_tree_preload_end();
- } else
- mem_cgroup_uncharge_cache_page(page);
- out:
- return error;
- }
|