요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
Loop device 검증
unstriped.rst:29-80네 member를 stripe한 뒤 각 unstriped view의 write가 올바른 backing file에 도달하는지 확인합니다.
NVMe core 격리
unstriped.rst:81-135두 core LBA layout을 분리해 noisy-neighbor 영향을 줄이고 네 drive mapping으로 확장하는 예제를 제공합니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
================================
Device-mapper "unstriped" target
================================
Introduction
============
The device-mapper "unstriped" target provides a transparent mechanism to
unstripe a device-mapper "striped" target to access the underlying disks
without having to touch the true backing block-device. It can also be
used to unstripe a hardware RAID-0 to access backing disks.
Parameters:
<number of stripes> <chunk size> <stripe #> <dev_path> <offset>
<number of stripes>
The number of stripes in the RAID 0.
<chunk size>
The amount of 512B sectors in the chunk striping.
<dev_path>
The block device you wish to unstripe.
<stripe #>
The stripe number within the device that corresponds to physical
drive you wish to unstripe. This must be 0 indexed.
Why use this module?
====================
An example of undoing an existing dm-stripe
-------------------------------------------
This small bash script will setup 4 loop devices and use the existing
striped target to combine the 4 devices into one. It then will use
the unstriped target on top of the striped device to access the
individual backing loop devices. We write data to the newly exposed
unstriped devices and verify the data written matches the correct
underlying device on the striped array::
#!/bin/bash
MEMBER_SIZE=$((128 * 1024 * 1024))
NUM=4
SEQ_END=$((${NUM}-1))
CHUNK=256
BS=4096
RAID_SIZE=$((${MEMBER_SIZE}*${NUM}/512))
DM_PARMS="0 ${RAID_SIZE} striped ${NUM} ${CHUNK}"
COUNT=$((${MEMBER_SIZE} / ${BS}))
for i in $(seq 0 ${SEQ_END}); do
dd if=/dev/zero of=member-${i} bs=${MEMBER_SIZE} count=1 oflag=direct
losetup /dev/loop${i} member-${i}
DM_PARMS+=" /dev/loop${i} 0"
done
echo $DM_PARMS | dmsetup create raid0
for i in $(seq 0 ${SEQ_END}); do
echo "0 1 unstriped ${NUM} ${CHUNK} ${i} /dev/mapper/raid0 0" | dmsetup create set-${i}
done;
for i in $(seq 0 ${SEQ_END}); do
dd if=/dev/urandom of=/dev/mapper/set-${i} bs=${BS} count=${COUNT} oflag=direct
diff /dev/mapper/set-${i} member-${i}
done;
for i in $(seq 0 ${SEQ_END}); do
dmsetup remove set-${i}
done
dmsetup remove raid0
for i in $(seq 0 ${SEQ_END}); do
losetup -d /dev/loop${i}
rm -f member-${i}
done
Another example
---------------
Intel NVMe drives contain two cores on the physical device.
Each core of the drive has segregated access to its LBA range.
The current LBA model has a RAID 0 128k chunk on each core, resulting
in a 256k stripe across the two cores::
Core 0: Core 1:
__________ __________
| LBA 512| | LBA 768|
| LBA 0 | | LBA 256|
---------- ----------
The purpose of this unstriping is to provide better QoS in noisy
neighbor environments. When two partitions are created on the
aggregate drive without this unstriping, reads on one partition
can affect writes on another partition. This is because the partitions
are striped across the two cores. When we unstripe this hardware RAID 0
and make partitions on each new exposed device the two partitions are now
physically separated.
With the dm-unstriped target we're able to segregate an fio script that
has read and write jobs that are independent of each other. Compared to
when we run the test on a combined drive with partitions, we were able
to get a 92% reduction in read latency using this device mapper target.
Example dmsetup usage
=====================
unstriped on top of Intel NVMe device that has 2 cores
------------------------------------------------------
::
dmsetup create nvmset0 --table '0 512 unstriped 2 256 0 /dev/nvme0n1 0'
dmsetup create nvmset1 --table '0 512 unstriped 2 256 1 /dev/nvme0n1 0'
There will now be two devices that expose Intel NVMe core 0 and 1
respectively::
/dev/mapper/nvmset0
/dev/mapper/nvmset1
unstriped on top of striped with 4 drives using 128K chunk size
---------------------------------------------------------------
::
dmsetup create raid_disk0 --table '0 512 unstriped 4 256 0 /dev/mapper/striped 0'
dmsetup create raid_disk1 --table '0 512 unstriped 4 256 1 /dev/mapper/striped 0'
dmsetup create raid_disk2 --table '0 512 unstriped 4 256 2 /dev/mapper/striped 0'
dmsetup create raid_disk3 --table '0 512 unstriped 4 256 3 /dev/mapper/striped 0'
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Striped address space에서 한 physical stripe 추출
1-28Device Mapper의 `unstriped` target은 실제 backing block device를 직접 건드리지 않고 Device Mapper `striped` target을 unstripe해 underlying disk에 접근하는 투명한 mechanism을 제공합니다. Hardware RAID-0을 unstripe해 backing disk에 접근하는 데도 사용할 수 있습니다.
Aggregate striped address space에서 지정한 stripe 번호의 chunk들만 이어 하나의 linear view로 노출합니다.
Constructor parameter 형식은 다음과 같습니다.
Parameters:
<number of stripes> <chunk size> <stripe #> <dev_path> <offset>
원래 RAID geometry와 추출할 stripe, aggregate device 위치를 지정합니다.
기존 dm-stripe를 되돌리는 검증 scenario
29-41작은 Bash script가 loop device 네 개를 만들고 기존 `striped` target으로 하나의 RAID-0 장치로 결합합니다. 그 위에 `unstriped` target을 배치해 개별 backing loop device에 접근합니다.
새로 노출된 각 unstriped device에 data를 쓰고, 기록된 data가 striped array의 올바른 underlying device 내용과 일치하는지 검증합니다.
Striped target 위에서 stripe별 view를 만들고 원본 member file과 byte 단위로 비교합니다.
네 member 생성·write 검증·정리
42-80각 member 크기는 128 MiB이고 device 수는 4개입니다. Chunk는 256 sector, I/O block size는 4096 byte입니다. 전체 RAID sector 수와 `striped` table parameter를 계산합니다.
Loop에서 zero-filled member file과 `/dev/loop0`~`/dev/loop3`을 만들고 각 path를 stripe table에 추가합니다. `raid0` target을 만든 다음 stripe index마다 `set-0`~`set-3` unstriped device를 생성합니다.
각 `set-i`에 `/dev/urandom` data를 direct I/O로 기록한 뒤 대응하는 `member-i`와 `diff`합니다. 검증이 끝나면 unstriped device와 raid0를 제거하고 loop device와 member file을 정리합니다.
#!/bin/bash
MEMBER_SIZE=$((128 * 1024 * 1024))
NUM=4
SEQ_END=$((${NUM}-1))
CHUNK=256
BS=4096
RAID_SIZE=$((${MEMBER_SIZE}*${NUM}/512))
DM_PARMS="0 ${RAID_SIZE} striped ${NUM} ${CHUNK}"
COUNT=$((${MEMBER_SIZE} / ${BS}))
for i in $(seq 0 ${SEQ_END}); do
dd if=/dev/zero of=member-${i} bs=${MEMBER_SIZE} count=1 oflag=direct
losetup /dev/loop${i} member-${i}
DM_PARMS+=" /dev/loop${i} 0"
done
echo $DM_PARMS | dmsetup create raid0
for i in $(seq 0 ${SEQ_END}); do
echo "0 1 unstriped ${NUM} ${CHUNK} ${i} /dev/mapper/raid0 0" | dmsetup create set-${i}
done;
for i in $(seq 0 ${SEQ_END}); do
dd if=/dev/urandom of=/dev/mapper/set-${i} bs=${BS} count=${COUNT} oflag=direct
diff /dev/mapper/set-${i} member-${i}
done;
for i in $(seq 0 ${SEQ_END}); do
dmsetup remove set-${i}
done
dmsetup remove raid0
for i in $(seq 0 ${SEQ_END}); do
losetup -d /dev/loop${i}
rm -f member-${i}
done
환경 구성부터 data routing 검증과 cleanup까지 단계별로 진행합니다.
Script의 주요 상수와 계산 결과의 의미입니다.
두 NVMe core의 LBA 분리와 QoS
81-108Intel NVMe physical device에는 core가 두 개 있으며 각 core는 서로 분리된 LBA range에 접근합니다. 현재 LBA model은 core마다 RAID-0 128 KiB chunk를 두어 두 core 전체의 stripe 크기가 256 KiB가 됩니다.
원문의 ASCII 그림을 chunk 범위 표로 다시 구성했습니다.
Unstriping 목적은 noisy-neighbor 환경에서 QoS를 높이는 것입니다. Aggregate drive에 unstriping 없이 partition 두 개를 만들면 두 partition이 모두 두 core에 stripe되므로 한 partition의 read가 다른 partition의 write에 영향을 줄 수 있습니다.
Hardware RAID-0을 unstripe하고 새로 노출된 core별 device에 partition을 만들면 두 partition이 물리적으로 분리됩니다.
Aggregate partition은 두 core를 공유하지만 unstriped partition은 core별로 분리됩니다.
`dm-unstriped`를 사용하면 서로 독립적인 read job과 write job을 가진 `fio` script를 core별로 분리할 수 있습니다. Partition을 둔 combined drive에서 같은 test를 실행한 경우와 비교해 read latency가 92% 감소했습니다.
문서의 test scenario에서 aggregate partition 대비 latency 개선을 요약합니다.
두 core를 각각 노출하는 dmsetup table
109-126두 core를 가진 Intel NVMe device 위에 stripe 0과 1의 unstriped target을 각각 만듭니다. Stripe 수는 2, chunk는 256 sector이며 두 mapping 모두 `/dev/nvme0n1` offset 0을 사용합니다.
::
dmsetup create nvmset0 --table '0 512 unstriped 2 256 0 /dev/nvme0n1 0'
dmsetup create nvmset1 --table '0 512 unstriped 2 256 1 /dev/nvme0n1 0'
같은 aggregate device에서 stripe number만 달리해 core별 view를 만듭니다.
생성 뒤 다음 두 device가 Intel NVMe core 0과 core 1을 각각 노출합니다.
/dev/mapper/nvmset0
/dev/mapper/nvmset1
Unstriped target 이름과 대응 core입니다.
네 drive stripe를 개별 view로 노출
127-135128 KiB chunk를 사용하는 네 drive striped device 위에서 stripe number 0~3을 각각 선택해 `raid_disk0`~`raid_disk3`을 만듭니다. 네 target 모두 `/dev/mapper/striped`와 offset 0을 사용합니다.
::
dmsetup create raid_disk0 --table '0 512 unstriped 4 256 0 /dev/mapper/striped 0'
dmsetup create raid_disk1 --table '0 512 unstriped 4 256 1 /dev/mapper/striped 0'
dmsetup create raid_disk2 --table '0 512 unstriped 4 256 2 /dev/mapper/striped 0'
dmsetup create raid_disk3 --table '0 512 unstriped 4 256 3 /dev/mapper/striped 0'
Aggregate striped target에서 네 stripe position을 별도 mapper device로 분리합니다.
네 명령은 stripe number만 다르고 나머지 geometry는 같습니다.
Unstriped mapping
unstriped.rst:1-28RAID geometry와 0-based stripe number로 aggregate device의 한 physical member view를 선택합니다.