요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
Persistent snapshot merge
snapshot.rst:72-89COW ownership handover, background merge, origin write 지연과 기존 snapshot의 -EIO 동작을 정리합니다.
LVM2 구성과 완료 확인
snapshot.rst:90-196네 dm device의 배치, merge target 교체와 allocated·metadata sector 기반 완료 판정을 보여 줍니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
==============================
Device-mapper snapshot support
==============================
Device-mapper allows you, without massive data copying:
- To create snapshots of any block device i.e. mountable, saved states of
the block device which are also writable without interfering with the
original content;
- To create device "forks", i.e. multiple different versions of the
same data stream.
- To merge a snapshot of a block device back into the snapshot's origin
device.
In the first two cases, dm copies only the chunks of data that get
changed and uses a separate copy-on-write (COW) block device for
storage.
For snapshot merge the contents of the COW storage are merged back into
the origin device.
There are three dm targets available:
snapshot, snapshot-origin, and snapshot-merge.
- snapshot-origin <origin>
which will normally have one or more snapshots based on it.
Reads will be mapped directly to the backing device. For each write, the
original data will be saved in the <COW device> of each snapshot to keep
its visible content unchanged, at least until the <COW device> fills up.
- snapshot <origin> <COW device> <persistent?> <chunksize>
[<# feature args> [<arg>]*]
A snapshot of the <origin> block device is created. Changed chunks of
<chunksize> sectors will be stored on the <COW device>. Writes will
only go to the <COW device>. Reads will come from the <COW device> or
from <origin> for unchanged data. <COW device> will often be
smaller than the origin and if it fills up the snapshot will become
useless and be disabled, returning errors. So it is important to monitor
the amount of free space and expand the <COW device> before it fills up.
<persistent?> is P (Persistent) or N (Not persistent - will not survive
after reboot). O (Overflow) can be added as a persistent store option
to allow userspace to advertise its support for seeing "Overflow" in the
snapshot status. So supported store types are "P", "PO" and "N".
The difference between persistent and transient is with transient
snapshots less metadata must be saved on disk - they can be kept in
memory by the kernel.
When loading or unloading the snapshot target, the corresponding
snapshot-origin or snapshot-merge target must be suspended. A failure to
suspend the origin target could result in data corruption.
Optional features:
discard_zeroes_cow - a discard issued to the snapshot device that
maps to entire chunks to will zero the corresponding exception(s) in
the snapshot's exception store.
discard_passdown_origin - a discard to the snapshot device is passed
down to the snapshot-origin's underlying device. This doesn't cause
copy-out to the snapshot exception store because the snapshot-origin
target is bypassed.
The discard_passdown_origin feature depends on the discard_zeroes_cow
feature being enabled.
- snapshot-merge <origin> <COW device> <persistent> <chunksize>
[<# feature args> [<arg>]*]
takes the same table arguments as the snapshot target except it only
works with persistent snapshots. This target assumes the role of the
"snapshot-origin" target and must not be loaded if the "snapshot-origin"
is still present for <origin>.
Creates a merging snapshot that takes control of the changed chunks
stored in the <COW device> of an existing snapshot, through a handover
procedure, and merges these chunks back into the <origin>. Once merging
has started (in the background) the <origin> may be opened and the merge
will continue while I/O is flowing to it. Changes to the <origin> are
deferred until the merging snapshot's corresponding chunk(s) have been
merged. Once merging has started the snapshot device, associated with
the "snapshot" target, will return -EIO when accessed.
How snapshot is used by LVM2
============================
When you create the first LVM2 snapshot of a volume, four dm devices are used:
1) a device containing the original mapping table of the source volume;
2) a device used as the <COW device>;
3) a "snapshot" device, combining #1 and #2, which is the visible snapshot
volume;
4) the "original" volume (which uses the device number used by the original
source volume), whose table is replaced by a "snapshot-origin" mapping
from device #1.
A fixed naming scheme is used, so with the following commands::
lvcreate -L 1G -n base volumeGroup
lvcreate -L 100M --snapshot -n snap volumeGroup/base
we'll have this situation (with volumes in above order)::
# dmsetup table|grep volumeGroup
volumeGroup-base-real: 0 2097152 linear 8:19 384
volumeGroup-snap-cow: 0 204800 linear 8:19 2097536
volumeGroup-snap: 0 2097152 snapshot 254:11 254:12 P 16
volumeGroup-base: 0 2097152 snapshot-origin 254:11
# ls -lL /dev/mapper/volumeGroup-*
brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
brw------- 1 root root 254, 12 29 ago 18:15 /dev/mapper/volumeGroup-snap-cow
brw------- 1 root root 254, 13 29 ago 18:15 /dev/mapper/volumeGroup-snap
brw------- 1 root root 254, 10 29 ago 18:14 /dev/mapper/volumeGroup-base
How snapshot-merge is used by LVM2
==================================
A merging snapshot assumes the role of the "snapshot-origin" while
merging. As such the "snapshot-origin" is replaced with
"snapshot-merge". The "-real" device is not changed and the "-cow"
device is renamed to <origin name>-cow to aid LVM2's cleanup of the
merging snapshot after it completes. The "snapshot" that hands over its
COW device to the "snapshot-merge" is deactivated (unless using lvchange
--refresh); but if it is left active it will simply return I/O errors.
A snapshot will merge into its origin with the following command::
lvconvert --merge volumeGroup/snap
we'll now have this situation::
# dmsetup table|grep volumeGroup
volumeGroup-base-real: 0 2097152 linear 8:19 384
volumeGroup-base-cow: 0 204800 linear 8:19 2097536
volumeGroup-base: 0 2097152 snapshot-merge 254:11 254:12 P 16
# ls -lL /dev/mapper/volumeGroup-*
brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
brw------- 1 root root 254, 12 29 ago 18:16 /dev/mapper/volumeGroup-base-cow
brw------- 1 root root 254, 10 29 ago 18:16 /dev/mapper/volumeGroup-base
How to determine when a merging is complete
===========================================
The snapshot-merge and snapshot status lines end with:
<sectors_allocated>/<total_sectors> <metadata_sectors>
Both <sectors_allocated> and <total_sectors> include both data and metadata.
During merging, the number of sectors allocated gets smaller and
smaller. Merging has finished when the number of sectors holding data
is zero, in other words <sectors_allocated> == <metadata_sectors>.
Here is a practical example (using a hybrid of lvm and dmsetup commands)::
# lvs
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
base volumeGroup owi-a- 4.00g
snap volumeGroup swi-a- 1.00g base 18.97
# dmsetup status volumeGroup-snap
0 8388608 snapshot 397896/2097152 1560
^^^^ metadata sectors
# lvconvert --merge -b volumeGroup/snap
Merging of volume snap started.
# lvs volumeGroup/snap
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
base volumeGroup Owi-a- 4.00g 17.23
# dmsetup status volumeGroup-base
0 8388608 snapshot-merge 281688/2097152 1104
# dmsetup status volumeGroup-base
0 8388608 snapshot-merge 180480/2097152 712
# dmsetup status volumeGroup-base
0 8388608 snapshot-merge 16/2097152 16
Merging has finished.
::
# lvs
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
base volumeGroup owi-a- 4.00g
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
전체 복사 없는 snapshot·fork·merge
1-20Device Mapper는 대규모 data 복사 없이 임의 block device의 snapshot을 만들 수 있습니다. Snapshot은 mount 가능한 저장 상태이며 원본 내용에 간섭하지 않고 자체적으로 write할 수 있습니다.
같은 data stream에서 서로 다른 여러 version을 만드는 device 'fork'도 지원하고, block device snapshot을 그 snapshot의 origin device로 다시 merge할 수도 있습니다.
Snapshot과 fork에서는 변경된 data chunk만 복사해 별도의 copy-on-write(COW) block device에 저장합니다. Snapshot merge에서는 COW storage의 내용을 origin device로 되돌려 합칩니다.
변경분만 별도 COW에 보존하고 필요하면 그 변경분을 origin으로 merge합니다.
전체 data copy 대신 changed chunk 단위 COW를 사용합니다.
snapshot-origin의 read와 copy-out
21-32사용 가능한 dm target은 `snapshot`, `snapshot-origin`, `snapshot-merge` 세 가지입니다.
- snapshot-origin <origin>
`snapshot-origin <origin>`에는 보통 하나 이상의 snapshot이 연결됩니다. Read는 backing device로 직접 mapping합니다. Write할 때는 각 snapshot에서 보이는 내용이 변하지 않도록 원래 data를 해당 snapshot의 `<COW device>`에 먼저 저장합니다. 이 보장은 최소한 COW 장치가 가득 차기 전까지 유지됩니다.
Origin read는 직접 통과하고 origin write는 연결된 모든 snapshot의 이전 data를 보존합니다.
Snapshot constructor, store 유형과 안전한 교체
33-57- snapshot <origin> <COW device> <persistent?> <chunksize>
[<# feature args> [<arg>]*]
`<origin>` block device의 snapshot을 만듭니다. `<chunksize>` sector 크기의 변경 chunk는 `<COW device>`에 저장됩니다. Snapshot write는 COW 장치에만 기록되고, read는 변경 data이면 COW에서, 변경되지 않은 data이면 origin에서 가져옵니다.
COW 장치는 origin보다 작은 경우가 많습니다. COW가 가득 차면 snapshot은 쓸 수 없게 되고 비활성화되어 오류를 반환합니다. 따라서 free space를 감시하고 가득 차기 전에 COW 장치를 확장해야 합니다.
Exception 존재 여부에 따라 read source를 선택하고 모든 snapshot write는 COW로 보냅니다.
`<persistent?>`는 reboot 후에도 유지되는 `P`(Persistent) 또는 유지되지 않는 `N`(Not persistent)입니다. Persistent store option에 `O`(Overflow)를 추가하면 userspace가 snapshot status의 `Overflow`를 인식할 수 있음을 알립니다. 지원 store type은 `P`, `PO`, `N`입니다.
Transient snapshot은 disk에 저장할 metadata가 더 적고 kernel memory에 유지할 수 있다는 점이 persistent snapshot과 다릅니다.
Reboot 지속성과 overflow status 지원 여부를 구분합니다.
Snapshot target을 load하거나 unload할 때 대응하는 `snapshot-origin` 또는 `snapshot-merge` target을 반드시 suspend해야 합니다. Origin target suspend에 실패하면 data corruption이 발생할 수 있습니다.
Snapshot discard 선택 기능
58-71`discard_zeroes_cow`를 사용하면 snapshot device에 발행된 discard가 전체 chunk에 mapping될 때 snapshot exception store의 대응 exception을 zero 처리합니다.
`discard_passdown_origin`은 snapshot device의 discard를 snapshot-origin의 underlying device로 전달합니다. 이 경로는 `snapshot-origin` target을 우회하므로 snapshot exception store로 copy-out하지 않습니다.
`discard_passdown_origin` 기능은 `discard_zeroes_cow`가 활성화되어 있어야 사용할 수 있습니다.
COW exception 정리와 origin passdown의 동작 및 의존성을 구분합니다.
Persistent COW를 origin에 background merge
72-89- snapshot-merge <origin> <COW device> <persistent> <chunksize>
[<# feature args> [<arg>]*]
`snapshot-merge`는 `snapshot` target과 같은 table argument를 받지만 persistent snapshot에서만 동작합니다. 이 target은 `snapshot-origin` 역할을 맡으므로 같은 `<origin>`에 `snapshot-origin`이 남아 있는 상태로 load하면 안 됩니다.
Handover 절차를 통해 기존 snapshot의 `<COW device>`에 저장된 changed chunk를 넘겨받아 `<origin>`으로 merge합니다. Background merge가 시작되면 origin을 open할 수 있고 I/O가 흐르는 동안에도 merge를 계속합니다.
Origin에 대한 변경은 해당 chunk가 merge될 때까지 지연됩니다. Merge가 시작된 뒤 기존 `snapshot` target에 연결된 snapshot device를 접근하면 `-EIO`를 반환합니다.
Snapshot의 COW ownership을 merge target으로 넘기고 origin I/O와 background merge를 조정합니다.
LVM2 snapshot의 네 dm device
90-123LVM2 volume에서 첫 snapshot을 만들면 네 개의 dm device를 사용합니다. 첫째는 source volume의 원래 mapping table, 둘째는 `<COW device>`, 셋째는 앞의 두 장치를 결합해 사용자에게 보이는 `snapshot` volume, 넷째는 원래 source volume의 device number를 유지하면서 첫 장치를 가리키는 `snapshot-origin` mapping으로 table을 바꾼 'original' volume입니다.
원본 실제 mapping과 COW를 내부 device로 분리하고 snapshot과 original volume이 이를 참조합니다.
고정 naming scheme을 사용하며 다음 명령으로 1 GiB base volume과 100 MiB snapshot을 만듭니다.
lvcreate -L 1G -n base volumeGroup
lvcreate -L 100M --snapshot -n snap volumeGroup/base
그 결과의 dm table과 `/dev/mapper` device는 다음과 같습니다. 출력 순서는 위에서 설명한 네 volume 순서입니다.
# dmsetup table|grep volumeGroup
volumeGroup-base-real: 0 2097152 linear 8:19 384
volumeGroup-snap-cow: 0 204800 linear 8:19 2097536
volumeGroup-snap: 0 2097152 snapshot 254:11 254:12 P 16
volumeGroup-base: 0 2097152 snapshot-origin 254:11
# ls -lL /dev/mapper/volumeGroup-*
brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
brw------- 1 root root 254, 12 29 ago 18:15 /dev/mapper/volumeGroup-snap-cow
brw------- 1 root root 254, 13 29 ago 18:15 /dev/mapper/volumeGroup-snap
brw------- 1 root root 254, 10 29 ago 18:14 /dev/mapper/volumeGroup-base
Table target과 device number가 네 내부·외부 volume의 연결을 보여 줍니다.
LVM2 merge 시 target 교체와 이름 변경
124-150Merge 중에는 merging snapshot이 `snapshot-origin` 역할을 맡으므로 `snapshot-origin`을 `snapshot-merge`로 교체합니다. `-real` device는 바꾸지 않고, merge 완료 뒤 LVM2가 정리하기 쉽도록 `-cow` device를 `<origin name>-cow`로 이름 변경합니다.
COW device를 `snapshot-merge`에 넘긴 `snapshot`은 비활성화됩니다. 단, `lvchange --refresh`를 사용하는 경우는 예외입니다. Snapshot을 active 상태로 남겨도 접근 시 I/O error만 반환합니다.
Real mapping을 유지한 채 origin target과 COW 이름만 merge 상태에 맞게 바꿉니다.
다음 명령으로 snapshot을 origin에 merge합니다.
lvconvert --merge volumeGroup/snap
Merge를 시작한 뒤 table과 device 이름은 다음과 같이 바뀝니다.
# dmsetup table|grep volumeGroup
volumeGroup-base-real: 0 2097152 linear 8:19 384
volumeGroup-base-cow: 0 204800 linear 8:19 2097536
volumeGroup-base: 0 2097152 snapshot-merge 254:11 254:12 P 16
# ls -lL /dev/mapper/volumeGroup-*
brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
brw------- 1 root root 254, 12 29 ago 18:16 /dev/mapper/volumeGroup-base-cow
brw------- 1 root root 254, 10 29 ago 18:16 /dev/mapper/volumeGroup-base
Base volume이 snapshot-merge target이 되고 COW가 base 이름 아래로 이동합니다.
Merge 완료 판정식
151-162`snapshot-merge`와 `snapshot` status line의 끝은 다음 형식입니다.
<sectors_allocated>/<total_sectors> <metadata_sectors>
`<sectors_allocated>`와 `<total_sectors>`에는 data와 metadata가 모두 포함됩니다. Merge 중에는 allocated sector 수가 계속 감소합니다.
Data를 담은 sector 수가 0이면 merge가 끝난 것입니다. 즉 완료 조건은 `<sectors_allocated> == <metadata_sectors>`입니다.
Allocated 값에서 metadata만 남았는지 비교해 data merge 완료를 판단합니다.
Allocated sector가 줄어 metadata sector와 같아지는 순간 merge가 완료됩니다.
LVM과 dmsetup을 함께 쓴 완료 예제
163-196실제 예제는 LVM과 `dmsetup` 명령을 함께 사용합니다. 처음 snapshot은 18.97% 사용 중이고 status는 allocated/total `397896/2097152`, metadata `1560`을 보고합니다.
`lvconvert --merge -b`로 background merge를 시작하면 base volume이 merge 상태가 됩니다. 이어지는 status에서 allocated sector가 `281688`, `180480`, 마지막에는 `16`으로 감소합니다. 마지막 status의 metadata sector도 `16`이므로 완료 조건을 만족합니다.
# lvs
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
base volumeGroup owi-a- 4.00g
snap volumeGroup swi-a- 1.00g base 18.97
# dmsetup status volumeGroup-snap
0 8388608 snapshot 397896/2097152 1560
^^^^ metadata sectors
# lvconvert --merge -b volumeGroup/snap
Merging of volume snap started.
# lvs volumeGroup/snap
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
base volumeGroup Owi-a- 4.00g 17.23
# dmsetup status volumeGroup-base
0 8388608 snapshot-merge 281688/2097152 1104
# dmsetup status volumeGroup-base
0 8388608 snapshot-merge 180480/2097152 712
# dmsetup status volumeGroup-base
0 8388608 snapshot-merge 16/2097152 16
Status의 allocated sector가 metadata sector와 같아지는 과정을 정리합니다.
Merge가 끝나면 snapshot volume은 사라지고 base volume만 일반 LVM volume으로 남습니다.
::
# lvs
LV VG Attr LSize Origin Snap% Move Log Copy% Convert
base volumeGroup owi-a- 4.00g
Snapshot과 COW가 정리되고 origin base volume만 남습니다.
Snapshot target과 COW
snapshot.rst:1-71snapshot-origin, snapshot과 discard 기능의 I/O routing, store 유형과 COW 용량 제약을 설명합니다.