GFP 플래그

밑줄 3개 ___GFP 플래그

직접 사용 금지 (밑줄 3개)

  • include/linux/gfp.h 내부에서만 사용되고 다른 소스에서는 직접 사용되지 않는다.
  • 커널 v4.4까지 새롭게 추가된 항목
    • ___GFP_ATOMIC
    • ___GFP_ACCOUNT
  • 커널 v4.4까지 삭제된 항목
    • ___GFP_WAIT
/* Plain integer GFP bitmasks. Do not use this directly. */
#define ___GFP_DMA              0x01u
#define ___GFP_HIGHMEM          0x02u
#define ___GFP_DMA32            0x04u
#define ___GFP_MOVABLE          0x08u
#define ___GFP_WAIT             0x10u
#define ___GFP_HIGH             0x20u
#define ___GFP_IO               0x40u
#define ___GFP_FS               0x80u
#define ___GFP_COLD             0x100u
#define ___GFP_NOWARN           0x200u
#define ___GFP_REPEAT           0x400u
#define ___GFP_NOFAIL           0x800u
#define ___GFP_NORETRY          0x1000u
#define ___GFP_MEMALLOC         0x2000u
#define ___GFP_COMP             0x4000u
#define ___GFP_ZERO             0x8000u
#define ___GFP_NOMEMALLOC       0x10000u
#define ___GFP_HARDWALL         0x20000u
#define ___GFP_THISNODE         0x40000u
#define ___GFP_RECLAIMABLE      0x80000u
#define ___GFP_NOACCOUNT        0x100000u
#define ___GFP_NOTRACK          0x200000u
#define ___GFP_NO_KSWAPD        0x400000u
#define ___GFP_OTHER_NODE       0x800000u
#define ___GFP_WRITE            0x1000000u
  • ___GFP_DMA
    • ZONE_DMA 영역에 할당 요청한다.
    • ZONE_HIGHMEM 영역에 할당 요청한다.
  • ___GFP_DMA32
    • ZONE_DMA32 영역에 할당 요청한다.
    • 두 가지 용도로 사용
      • ZONE_MOVABLE이 가용할 때 이 영역에 할당 요청한다.
      • 페이지 이주가 가능하도록 할당 요청한다.
    • 회수 가능한 페이지로 할당 요청한다.
  • ___GFP_WAIT
    • 메모리 할당을 하는 동안 sleep을 허용하도록 요청한다.
  • ___GFP_HIGH
    • 높은 우선 순위에서 처리되도록 요청한다.
  • ___GFP_IO
    • 메모리 할당을 하는 동안 어떠한 I/O 처리도 가능하도록 요청한다.
  • ___GFP_FS
    • 메모리 할당을 하는 동안 File System calls 가능하도록 요청한다.
  • ___GFP_COLD
    • 메모리 파편화에 영향을 덜 주도록 warm(hot) 페이지 대신 cold 페이지에서 관리하도록 요청한다
    • 메모리 할당이 실패할 때 어떠한 경고도 처리하지 않도록 요청한다.
    • 메모리 할당이 처음 실패하는 경우 한 번 더 시도하도록 요청한다.
    • 실패를 허용하지 않고, 메모리 할당 요청에 대해 성공할 때까지 처리하도록 요청한다.
    • 메모리 할당 요청에 대해 실패 시 재시도 하지 않도록 요청한다.
    • 메모리 할당에 비상 영역을 사용할 수 있도록 요청한다.
  • ___GFP_COMP
    • 메타 데이터 또는 연속된 복합 페이지를 구성하도록 요청한다.
  • ___GFP_ZERO
    • 할당된 영역을 0으로 초기화 하도록 요청한다.
    • 메모리 할당에 비상 영역을 사용하지 않도록 요청한다.
    • 현재 태스크에 지정된 cpuset 메모리 할당 정책을 사용하게 요청한다.
    • 지정된 노드에서만 할당을 허용한다.
    • kmemcg(메모리 Control Group)의 사용량 통제를 받지 않도록 요청한다.
    • kmemcheck를 사용한 디버그 트래킹을 허용하지 않도록 요청한다.
    • 할당된 페이지가 Swap 파일로 이동할 수 없게 요청한다.
    • 리모트 노드에서 할당을 하도록 요청한다.
  • ___GFP_WRITE
    • dirty(쓰기용 파일 캐시)  페이지 할당을 요청한다.


밑줄 2개 __GFP 플래그

