<kernel v5.0>
슬랩 페이지 해제
다음 그림은 해제할 slub page가 free_slab() 함수를 통해 버디 시스템으로 돌아가기까지의 흐름을 보여준다.
free_slab()
mm/slub.c
static void free_slab(struct kmem_cache *s, struct page *page) { if (unlikely(s->flags & SLAB_TYPESAFE_BY_RCU)) { call_rcu(&page->rcu_head, rcu_free_slab); } else __free_slab(s, page); }
슬랩 페이지를 해제하여 버디 시스템으로 돌려보낸다.
- 코드 라인 3~4에서 적은 확률로 슬랩 해제에 lock-less rcu를 사용하여 버디 시스템에 회수시킨다.
- 코드 라인 5~6에서 즉각 슬랩 페이지를 버디 시스템에 회수시킨다.
rcu_free_slab()
mm/slub.c
static void rcu_free_slab(struct rcu_head *h) { struct page *page = container_of(h, struct page, rcu_head); __free_slab(page->slab_cache, page); }
슬랩 페이지를 버디 시스템으로 회수시킨다. 이 함수는 rcu를 통해 호출된다.
__free_slab()
mm/slub.c
static void __free_slab(struct kmem_cache *s, struct page *page) { int order = compound_order(page); int pages = 1 << order; if (s->flags & SLAB_CONSISTENCY_CHECKS) { void *p; slab_pad_check(s, page); for_each_object(p, s, page_address(page), page->objects) check_object(s, page, p, SLUB_RED_INACTIVE); } mod_lruvec_page_state(page, (s->flags & SLAB_RECLAIM_ACCOUNT) ? NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, -pages); __ClearPageSlabPfmemalloc(page); __ClearPageSlab(page); page->mapping = NULL; if (current->reclaim_state) current->reclaim_state->reclaimed_slab += pages; memcg_uncharge_slab(page, order, s); __free_pages(page, order); }
슬랩 페이지를 해제하여 버디 시스템으로 회수시킨다.
- 코드 라인 3~4에서 슬랩 페이지는 compound 페이지로 구성 가능하다. 따라서 해당하는 order 값과 페이지 수를 알아온다.
- 코드 라인 6~13에서 SLAB_CONSISTENCY_CHECKS 플래그를 사용한 경우 슬랩 페이지에 대한 consistency 체크를 다음과 같이 수행한다.
- 슬랩 페이지에 대한 패딩을 확인한다.
- 각 슬랩 object의 red-zone을 확인하여 SLUB_RED_INACTIVE(0xbb)인지 확인한다.
- 코드 라인 15~18에서 reclaimable 슬랩 캐시인 경우 NR_SLAB_RECLAIMABLE 카운터를, 아닌 경우 NR_SLAB_UNRECLAIMABLE 카운터를 페이지 수만큼 감소시킨다.
- 코드 라인 20~23에서 PG_active 및 PG_slab 를 클리어하고 페이지 매핑 연결도 해제한다.
- 코드 라인 24~25에서 현재 태스크의 회수 상태가 설정된 경우 reclaimed_slab을 페이지 수 만큼 더한다.
- 코드 라인 26에서 memory cgroup으로 slab 페이지가 회수되었다는 것을 알려 counting에서 감소시키게 한다.
- 코드 라인 27에서 버디 시스템으로 페이지를 order 수 만큼 회수시킨다.
memcg_uncharge_slab()
mm/slab.h
static __always_inline void memcg_uncharge_slab(struct page *page, int order, struct kmem_cache *s) { if (!memcg_kmem_enabled()) return; memcg_kmem_uncharge(page, order); }
CONFIG_MEMCG_KMEM 커널 옵션을 사용하면서 memcg_kmem이 활성화된 경우 memory cgroup으로 슬랩 페이지가 회수되었다는 것을 알려 counting에서 감소시키게 한다. 단 루트 캐시인 경우 처리하지 않고 루틴을 빠져나간다.
참고
- Slab Memory Allocator -1- (구조) | 문c
- Slab Memory Allocator -2- (캐시 초기화) | 문c
- Slub Memory Allocator -3- (캐시 생성) | 문c
- Slub Memory Allocator -4- (Order 계산) | 문c
- Slub Memory Allocator -5- (Slub 할당) | 문c
- Slub Memory Allocator -6- (Object 할당) | 문c
- Slub Memory Allocator -7- (Object 해제) | 문c
- Slub Memory Allocator -8- (Drain/Flash 캐시) | 문c
- Slub Memory Allocator -9- (캐시 Shrink) | 문c
- Slub Memory Allocator -10- (Slub 해제) | 문c – 현재 글
- Slub Memory Allocator -11- (캐시 삭제) | 문c
- Slub Memory Allocator -12- (Slub 디버깅) | 문c
- Slub Memory Allocator -13- (slabinfo) | 문c