요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
목록과 failure 제어
dm-dust.rst:86-254Bad block 추가·삭제·조회·전체 정리, read EIO와 write-remap 및 전체 message를 정리합니다.
Logging과 설계 이유
dm-dust.rst:255-305Quiet mode toggle과 scsi_debug·dm-flakey 대신 dm-dust가 필요한 이유를 설명합니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
dm-dust
=======
This target emulates the behavior of bad sectors at arbitrary
locations, and the ability to enable the emulation of the failures
at an arbitrary time.
This target behaves similarly to a linear target. At a given time,
the user can send a message to the target to start failing read
requests on specific blocks (to emulate the behavior of a hard disk
drive with bad sectors).
When the failure behavior is enabled (i.e.: when the output of
"dmsetup status" displays "fail_read_on_bad_block"), reads of blocks
in the "bad block list" will fail with EIO ("Input/output error").
Writes of blocks in the "bad block list will result in the following:
1. Remove the block from the "bad block list".
2. Successfully complete the write.
This emulates the "remapped sector" behavior of a drive with bad
sectors.
Normally, a drive that is encountering bad sectors will most likely
encounter more bad sectors, at an unknown time or location.
With dm-dust, the user can use the "addbadblock" and "removebadblock"
messages to add arbitrary bad blocks at new locations, and the
"enable" and "disable" messages to modulate the state of whether the
configured "bad blocks" will be treated as bad, or bypassed.
This allows the pre-writing of test data and metadata prior to
simulating a "failure" event where bad sectors start to appear.
Table parameters
----------------
<device_path> <offset> <blksz>
Mandatory parameters:
<device_path>:
Path to the block device.
<offset>:
Offset to data area from start of device_path
<blksz>:
Block size in bytes
(minimum 512, maximum 1073741824, must be a power of 2)
Usage instructions
------------------
First, find the size (in 512-byte sectors) of the device to be used::
$ sudo blockdev --getsz /dev/vdb1
33552384
Create the dm-dust device:
(For a device with a block size of 512 bytes)
::
$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 512'
(For a device with a block size of 4096 bytes)
::
$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 4096'
Check the status of the read behavior ("bypass" indicates that all I/O
will be passed through to the underlying device; "verbose" indicates that
bad block additions, removals, and remaps will be verbosely logged)::
$ sudo dmsetup status dust1
0 33552384 dust 252:17 bypass verbose
$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=128 iflag=direct
128+0 records in
128+0 records out
$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
128+0 records in
128+0 records out
Adding and removing bad blocks
------------------------------
At any time (i.e.: whether the device has the "bad block" emulation
enabled or disabled), bad blocks may be added or removed from the
device via the "addbadblock" and "removebadblock" messages::
$ sudo dmsetup message dust1 0 addbadblock 60
kernel: device-mapper: dust: badblock added at block 60
$ sudo dmsetup message dust1 0 addbadblock 67
kernel: device-mapper: dust: badblock added at block 67
$ sudo dmsetup message dust1 0 addbadblock 72
kernel: device-mapper: dust: badblock added at block 72
These bad blocks will be stored in the "bad block list".
While the device is in "bypass" mode, reads and writes will succeed::
$ sudo dmsetup status dust1
0 33552384 dust 252:17 bypass
Enabling block read failures
----------------------------
To enable the "fail read on bad block" behavior, send the "enable" message::
$ sudo dmsetup message dust1 0 enable
kernel: device-mapper: dust: enabling read failures on bad sectors
$ sudo dmsetup status dust1
0 33552384 dust 252:17 fail_read_on_bad_block
With the device in "fail read on bad block" mode, attempting to read a
block will encounter an "Input/output error"::
$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=1 skip=67 iflag=direct
dd: error reading '/dev/mapper/dust1': Input/output error
0+0 records in
0+0 records out
0 bytes copied, 0.00040651 s, 0.0 kB/s
...and writing to the bad blocks will remove the blocks from the list,
therefore emulating the "remap" behavior of hard disk drives::
$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
128+0 records in
128+0 records out
kernel: device-mapper: dust: block 60 removed from badblocklist by write
kernel: device-mapper: dust: block 67 removed from badblocklist by write
kernel: device-mapper: dust: block 72 removed from badblocklist by write
kernel: device-mapper: dust: block 87 removed from badblocklist by write
Bad block add/remove error handling
-----------------------------------
Attempting to add a bad block that already exists in the list will
result in an "Invalid argument" error, as well as a helpful message::
$ sudo dmsetup message dust1 0 addbadblock 88
device-mapper: message ioctl on dust1 failed: Invalid argument
kernel: device-mapper: dust: block 88 already in badblocklist
Attempting to remove a bad block that doesn't exist in the list will
result in an "Invalid argument" error, as well as a helpful message::
$ sudo dmsetup message dust1 0 removebadblock 87
device-mapper: message ioctl on dust1 failed: Invalid argument
kernel: device-mapper: dust: block 87 not found in badblocklist
Counting the number of bad blocks in the bad block list
-------------------------------------------------------
To count the number of bad blocks configured in the device, run the
following message command::
$ sudo dmsetup message dust1 0 countbadblocks
A message will print with the number of bad blocks currently
configured on the device::
countbadblocks: 895 badblock(s) found
Querying for specific bad blocks
--------------------------------
To find out if a specific block is in the bad block list, run the
following message command::
$ sudo dmsetup message dust1 0 queryblock 72
The following message will print if the block is in the list::
dust_query_block: block 72 found in badblocklist
The following message will print if the block is not in the list::
dust_query_block: block 72 not found in badblocklist
The "queryblock" message command will work in both the "enabled"
and "disabled" modes, allowing the verification of whether a block
will be treated as "bad" without having to issue I/O to the device,
or having to "enable" the bad block emulation.
Clearing the bad block list
---------------------------
To clear the bad block list (without needing to individually run
a "removebadblock" message command for every block), run the
following message command::
$ sudo dmsetup message dust1 0 clearbadblocks
After clearing the bad block list, the following message will appear::
dust_clear_badblocks: badblocks cleared
If there were no bad blocks to clear, the following message will
appear::
dust_clear_badblocks: no badblocks found
Listing the bad block list
--------------------------
To list all bad blocks in the bad block list (using an example device
with blocks 1 and 2 in the bad block list), run the following message
command::
$ sudo dmsetup message dust1 0 listbadblocks
1
2
If there are no bad blocks in the bad block list, the command will
execute with no output::
$ sudo dmsetup message dust1 0 listbadblocks
Message commands list
---------------------
Below is a list of the messages that can be sent to a dust device:
Operations on blocks (requires a <blknum> argument)::
addbadblock <blknum>
queryblock <blknum>
removebadblock <blknum>
...where <blknum> is a block number within range of the device
(corresponding to the block size of the device.)
Single argument message commands::
countbadblocks
clearbadblocks
listbadblocks
disable
enable
quiet
Device removal
--------------
When finished, remove the device via the "dmsetup remove" command::
$ sudo dmsetup remove dust1
Quiet mode
----------
On test runs with many bad blocks, it may be desirable to avoid
excessive logging (from bad blocks added, removed, or "remapped").
This can be done by enabling "quiet mode" via the following message::
$ sudo dmsetup message dust1 0 quiet
This will suppress log messages from add / remove / removed by write
operations. Log messages from "countbadblocks" or "queryblock"
message commands will still print in quiet mode.
The status of quiet mode can be seen by running "dmsetup status"::
$ sudo dmsetup status dust1
0 33552384 dust 252:17 fail_read_on_bad_block quiet
To disable quiet mode, send the "quiet" message again::
$ sudo dmsetup message dust1 0 quiet
$ sudo dmsetup status dust1
0 33552384 dust 252:17 fail_read_on_bad_block verbose
(The presence of "verbose" indicates normal logging.)
"Why not...?"
-------------
scsi_debug has a "medium error" mode that can fail reads on one
specified sector (sector 0x1234, hardcoded in the source code), but
it uses RAM for the persistent storage, which drastically decreases
the potential device size.
dm-flakey fails all I/O from all block locations at a specified time
frequency, and not a given point in time.
When a bad sector occurs on a hard disk drive, reads to that sector
are failed by the device, usually resulting in an error code of EIO
("I/O error") or ENODATA ("No data available"). However, a write to
the sector may succeed, and result in the sector becoming readable
after the device controller no longer experiences errors reading the
sector (or after a reallocation of the sector). However, there may
be bad sectors that occur on the device in the future, in a different,
unpredictable location.
This target seeks to provide a device that can exhibit the behavior
of a bad sector at a known sector location, at a known time, based
on a large storage device (at least tens of gigabytes, not occupying
system memory).
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
임의 위치의 bad-sector emulation
1-33`dm-dust` target은 임의 위치의 bad sector 동작과 임의 시점에 failure emulation을 활성화하는 기능을 제공합니다.
평소에는 linear target과 비슷하게 동작합니다. 사용자는 특정 시점에 target으로 message를 보내 지정 block의 read request를 실패시켜 bad sector가 있는 hard disk drive 동작을 흉내 낼 수 있습니다.
Failure가 활성화되어 `dmsetup status`에 `fail_read_on_bad_block`이 표시되면 bad block list에 있는 block read가 EIO(`Input/output error`)로 실패합니다.
Bad block list에 있는 block에 write하면 먼저 그 block을 list에서 제거하고 write 자체는 성공시킵니다. 이는 bad sector가 있는 drive의 `remapped sector` 동작을 emulation합니다.
Bad sector가 생기기 시작한 drive는 알 수 없는 시간과 위치에서 더 많은 bad sector를 만날 가능성이 큽니다. `addbadblock`과 `removebadblock` message로 새 위치를 자유롭게 추가·제거하고, `enable`과 `disable`로 구성된 bad block을 실제 bad로 취급할지 bypass할지 바꿀 수 있습니다. 따라서 test data와 metadata를 먼저 write한 뒤 bad sector가 나타나는 failure event를 simulation할 수 있습니다.
List 구성과 failure enable 상태를 분리하고 write 성공으로 sector remap을 흉내 냅니다.
Table parameter와 device 생성
34-85dm-dust table은 다음 세 parameter를 받습니다.
<device_path> <offset> <blksz>
Backing device, data offset과 emulation block 크기를 지정합니다.
먼저 사용할 device 크기를 512-byte sector 단위로 확인합니다.
$ sudo blockdev --getsz /dev/vdb1
33552384
512-byte block 크기의 `dust1` device는 다음처럼 만듭니다.
$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 512'
4096-byte block 크기를 사용하려면 마지막 값을 4096으로 지정합니다.
$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 4096'
`dmsetup status`에서 `bypass`는 모든 I/O가 underlying device로 통과함을 뜻합니다. `verbose`는 bad block 추가·제거·remap을 자세히 log한다는 뜻입니다. 초기 상태에서는 direct read와 write가 모두 성공합니다.
$ sudo dmsetup status dust1
0 33552384 dust 252:17 bypass verbose
$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=128 iflag=direct
128+0 records in
128+0 records out
$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
128+0 records in
128+0 records out
Bad block failure가 활성화되기 전에는 linear mapping처럼 동작합니다.
Bad block 추가, failure 활성화와 write remap
86-139Device의 bad-block emulation이 enabled이든 disabled이든 언제든 `addbadblock`과 `removebadblock` message로 bad block을 추가하거나 제거할 수 있습니다. 다음 예는 block 60, 67, 72를 추가합니다.
$ sudo dmsetup message dust1 0 addbadblock 60
kernel: device-mapper: dust: badblock added at block 60
$ sudo dmsetup message dust1 0 addbadblock 67
kernel: device-mapper: dust: badblock added at block 67
$ sudo dmsetup message dust1 0 addbadblock 72
kernel: device-mapper: dust: badblock added at block 72
추가한 block은 bad block list에 저장됩니다. Device가 `bypass` mode인 동안에는 read와 write가 성공합니다.
$ sudo dmsetup status dust1
0 33552384 dust 252:17 bypass
`enable` message를 보내 `fail read on bad block` 동작을 활성화합니다. Status는 `fail_read_on_bad_block`으로 바뀝니다.
$ sudo dmsetup message dust1 0 enable
kernel: device-mapper: dust: enabling read failures on bad sectors
$ sudo dmsetup status dust1
0 33552384 dust 252:17 fail_read_on_bad_block
이 mode에서 bad block 67을 direct read하면 `Input/output error`가 발생하고 0 byte가 copy됩니다.
$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=1 skip=67 iflag=direct
dd: error reading '/dev/mapper/dust1': Input/output error
0+0 records in
0+0 records out
0 bytes copied, 0.00040651 s, 0.0 kB/s
반대로 bad block에 write하면 write가 성공하고 해당 block을 bad block list에서 제거합니다. 다음 log는 block 60, 67, 72, 87이 write 때문에 제거된 결과를 보여 줍니다.
$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
128+0 records in
128+0 records out
kernel: device-mapper: dust: block 60 removed from badblocklist by write
kernel: device-mapper: dust: block 67 removed from badblocklist by write
kernel: device-mapper: dust: block 72 removed from badblocklist by write
kernel: device-mapper: dust: block 87 removed from badblocklist by write
같은 bad block도 operation에 따라 실패하거나 list에서 복구됩니다.
List에 추가한 block은 write 범위에 포함되면 remap된 것처럼 제거됩니다.
중복·누락 error와 block 수 조회
140-169이미 list에 있는 bad block을 다시 추가하면 `Invalid argument` error와 `already in badblocklist` message가 발생합니다.
$ sudo dmsetup message dust1 0 addbadblock 88
device-mapper: message ioctl on dust1 failed: Invalid argument
kernel: device-mapper: dust: block 88 already in badblocklist
List에 없는 bad block을 제거하려 해도 `Invalid argument` error와 `not found in badblocklist` message가 발생합니다.
$ sudo dmsetup message dust1 0 removebadblock 87
device-mapper: message ioctl on dust1 failed: Invalid argument
kernel: device-mapper: dust: block 87 not found in badblocklist
현재 device에 구성된 bad block 수는 `countbadblocks` message로 셉니다.
$ sudo dmsetup message dust1 0 countbadblocks
응답 message에는 현재 bad block 수가 표시됩니다.
countbadblocks: 895 badblock(s) found
List operation은 잘못된 중복·누락 요청을 명시적으로 거부합니다.
조회, 전체 삭제와 목록 출력
170-224특정 block이 bad block list에 있는지 확인하려면 `queryblock <blknum>`을 사용합니다.
$ sudo dmsetup message dust1 0 queryblock 72
Block이 list에 있으면 다음 message가 출력됩니다.
dust_query_block: block 72 found in badblocklist
List에 없으면 다음 message가 출력됩니다.
dust_query_block: block 72 not found in badblocklist
`queryblock`은 enabled와 disabled mode 모두에서 동작합니다. Device에 I/O를 보내거나 bad-block emulation을 enable하지 않고도 해당 block을 bad로 취급할지 확인할 수 있습니다.
각 block마다 `removebadblock`을 실행하지 않고 list 전체를 비우려면 `clearbadblocks`를 사용합니다.
$ sudo dmsetup message dust1 0 clearbadblocks
Bad block을 지우면 다음 message가 표시됩니다.
dust_clear_badblocks: badblocks cleared
지울 bad block이 없으면 별도 message가 표시됩니다.
dust_clear_badblocks: no badblocks found
`listbadblocks`는 bad block을 한 줄에 하나씩 출력합니다. 다음 예에는 block 1과 2가 있습니다.
$ sudo dmsetup message dust1 0 listbadblocks
1
2
List가 비어 있으면 command는 아무 출력 없이 끝납니다.
$ sudo dmsetup message dust1 0 listbadblocks
I/O를 일으키지 않고 list를 조회·정리할 수 있습니다.
Message command 목록과 제거
225-254Block number argument가 필요한 operation은 다음 세 가지입니다.
addbadblock <blknum>
queryblock <blknum>
removebadblock <blknum>
`<blknum>`은 device block 크기에 대응하는 device 범위 안의 block number여야 합니다.
Single-argument message command 목록은 다음과 같습니다.
countbadblocks
clearbadblocks
listbadblocks
disable
enable
quiet
List 조작, emulation 상태와 logging을 runtime에 제어합니다.
시험이 끝나면 `dmsetup remove`로 device를 제거합니다.
$ sudo dmsetup remove dust1
Quiet mode logging 제어
255-281Bad block이 많은 test에서는 block 추가·제거·write-remap log가 지나치게 많을 수 있습니다. `quiet` message로 quiet mode를 활성화할 수 있습니다.
$ sudo dmsetup message dust1 0 quiet
Quiet mode는 add, remove, write로 제거된 operation의 log를 억제합니다. `countbadblocks`와 `queryblock` message의 log는 quiet mode에서도 계속 출력됩니다.
`dmsetup status`에서 `quiet` 표시로 mode를 확인할 수 있습니다.
$ sudo dmsetup status dust1
0 33552384 dust 252:17 fail_read_on_bad_block quiet
`quiet` message를 다시 보내면 quiet mode를 끄는 toggle로 동작하며 status가 `verbose`로 돌아옵니다.
$ sudo dmsetup message dust1 0 quiet
$ sudo dmsetup status dust1
0 33552384 dust 252:17 fail_read_on_bad_block verbose
`verbose`가 있으면 정상 logging 상태입니다.
같은 message로 verbose와 quiet logging 상태를 전환합니다.
scsi_debug와 dm-flakey 대신 dm-dust
282-305`scsi_debug`에는 source code에 hardcode된 한 sector `0x1234`의 read를 실패시키는 `medium error` mode가 있습니다. 하지만 persistent storage로 RAM을 사용해 가능한 device 크기가 크게 줄어듭니다.
`dm-flakey`는 특정 시점이 아니라 지정된 시간 주기에 모든 block 위치의 모든 I/O를 실패시킵니다.
실제 hard disk의 bad sector는 read를 실패시키며 보통 EIO(`I/O error`) 또는 ENODATA(`No data available`)를 반환합니다. 그러나 그 sector에 write는 성공할 수 있고, controller가 더 이상 read error를 겪지 않거나 sector를 reallocate하면 다시 읽을 수 있게 됩니다. 이후 예측할 수 없는 다른 위치에 새 bad sector가 생길 수도 있습니다.
dm-dust는 system memory를 차지하지 않는 수십 GB 이상의 큰 storage device를 바탕으로, 알려진 sector 위치와 알려진 시점에 bad-sector 동작을 나타내는 device를 제공하려고 합니다.
위치·시점 제어, storage 규모와 write-remap 현실성을 비교합니다.
Bad-sector 상태 모델
dm-dust.rst:1-85Bad block list, bypass/failure 상태, block 크기와 initial device 생성 절차를 설명합니다.