ZONE 관련 (밑줄 2개)

  • 하위 4개의 비트를 사용한다.
 * Physical address zone modifiers (see linux/mmzone.h - low four bits)
 * Do not put any conditional on these. If necessary modify the definitions
 * without the underscores and use them consistently. The definitions here may
 * be used in bit comparisons.
#define __GFP_DMA       ((__force gfp_t)___GFP_DMA)
#define __GFP_HIGHMEM   ((__force gfp_t)___GFP_HIGHMEM)
#define __GFP_DMA32     ((__force gfp_t)___GFP_DMA32)
#define __GFP_MOVABLE   ((__force gfp_t)___GFP_MOVABLE)  /* Page is movable */
  • __GFP_DMA
    • ZONE_DMA 영역에 할당 요청
    • ZONE_HIGHMEM 영역에 할당 요청
  • __GFP_DMA32
    • ZONE_DMA32 영역에 할당 요청
    • ZONE_MOVABLE이 허락되는 경우 이 영역에 할당 요청
    • 위의 4개 zone을 포함
    • GFP 플래그를 사용하지 하지 않을 때 일반적으로 ZONE_NORMAL을 의미한다.


Page Mobility 와 장소 hint 관련 (밑줄 2개)

 * Page mobility and placement hints
 * These flags provide hints about how mobile the page is. Pages with similar
 * mobility are placed within the same pageblocks to minimise problems due
 * to external fragmentation.
 * __GFP_MOVABLE (also a zone modifier) indicates that the page can be
 *   moved by page migration during memory compaction or can be reclaimed.
 * __GFP_RECLAIMABLE is used for slab allocations that specify
 *   SLAB_RECLAIM_ACCOUNT and whose pages can be freed via shrinkers.
 * __GFP_WRITE indicates the caller intends to dirty the page. Where possible,
 *   these pages will be spread between local zones to avoid all the dirty
 *   pages being in one zone (fair zone allocation policy).
 * __GFP_HARDWALL enforces the cpuset memory allocation policy.
 * __GFP_THISNODE forces the allocation to be satisified from the requested
 *   node with no fallbacks or placement policy enforcements.
 * __GFP_ACCOUNT causes the allocation to be accounted to kmemcg (only relevant
 *   to kmem allocations).
#define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE)
#define __GFP_WRITE     ((__force gfp_t)___GFP_WRITE)
#define __GFP_HARDWALL   ((__force gfp_t)___GFP_HARDWALL)
#define __GFP_THISNODE  ((__force gfp_t)___GFP_THISNODE)
#define __GFP_ACCOUNT   ((__force gfp_t)___GFP_ACCOUNT)
    • 회수 가능한 페이지로 할당한다.
    • dirty(쓰기용 파일 캐시)  페이지 할당을 요청한다.
    • 현재 태스크에 지정된 cpuset 메모리 할당 정책을 사용하게 요청한다.
    • 지정된 노드에서만 할당을 허용한다.
    • kmemcg(메모리 Control Group)의 사용량 통제를 받지 않도록 요청한다.


워터마크 관련 (밑줄 2개)

 * Watermark modifiers -- controls access to emergency reserves
 * __GFP_HIGH indicates that the caller is high-priority and that granting
 *   the request is necessary before the system can make forward progress.
 *   For example, creating an IO context to clean pages.
 * __GFP_ATOMIC indicates that the caller cannot reclaim or sleep and is
 *   high priority. Users are typically interrupt handlers. This may be
 *   used in conjunction with __GFP_HIGH
 * __GFP_MEMALLOC allows access to all memory. This should only be used when
 *   the caller guarantees the allocation will allow more memory to be freed
 *   very shortly e.g. process exiting or swapping. Users either should
 *   be the MM or co-ordinating closely with the VM (e.g. swap over NFS).
 * __GFP_NOMEMALLOC is used to explicitly forbid access to emergency reserves.
 *   This takes precedence over the __GFP_MEMALLOC flag if both are set.
#define __GFP_ATOMIC    ((__force gfp_t)___GFP_ATOMIC)
#define __GFP_HIGH      ((__force gfp_t)___GFP_HIGH)
#define __GFP_MEMALLOC  ((__force gfp_t)___GFP_MEMALLOC)
#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC)
    • 페이지 회수나 슬립이 허용되지 않고 높은 우선 순위로 처리되도록 요청한다.
    • 인터럽트 핸들러들에서 보통 사용되며 __GFP_HIGH와 붙여서 사용될 수도 있다.
  • __GFP_HIGH
    • 높은 우선 순위로 처리되도록 요청한다. \
    • 모든 메모리로의 접근을 허가하도록 요청한다.
    • 프로세스 종료나 스와핑의 사용 예와 같이 매우 짧은 시간내 메모리 할당이 요구될 때 필요하다.
    • 비상용 reserves 영역을 이용하지 못하게 엄격히 금지하도록 요청한다.


