Slub Memory Allocator -10- (Slub 해제)

<kernel v5.0>

슬랩 페이지 해제

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

free_slab-1

 

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에서 감소시키게 한다. 단 루트 캐시인 경우 처리하지 않고 루틴을 빠져나간다.

 

참고

 

댓글 남기기