요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
상태와 data path
dm-pcache.rst:61-155세 cursor, segment·kset 구조, write-back·GC·CRC 흐름을 정리합니다.
Failure와 workflow
dm-pcache.rst:156-202Media 오류·cache full·crash 복구, 현재 제약과 운영 예제를 설명합니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
=================================
dm-pcache — Persistent Cache
=================================
*Author: Dongsheng Yang <dongsheng.yang@linux.dev>*
This document describes *dm-pcache*, a Device-Mapper target that lets a
byte-addressable *DAX* (persistent-memory, “pmem”) region act as a
high-performance, crash-persistent cache in front of a slower block
device. The code lives in `drivers/md/dm-pcache/`.
Quick feature summary
=====================
* *Write-back* caching (only mode currently supported).
* *16 MiB segments* allocated on the pmem device.
* *Data CRC32* verification (optional, per cache).
* Crash-safe: every metadata structure is duplicated (`PCACHE_META_INDEX_MAX
== 2`) and protected with CRC+sequence numbers.
* *Multi-tree indexing* (indexing trees sharded by logical address) for high PMem parallelism
* Pure *DAX path* I/O – no extra BIO round-trips
* *Log-structured write-back* that preserves backend crash-consistency
Constructor
===========
::
pcache <cache_dev> <backing_dev> [<number_of_optional_arguments> <cache_mode writeback> <data_crc true|false>]
========================= ====================================================
``cache_dev`` Any DAX-capable block device (``/dev/pmem0``…).
All metadata *and* cached blocks are stored here.
``backing_dev`` The slow block device to be cached.
``cache_mode`` Optional, Only ``writeback`` is accepted at the
moment.
``data_crc`` Optional, default to ``false``
* ``true`` – store CRC32 for every cached entry
and verify on reads
* ``false`` – skip CRC (faster)
========================= ====================================================
Example
-------
.. code-block:: shell
dmsetup create pcache_sdb --table \
"0 $(blockdev --getsz /dev/sdb) pcache /dev/pmem0 /dev/sdb 4 cache_mode writeback data_crc true"
The first time a pmem device is used, dm-pcache formats it automatically
(super-block, cache_info, etc.).
Status line
===========
``dmsetup status <device>`` (``STATUSTYPE_INFO``) prints:
::
<sb_flags> <seg_total> <cache_segs> <segs_used> \
<gc_percent> <cache_flags> \
<key_head_seg>:<key_head_off> \
<dirty_tail_seg>:<dirty_tail_off> \
<key_tail_seg>:<key_tail_off>
Field meanings
--------------
=============================== =============================================
``sb_flags`` Super-block flags (e.g. endian marker).
``seg_total`` Number of physical *pmem* segments.
``cache_segs`` Number of segments used for cache.
``segs_used`` Segments currently allocated (bitmap weight).
``gc_percent`` Current GC high-water mark (0-90).
``cache_flags`` Bit 0 – DATA_CRC enabled
Bit 1 – INIT_DONE (cache initialised)
Bits 2-5 – cache mode (0 == WB).
``key_head`` Where new key-sets are being written.
``dirty_tail`` First dirty key-set that still needs
write-back to the backing device.
``key_tail`` First key-set that may be reclaimed by GC.
=============================== =============================================
Messages
========
*Change GC trigger*
::
dmsetup message <dev> 0 gc_percent <0-90>
Theory of operation
===================
Sub-devices
-----------
==================== =========================================================
backing_dev Any block device (SSD/HDD/loop/LVM, etc.).
cache_dev DAX device; must expose direct-access memory.
==================== =========================================================
Segments and key-sets
---------------------
* The pmem space is divided into *16 MiB segments*.
* Each write allocates space from a per-CPU *data_head* inside a segment.
* A *cache-key* records a logical range on the origin and where it lives
inside pmem (segment + offset + generation).
* 128 keys form a *key-set* (kset); ksets are written sequentially in pmem
and are themselves crash-safe (CRC).
* The pair *(key_tail, dirty_tail)* delimit clean/dirty and live/dead ksets.
Write-back
----------
Dirty keys are queued into a tree; a background worker copies data
back to the backing_dev and advances *dirty_tail*. A FLUSH/FUA bio from the
upper layers forces an immediate metadata commit.
Garbage collection
------------------
GC starts when ``segs_used >= seg_total * gc_percent / 100``. It walks
from *key_tail*, frees segments whose every key has been invalidated, and
advances *key_tail*.
CRC verification
----------------
If ``data_crc is enabled`` dm-pcache computes a CRC32 over every cached data
range when it is inserted and stores it in the on-media key. Reads
validate the CRC before copying to the caller.
Failure handling
================
* *pmem media errors* – all metadata copies are read with
``copy_mc_to_kernel``; an uncorrectable error logs and aborts initialisation.
* *Cache full* – if no free segment can be found, writes return ``-EBUSY``;
dm-pcache retries internally (request deferral).
* *System crash* – on attach, the driver replays ksets from *key_tail* to
rebuild the in-core trees; every segment’s generation guards against
use-after-free keys.
Limitations & TODO
==================
* Only *write-back* mode; other modes planned.
* Only FIFO cache invalidate; other (LRU, ARC...) planned.
* Table reload is not supported currently.
* Discard planned.
Example workflow
================
.. code-block:: shell
# 1. Create devices
dmsetup create pcache_sdb --table \
"0 $(blockdev --getsz /dev/sdb) pcache /dev/pmem0 /dev/sdb 4 cache_mode writeback data_crc true"
# 2. Put a filesystem on top
mkfs.ext4 /dev/mapper/pcache_sdb
mount /dev/mapper/pcache_sdb /mnt
# 3. Tune GC threshold to 80 %
dmsetup message pcache_sdb 0 gc_percent 80
# 4. Observe status
watch -n1 'dmsetup status pcache_sdb'
# 5. Shutdown
umount /mnt
dmsetup remove pcache_sdb
``dm-pcache`` is under active development; feedback, bug reports and patches
are very welcome!
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
DAX persistent cache 구조와 기능
1-25저자는 Dongsheng Yang `<dongsheng.yang@linux.dev>`입니다. `dm-pcache`는 byte-addressable DAX persistent-memory, 즉 pmem 영역을 느린 block device 앞의 고성능 crash-persistent cache로 사용하는 Device-Mapper target입니다. 구현은 `drivers/md/dm-pcache/`에 있습니다.
빠른 DAX pmem이 느린 backing block device 앞에서 write-back cache로 동작합니다.
현재 구현의 cache 정책, 배치, 검증과 crash-safety 특성입니다.
Target constructor와 최초 format
26-60Target constructor 형식은 다음과 같습니다.
pcache <cache_dev> <backing_dev> [<number_of_optional_arguments> <cache_mode writeback> <data_crc true|false>]
Cache 장치, backing 장치와 optional key/value 인자를 지정합니다.
========================= ====================================================
``cache_dev`` Any DAX-capable block device (``/dev/pmem0``…).
All metadata *and* cached blocks are stored here.
``backing_dev`` The slow block device to be cached.
``cache_mode`` Optional, Only ``writeback`` is accepted at the
moment.
``data_crc`` Optional, default to ``false``
* ``true`` – store CRC32 for every cached entry
and verify on reads
* ``false`` – skip CRC (faster)
========================= ====================================================
다음 예는 `/dev/pmem0`를 `/dev/sdb`의 write-back cache로 사용하고 data CRC를 활성화합니다.
dmsetup create pcache_sdb --table \
"0 $(blockdev --getsz /dev/sdb) pcache /dev/pmem0 /dev/sdb 4 cache_mode writeback data_crc true"
PMem 장치를 처음 사용하면 `dm-pcache`가 superblock과 `cache_info` 등을 자동으로 format합니다.
Status line과 세 개의 log cursor
61-101`dmsetup status <device>`의 `STATUSTYPE_INFO` 출력 형식은 다음과 같습니다.
<sb_flags> <seg_total> <cache_segs> <segs_used> \
<gc_percent> <cache_flags> \
<key_head_seg>:<key_head_off> \
<dirty_tail_seg>:<dirty_tail_off> \
<key_tail_seg>:<key_tail_off>
용량, GC 임계값, cache 상태와 log cursor 위치를 보여 줍니다.
=============================== =============================================
``sb_flags`` Super-block flags (e.g. endian marker).
``seg_total`` Number of physical *pmem* segments.
``cache_segs`` Number of segments used for cache.
``segs_used`` Segments currently allocated (bitmap weight).
``gc_percent`` Current GC high-water mark (0-90).
``cache_flags`` Bit 0 – DATA_CRC enabled
Bit 1 – INIT_DONE (cache initialised)
Bits 2-5 – cache mode (0 == WB).
``key_head`` Where new key-sets are being written.
``dirty_tail`` First dirty key-set that still needs
write-back to the backing device.
``key_tail`` First key-set that may be reclaimed by GC.
=============================== =============================================
세 cursor가 새 기록, dirty write-back 경계와 GC 회수 경계를 나눕니다.
GC trigger runtime message
102-111Runtime message로 GC가 시작되는 사용률 임계값을 0부터 90 사이에서 변경할 수 있습니다.
dmsetup message <dev> 0 gc_percent <0-90>
Target sector 0에 message를 보내 새 high-water mark를 적용합니다.
Sub-device, segment와 key-set
112-133`backing_dev`는 SSD, HDD, loop, LVM 등을 포함한 임의의 block device입니다. `cache_dev`는 direct-access memory를 노출하는 DAX 장치여야 합니다.
Cache data path의 두 저장 계층입니다.
==================== =========================================================
backing_dev Any block device (SSD/HDD/loop/LVM, etc.).
cache_dev DAX device; must expose direct-access memory.
==================== =========================================================
PMem 공간은 16 MiB segment로 나뉩니다. 각 write는 segment 안의 per-CPU `data_head`에서 공간을 할당합니다. `cache-key`는 origin의 logical range와 PMem 내 위치인 segment, offset, generation을 기록합니다.
Key 128개가 하나의 key-set, 즉 kset을 이룹니다. Kset은 PMem에 순차 기록되고 자체 CRC로 crash-safe하게 보호됩니다. `(key_tail, dirty_tail)` 쌍은 clean/dirty kset과 live/dead kset의 경계를 정합니다.
Per-CPU append 위치에서 data를 할당하고 key를 128개씩 crash-safe kset으로 묶습니다.
Write-back, garbage collection과 CRC 검증
134-155Dirty key는 tree에 queue됩니다. Background worker가 data를 `backing_dev`로 복사하고 `dirty_tail`을 전진시킵니다. Upper layer의 FLUSH 또는 FUA bio는 metadata를 즉시 commit하도록 강제합니다.
Dirty tree를 순회해 backing device에 반영하고 clean 경계를 이동합니다.
GC는 `segs_used >= seg_total * gc_percent / 100`일 때 시작합니다. `key_tail`부터 순회해 모든 key가 invalidate된 segment를 해제하고 `key_tail`을 전진시킵니다.
High-water mark를 넘으면 가장 오래된 kset부터 완전히 죽은 segment를 회수합니다.
`data_crc`를 활성화하면 cached data range를 삽입할 때마다 CRC32를 계산해 on-media key에 저장합니다. Read에서는 caller에게 복사하기 전에 CRC를 검증합니다.
삽입 시 저장한 CRC32와 read 시 재계산 값을 비교합니다.
Failure 처리와 현재 제약
156-175Media 오류, cache 부족과 crash 재부착 상황의 동작입니다.
문서 시점에 지원하지 않거나 계획된 기능입니다.
생성부터 종료까지의 예제 workflow
176-202다음 workflow는 target 생성, filesystem 생성과 mount, GC 임계값 조정, status 관찰, 안전한 unmount와 제거 순서를 보여 줍니다.
# 1. Create devices
dmsetup create pcache_sdb --table \
"0 $(blockdev --getsz /dev/sdb) pcache /dev/pmem0 /dev/sdb 4 cache_mode writeback data_crc true"
# 2. Put a filesystem on top
mkfs.ext4 /dev/mapper/pcache_sdb
mount /dev/mapper/pcache_sdb /mnt
# 3. Tune GC threshold to 80 %
dmsetup message pcache_sdb 0 gc_percent 80
# 4. Observe status
watch -n1 'dmsetup status pcache_sdb'
# 5. Shutdown
umount /mnt
dmsetup remove pcache_sdb
Cache 장치를 만든 뒤 filesystem을 사용하고 GC를 조정한 다음 순서대로 종료합니다.
`dm-pcache`는 활발히 개발 중이며 feedback, bug report와 patch를 환영합니다.
구조와 생성
dm-pcache.rst:1-60DAX cache 아키텍처, crash-safe metadata와 constructor·최초 format을 설명합니다.