페이지 회수관련 (밑줄 2개)

 * Reclaim modifiers
 * __GFP_IO can start physical IO.
 * __GFP_FS can call down to the low-level FS. Clearing the flag avoids the
 *   allocator recursing into the filesystem which might already be holding
 *   locks.
 * __GFP_DIRECT_RECLAIM indicates that the caller may enter direct reclaim.
 *   This flag can be cleared to avoid unnecessary delays when a fallback
 *   option is available.
 * __GFP_KSWAPD_RECLAIM indicates that the caller wants to wake kswapd when
 *   the low watermark is reached and have it reclaim pages until the high
 *   watermark is reached. A caller may wish to clear this flag when fallback
 *   options are available and the reclaim is likely to disrupt the system. The
 *   canonical example is THP allocation where a fallback is cheap but
 *   reclaim/compaction may cause indirect stalls.
 * __GFP_RECLAIM is shorthand to allow/forbid both direct and kswapd reclaim.
 * __GFP_REPEAT: Try hard to allocate the memory, but the allocation attempt
 *   _might_ fail.  This depends upon the particular VM implementation.
 * __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
 *   cannot handle allocation failures. New users should be evaluated carefully
 *   (and the flag should be used only when there is no reasonable failure
 *   policy) but it is definitely preferable to use the flag rather than
 *   opencode endless loop around allocator.
 * __GFP_NORETRY: The VM implementation must not retry indefinitely and will
 *   return NULL when direct reclaim and memory compaction have failed to allow
 *   the allocation to succeed.  The OOM killer is not called with the current
 *   implementation.
#define __GFP_IO        ((__force gfp_t)___GFP_IO)
#define __GFP_FS        ((__force gfp_t)___GFP_FS)
#define __GFP_DIRECT_RECLAIM    ((__force gfp_t)___GFP_DIRECT_RECLAIM) /* Caller can reclaim */
#define __GFP_KSWAPD_RECLAIM    ((__force gfp_t)___GFP_KSWAPD_RECLAIM) /* kswapd can wake */
#define __GFP_RECLAIM ((__force gfp_t)(___GFP_DIRECT_RECLAIM|___GFP_KSWAPD_RECLAIM))
#define __GFP_REPEAT    ((__force gfp_t)___GFP_REPEAT)
#define __GFP_NOFAIL    ((__force gfp_t)___GFP_NOFAIL)
#define __GFP_NORETRY   ((__force gfp_t)___GFP_NORETRY)
  • __GFP_IO
    • 메모리 할당을 하는 동안 어떠한 I/O 처리도 가능하도록 요청한다.
  • __GFP_FS
    • 메모리 할당을 하는 동안 File System calls 가능하도록 요청한다.
    • 페이지 할당 요청 시 free 페이지가 부족한 경우 direct reclaim(호출자가 직접 회수)을 들어갈 수 있도록 요청한다.
    • 메모리 할당 관련하여 준비된 fallback이 있는 경우 fallback 루틴에서는 불필요한 지연을 없애기 위해 명확히 이 플래그를 제거하여 요청한다.
    • low 워터마크에 접근하는 경우 kswapd를 깨워서 high 워터마크에 오를때까지 페이지를 회수하도록 요청한다.
    • 위 2가지 플래그 즉, direct reclaim과 kswapd를 사용한 회수를 동시에 요청한다.
    • 메모리 할당이 처음 실패하는 경우 한 번 더 시도하도록 요청한다.
    • 실패를 허용하지 않고, 메모리 할당 요청에 대해 성공할 때까지 처리하도록 요청한다.
    • 메모리 할당 요청에 대해 실패 시 재시도 하지 않도록 요청한다.


