Slub Memory Allocator -10- (Slub 해제)

<kernel v5.0>

슬랩 페이지 해제

다음 그림은 해제할 slub page가 free_slab() 함수를 통해 버디 시스템으로 돌아가기까지의 흐름을 보여준다.

free_slab-1

 

free_slab()

mm/slub.c

1static void free_slab(struct kmem_cache *s, struct page *page)
2{
3        if (unlikely(s->flags & SLAB_TYPESAFE_BY_RCU)) {
4                call_rcu(&page->rcu_head, rcu_free_slab);
5        } else
6                __free_slab(s, page);
7}

슬랩 페이지를 해제하여 버디 시스템으로 돌려보낸다.

  • 코드 라인 3~4에서 적은 확률로 슬랩 해제에 lock-less rcu를 사용하여 버디 시스템에 회수시킨다.
  • 코드 라인 5~6에서 즉각 슬랩 페이지를 버디 시스템에 회수시킨다.

 

rcu_free_slab()

mm/slub.c

1static void rcu_free_slab(struct rcu_head *h)
2{
3        struct page *page = container_of(h, struct page, rcu_head);
4 
5        __free_slab(page->slab_cache, page);
6}

슬랩 페이지를 버디 시스템으로 회수시킨다. 이 함수는 rcu를 통해 호출된다.

 

__free_slab()

mm/slub.c

01static void __free_slab(struct kmem_cache *s, struct page *page)
02{
03        int order = compound_order(page);
04        int pages = 1 << order;
05 
06        if (s->flags & SLAB_CONSISTENCY_CHECKS) {
07                void *p;
08 
09                slab_pad_check(s, page);
10                for_each_object(p, s, page_address(page),
11                                                page->objects)
12                        check_object(s, page, p, SLUB_RED_INACTIVE);
13        }
14 
15        mod_lruvec_page_state(page,
16                (s->flags & SLAB_RECLAIM_ACCOUNT) ?
17                NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
18                -pages);
19 
20        __ClearPageSlabPfmemalloc(page);
21        __ClearPageSlab(page);
22 
23        page->mapping = NULL;
24        if (current->reclaim_state)
25                current->reclaim_state->reclaimed_slab += pages;
26        memcg_uncharge_slab(page, order, s);
27        __free_pages(page, order);
28}

슬랩 페이지를 해제하여 버디 시스템으로 회수시킨다.

  • 코드 라인 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

1static __always_inline void memcg_uncharge_slab(struct page *page, int order,
2                                                struct kmem_cache *s)
3{
4        if (!memcg_kmem_enabled())
5                return;
6        memcg_kmem_uncharge(page, order);
7}

CONFIG_MEMCG_KMEM 커널 옵션을 사용하면서 memcg_kmem이 활성화된 경우 memory cgroup으로 슬랩 페이지가 회수되었다는 것을 알려 counting에서 감소시키게 한다. 단 루트 캐시인 경우 처리하지 않고 루틴을 빠져나간다.

 

참고

 

댓글 남기기