요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
==============
Page fragments
==============
A page fragment is an arbitrary-length arbitrary-offset area of memory
which resides within a 0 or higher order compound page. Multiple
fragments within that page are individually refcounted, in the page's
reference counter.
The page_frag functions, page_frag_alloc and page_frag_free, provide a
simple allocation framework for page fragments. This is used by the
network stack and network device drivers to provide a backing region of
memory for use as either an sk_buff->head, or to be used in the "frags"
portion of skb_shared_info.
In order to make use of the page fragment APIs a backing page fragment
cache is needed. This provides a central point for the fragment allocation
and tracks allows multiple calls to make use of a cached page. The
advantage to doing this is that multiple calls to get_page can be avoided
which can be expensive at allocation time. However due to the nature of
this caching it is required that any calls to the cache be protected by
either a per-cpu limitation, or a per-cpu limitation and forcing interrupts
to be disabled when executing the fragment allocation.
The network stack uses two separate caches per CPU to handle fragment
allocation. The netdev_alloc_cache is used by callers making use of the
netdev_alloc_frag and __netdev_alloc_skb calls. The napi_alloc_cache is
used by callers of the __napi_alloc_frag and napi_alloc_skb calls. The
main difference between these two calls is the context in which they may be
called. The "netdev" prefixed functions are usable in any context as these
functions will disable interrupts, while the "napi" prefixed functions are
only usable within the softirq context.
Many network device drivers use a similar methodology for allocating page
fragments, but the page fragments are cached at the ring or descriptor
level. In order to enable these cases it is necessary to provide a generic
way of tearing down a page cache. For this reason __page_frag_cache_drain
was implemented. It allows for freeing multiple references from a single
page via a single call. The advantage to doing this is that it allows for
cleaning up the multiple references that were added to a page in order to
avoid calling get_page per allocation.
Alexander Duyck, Nov 29, 2016.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Page fragment와 allocation API
1-14Page fragment는 order 0 이상의 compound page 안에 위치하는, 길이와 offset이 임의인 memory 영역입니다. 한 page 안의 여러 fragment는 page reference counter를 이용해 각각 reference count를 관리합니다.
`page_frag_alloc`과 `page_frag_free` page-fragment 함수는 fragment를 위한 단순한 allocation framework를 제공합니다. Network stack과 network-device driver는 이 framework로 `sk_buff->head` 또는 `skb_shared_info`의 `frags` 부분에 사용할 backing memory 영역을 마련합니다.
==============
Page fragments
==============
A page fragment is an arbitrary-length arbitrary-offset area of memory
which resides within a 0 or higher order compound page. Multiple
fragments within that page are individually refcounted, in the page's
reference counter.
The page_frag functions, page_frag_alloc and page_frag_free, provide a
simple allocation framework for page fragments. This is used by the
network stack and network device drivers to provide a backing region of
memory for use as either an sk_buff->head, or to be used in the "frags"
portion of skb_shared_info.
Backing cache와 동시 실행 보호
15-23Page-fragment API를 사용하려면 backing page-fragment cache가 필요합니다. Cache는 fragment allocation의 중앙 지점이 되어 여러 호출이 cached page를 재사용할 수 있도록 추적합니다. Allocation마다 비용이 큰 `get_page`를 여러 번 호출하지 않아도 된다는 장점이 있습니다.
이 caching 방식의 특성 때문에 cache 호출은 CPU별 사용으로 제한해 보호해야 합니다. 실행 context에 따라 CPU별 제한과 함께 fragment allocation을 수행하는 동안 interrupt도 disable해야 합니다.
In order to make use of the page fragment APIs a backing page fragment
cache is needed. This provides a central point for the fragment allocation
and tracks allows multiple calls to make use of a cached page. The
advantage to doing this is that multiple calls to get_page can be avoided
which can be expensive at allocation time. However due to the nature of
this caching it is required that any calls to the cache be protected by
either a per-cpu limitation, or a per-cpu limitation and forcing interrupts
to be disabled when executing the fragment allocation.
Network stack의 CPU별 cache
24-32Network stack은 CPU마다 fragment allocation용 cache 두 개를 사용합니다. `netdev_alloc_cache`는 `netdev_alloc_frag`와 `__netdev_alloc_skb` 호출자가 사용하고, `napi_alloc_cache`는 `__napi_alloc_frag`와 `napi_alloc_skb` 호출자가 사용합니다.
두 계열의 주된 차이는 호출할 수 있는 context입니다. `netdev` 접두 함수는 자체적으로 interrupt를 disable하므로 어떤 context에서도 사용할 수 있습니다. `napi` 접두 함수는 softirq context 안에서만 사용할 수 있습니다.
The network stack uses two separate caches per CPU to handle fragment
allocation. The netdev_alloc_cache is used by callers making use of the
netdev_alloc_frag and __netdev_alloc_skb calls. The napi_alloc_cache is
used by callers of the __napi_alloc_frag and napi_alloc_skb calls. The
main difference between these two calls is the context in which they may be
called. The "netdev" prefixed functions are usable in any context as these
functions will disable interrupts, while the "napi" prefixed functions are
only usable within the softirq context.
Ring·descriptor cache의 해제
33-43많은 network-device driver도 비슷한 방식으로 page fragment를 할당하지만, fragment를 ring 또는 descriptor 수준에서 cache합니다. 이런 사용 사례에는 page cache를 정리하는 범용 방법이 필요합니다.
이를 위해 `__page_frag_cache_drain`이 구현되었습니다. 한 번 호출해 단일 page의 reference 여러 개를 해제할 수 있습니다. Allocation마다 `get_page`를 호출하지 않으려고 page에 추가해 둔 여러 reference를 효율적으로 정리할 수 있다는 장점이 있습니다.
Alexander Duyck가 2016년 11월 29일 작성했습니다.
Many network device drivers use a similar methodology for allocating page
fragments, but the page fragments are cached at the ring or descriptor
level. In order to enable these cases it is necessary to provide a generic
way of tearing down a page cache. For this reason __page_frag_cache_drain
was implemented. It allows for freeing multiple references from a single
page via a single call. The advantage to doing this is that it allows for
cleaning up the multiple references that were added to a page in order to
avoid calling get_page per allocation.
Alexander Duyck, Nov 29, 2016.
요약·해설
page_frags.rst:1-43Page fragment는 compound page 일부를 network buffer backing으로 나눠 쓰는 단위입니다. CPU별 cache로 page를 재사용해 allocation마다 `get_page`를 부르는 비용을 줄이되, 호출 context에 맞춰 interrupt와 CPU-local 접근을 제어해야 합니다.
Compound page를 cache하고 여러 fragment를 할당한 뒤 reference를 한꺼번에 정리합니다.
호출 context와 interrupt 처리 방식이 두 cache 계열을 구분합니다.