Action 관련 (밑줄 2개)

 * Action modifiers
 * __GFP_COLD indicates that the caller does not expect to be used in the near
 *   future. Where possible, a cache-cold page will be returned.
 * __GFP_NOWARN suppresses allocation failure reports.
 * __GFP_COMP address compound page metadata.
 * __GFP_ZERO returns a zeroed page on success.
 * __GFP_NOTRACK avoids tracking with kmemcheck.
 * __GFP_NOTRACK_FALSE_POSITIVE is an alias of __GFP_NOTRACK. It's a means of
 *   distinguishing in the source between false positives and allocations that
 *   cannot be supported (e.g. page tables).
 * __GFP_OTHER_NODE is for allocations that are on a remote node but that
 *   should not be accounted for as a remote allocation in vmstat. A
 *   typical user would be khugepaged collapsing a huge page on a remote
 *   node.
#define __GFP_COLD      ((__force gfp_t)___GFP_COLD)
#define __GFP_NOWARN    ((__force gfp_t)___GFP_NOWARN)
#define __GFP_COMP      ((__force gfp_t)___GFP_COMP)
#define __GFP_ZERO      ((__force gfp_t)___GFP_ZERO)
#define __GFP_NOTRACK   ((__force gfp_t)___GFP_NOTRACK)
#define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE)
  • __GFP_COLD
    • 메모리 파편화에 영향을 덜 주도록 warm(hot) 페이지 대신 cold 페이지에서 관리하도록 요청한다
    • 메모리 할당이 실패할 때 어떠한 경고도 처리하지 않도록 요청한다.
  • __GFP_COMP
    • 메타 데이터 또는 연속된 복합 페이지를 구성하도록 요청한다.
  • __GFP_ZERO
    • 할당된 영역을 0으로 초기화 하도록 요청한다.
    • kmemcheck를 사용한 디버그 트래킹을 허용하지 않도록 요청한다.
    • kmemcheck를 사용한 false positive(가짜 긍정) 디버그 트래킹을 허용하지 않도록 요청한다.
    • 리모트 노드에서 할당을 하도록 요청한다.


밑줄 없는 GFP 플래그

 * Useful GFP flag combinations that are commonly used. It is recommended
 * that subsystems start with one of these combinations and then set/clear
 * __GFP_FOO flags as necessary.
 * GFP_ATOMIC users can not sleep and need the allocation to succeed. A lower
 *   watermark is applied to allow access to "atomic reserves"
 * GFP_KERNEL is typical for kernel-internal allocations. The caller requires
 *   ZONE_NORMAL or a lower zone for direct access but can direct reclaim.
 * GFP_KERNEL_ACCOUNT is the same as GFP_KERNEL, except the allocation is
 *   accounted to kmemcg.
 * GFP_NOWAIT is for kernel allocations that should not stall for direct
 *   reclaim, start physical IO or use any filesystem callback.
 * GFP_NOIO will use direct reclaim to discard clean pages or slab pages
 *   that do not require the starting of any physical IO.
 * GFP_NOFS will use direct reclaim but will not use any filesystem interfaces.
 * GFP_USER is for userspace allocations that also need to be directly
 *   accessibly by the kernel or hardware. It is typically used by hardware
 *   for buffers that are mapped to userspace (e.g. graphics) that hardware
 *   still must DMA to. cpuset limits are enforced for these allocations.
 * GFP_DMA exists for historical reasons and should be avoided where possible.
 *   The flags indicates that the caller requires that the lowest zone be
 *   used (ZONE_DMA or 16M on x86-64). Ideally, this would be removed but
 *   it would require careful auditing as some users really require it and
 *   others use the flag to avoid lowmem reserves in ZONE_DMA and treat the
 *   lowest zone as a type of emergency reserve.
 * GFP_DMA32 is similar to GFP_DMA except that the caller requires a 32-bit
 *   address.
 * GFP_DMA32 is similar to GFP_DMA except that the caller requires a 32-bit
 *   address.
 * GFP_HIGHUSER is for userspace allocations that may be mapped to userspace,
 *   do not need to be directly accessible by the kernel but that cannot
 *   move once in use. An example may be a hardware allocation that maps
 *   data directly into userspace but has no addressing limitations.
 * GFP_HIGHUSER_MOVABLE is for userspace allocations that the kernel does not
 *   need direct access to but can use kmap() when access is required. They
 *   are expected to be movable via page reclaim or page migration. Typically,
 *   pages on the LRU would also be allocated with GFP_HIGHUSER_MOVABLE.
 * GFP_TRANSHUGE is used for THP allocations. They are compound allocations
 *   that will fail quickly if memory is not available and will not wake
 *   kswapd on failure.
