mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
10 KiB
305 lines
10 KiB
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).
|
|
|