#define GFP_KERNEL      (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
#define GFP_NOIO        (__GFP_RECLAIM)
#define GFP_NOFS        (__GFP_RECLAIM | __GFP_IO)
#define GFP_TEMPORARY   (__GFP_RECLAIM | __GFP_IO | __GFP_FS | \
#define GFP_USER        (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
#define GFP_DMA         __GFP_DMA
#define GFP_DMA32       __GFP_DMA32
                         __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN) & \
    • 슬립되지 않아야 하고 “atomic reserves”으로의 접근이 허락된  low 워터마크가 적용되게 요청한다.
    • 커널 내부 알고리즘이 이용하는 할당을 위해 사용되며, direct-reclaim이나 kswapd를 통한 reclaim이 가능하고 io 및 fs의 이용이 가능한 상태로 ZONE_NORMAL 또는 lower zone을 사용하도록 요청한다.
    • kmemcg(메모리 Control Group)의 사용량 통제를 받는것을 제외하고 GFP_KERNEL과 동일하다.
    • 커널 할당을 위해 kswapd를 사용한 reclaim이 가능하도록 요청한다.
    • direct reclaim을 이용 시 클린 페이지 또는 slab 페이지들을 버릴 수 없도록 한다.
    • direct reclaim을 이용 시 io 처리는 가능하나 file system 인터페이스를 이용하지 못한다.
    • userspace 할당을 위해 커널 및 하드웨어에 의해 직접 접근이 가능하도록 요청한다.
    • 현재 태스크에 지정된 cpuset 메모리 할당 정책을 사용하게 요청한다.
    • 가장 낮은 zone(ZONE_DMA)을 요청한다.
  • GFP_DMA32
    • ZONE_DMA를 요청한다.
    • userspace 할당을 위해 GFP_USER에 highmem 사용을 요청한다.
    • userspace 할당을 위해 GFP_USER에 highmem 및 movable migrate 타입 사용을 요청한다.
    • THP(Transparent Huge Page) 할당을 위해 사용되며 메모리 부족시 빠르게 실패하게 한다.
    • 실패한 경우에도 kswapd를 깨우지 않게 한다.

2 thoughts to “GFP 플래그”

  1. __GFP_DIRECT_RECLAIM에 대해서 궁금한점이 있습니다.
    ‘fallback이 유효한 경우 불필요한 지연을 없애기 위해 명확히 지정한다.’ 라고 설명하셨는데, 주석에서 말한 clear는 제거될 수 있다는 뜻으로 보입니다. 실제로 block/bio.c의 bvec_alloc() 코드 내부에 보면

    206 if (*idx == BVEC_POOL_MAX) {
    207 fallback:
    208 bvl = mempool_alloc(pool, gfp_mask);
    209 } else {
    210 struct biovec_slab *bvs = bvec_slabs + *idx;
    211 gfp_t __gfp_mask = gfp_mask & ~(__GFP_DIRECT_RECLAIM | __GFP_IO);
    213 /*
    214 * Make this allocation restricted and don’t dump info on
    215 * allocation failures, since we’ll fallback to the mempool
    216 * in case of failure.
    217 */
    218 __gfp_mask |= __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN;
    220 /*
    221 * Try a slab allocation. If this fails and __GFP_DIRECT_RECLAIM
    222 * is set, retry with the 1-entry mempool
    223 */
    224 bvl = kmem_cache_alloc(bvs->slab, __gfp_mask);

    이런 부분이 있습니다. fallback으로 사용할 mempool이 있는 경우에는 __GFP_DIRECT_RECLAIM flag를 제거하겠다는 뜻으로 이해하였습니다.
    제가 잘못 이해한 것인지, 의견 주시면 감사하겠습니다!

    1. 안녕하세요?

      __GFP_DIRECT_RECLAIM 관련하여 제 글의 해석이 반대로 설명된 부분이 있어 수정하였습니다.

      할당 관련하여 사용자의 fallback 코드가 준비된 경우 그 fallback 코드에서는
      명확히 __GFP_DIRECT_RECLAIM 플래그를 지우고 사용하여 지연 시간을 줄일 수 있습니다.

      잘 이해하고 질문하셨겠지만, 혹시나 조금 더 설명드리면,
      첫 번째 메모리 할당 시 direct-reclaim 옵션을 가지고도 실패하면, 두 번째 메모리 할당 시에는 direct-reclaim을 곧바로 또 해봤자, 메모리 회수가 될 확률이 거의 없습니다. 그냥 시간만 버리는 것입니다.

      따라서 메모리 할당에 대한 fallback 코드가 준비된 경우에는 direct-reclaim 플래그를 제거하고 진행하는 것이 좋습니다.


댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다