1dm-dust
2=======
3
4This target emulates the behavior of bad sectors at arbitrary
5locations, and the ability to enable the emulation of the failures
6at an arbitrary time.
7
8This target behaves similarly to a linear target.  At a given time,
9the user can send a message to the target to start failing read
10requests on specific blocks (to emulate the behavior of a hard disk
11drive with bad sectors).
12
13When the failure behavior is enabled (i.e.: when the output of
14"dmsetup status" displays "fail_read_on_bad_block"), reads of blocks
15in the "bad block list" will fail with EIO ("Input/output error").
16
17Writes of blocks in the "bad block list will result in the following:
18
191. Remove the block from the "bad block list".
202. Successfully complete the write.
21
22This emulates the "remapped sector" behavior of a drive with bad
23sectors.
24
25Normally, a drive that is encountering bad sectors will most likely
26encounter more bad sectors, at an unknown time or location.
27With dm-dust, the user can use the "addbadblock" and "removebadblock"
28messages to add arbitrary bad blocks at new locations, and the
29"enable" and "disable" messages to modulate the state of whether the
30configured "bad blocks" will be treated as bad, or bypassed.
31This allows the pre-writing of test data and metadata prior to
32simulating a "failure" event where bad sectors start to appear.
33
34Table parameters:
35-----------------
36<device_path> <offset> <blksz>
37
38Mandatory parameters:
39    <device_path>: path to the block device.
40    <offset>: offset to data area from start of device_path
41    <blksz>: block size in bytes
42	     (minimum 512, maximum 1073741824, must be a power of 2)
43
44Usage instructions:
45-------------------
46
47First, find the size (in 512-byte sectors) of the device to be used:
48
49$ sudo blockdev --getsz /dev/vdb1
5033552384
51
52Create the dm-dust device:
53(For a device with a block size of 512 bytes)
54$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 512'
55
56(For a device with a block size of 4096 bytes)
57$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 4096'
58
59Check the status of the read behavior ("bypass" indicates that all I/O
60will be passed through to the underlying device):
61$ sudo dmsetup status dust1
620 33552384 dust 252:17 bypass
63
64$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=128 iflag=direct
65128+0 records in
66128+0 records out
67
68$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
69128+0 records in
70128+0 records out
71
72Adding and removing bad blocks:
73-------------------------------
74
75At any time (i.e.: whether the device has the "bad block" emulation
76enabled or disabled), bad blocks may be added or removed from the
77device via the "addbadblock" and "removebadblock" messages:
78
79$ sudo dmsetup message dust1 0 addbadblock 60
80kernel: device-mapper: dust: badblock added at block 60
81
82$ sudo dmsetup message dust1 0 addbadblock 67
83kernel: device-mapper: dust: badblock added at block 67
84
85$ sudo dmsetup message dust1 0 addbadblock 72
86kernel: device-mapper: dust: badblock added at block 72
87
88These bad blocks will be stored in the "bad block list".
89While the device is in "bypass" mode, reads and writes will succeed:
90
91$ sudo dmsetup status dust1
920 33552384 dust 252:17 bypass
93
94Enabling block read failures:
95-----------------------------
96
97To enable the "fail read on bad block" behavior, send the "enable" message:
98
99$ sudo dmsetup message dust1 0 enable
100kernel: device-mapper: dust: enabling read failures on bad sectors
101
102$ sudo dmsetup status dust1
1030 33552384 dust 252:17 fail_read_on_bad_block
104
105With the device in "fail read on bad block" mode, attempting to read a
106block will encounter an "Input/output error":
107
108$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=1 skip=67 iflag=direct
109dd: error reading '/dev/mapper/dust1': Input/output error
1100+0 records in
1110+0 records out
1120 bytes copied, 0.00040651 s, 0.0 kB/s
113
114...and writing to the bad blocks will remove the blocks from the list,
115therefore emulating the "remap" behavior of hard disk drives:
116
117$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
118128+0 records in
119128+0 records out
120
121kernel: device-mapper: dust: block 60 removed from badblocklist by write
122kernel: device-mapper: dust: block 67 removed from badblocklist by write
123kernel: device-mapper: dust: block 72 removed from badblocklist by write
124kernel: device-mapper: dust: block 87 removed from badblocklist by write
125
126Bad block add/remove error handling:
127------------------------------------
128
129Attempting to add a bad block that already exists in the list will
130result in an "Invalid argument" error, as well as a helpful message:
131
132$ sudo dmsetup message dust1 0 addbadblock 88
133device-mapper: message ioctl on dust1  failed: Invalid argument
134kernel: device-mapper: dust: block 88 already in badblocklist
135
136Attempting to remove a bad block that doesn't exist in the list will
137result in an "Invalid argument" error, as well as a helpful message:
138
139$ sudo dmsetup message dust1 0 removebadblock 87
140device-mapper: message ioctl on dust1  failed: Invalid argument
141kernel: device-mapper: dust: block 87 not found in badblocklist
142
143Counting the number of bad blocks in the bad block list:
144--------------------------------------------------------
145
146To count the number of bad blocks configured in the device, run the
147following message command:
148
149$ sudo dmsetup message dust1 0 countbadblocks
150
151A message will print with the number of bad blocks currently
152configured on the device:
153
154kernel: device-mapper: dust: countbadblocks: 895 badblock(s) found
155
156Querying for specific bad blocks:
157---------------------------------
158
159To find out if a specific block is in the bad block list, run the
160following message command:
161
162$ sudo dmsetup message dust1 0 queryblock 72
163
164The following message will print if the block is in the list:
165device-mapper: dust: queryblock: block 72 found in badblocklist
166
167The following message will print if the block is in the list:
168device-mapper: dust: queryblock: block 72 not found in badblocklist
169
170The "queryblock" message command will work in both the "enabled"
171and "disabled" modes, allowing the verification of whether a block
172will be treated as "bad" without having to issue I/O to the device,
173or having to "enable" the bad block emulation.
174
175Clearing the bad block list:
176----------------------------
177
178To clear the bad block list (without needing to individually run
179a "removebadblock" message command for every block), run the
180following message command:
181
182$ sudo dmsetup message dust1 0 clearbadblocks
183
184After clearing the bad block list, the following message will appear:
185
186kernel: device-mapper: dust: clearbadblocks: badblocks cleared
187
188If there were no bad blocks to clear, the following message will
189appear:
190
191kernel: device-mapper: dust: clearbadblocks: no badblocks found
192
193Message commands list:
194----------------------
195
196Below is a list of the messages that can be sent to a dust device:
197
198Operations on blocks (requires a <blknum> argument):
199
200addbadblock <blknum>
201queryblock <blknum>
202removebadblock <blknum>
203
204...where <blknum> is a block number within range of the device
205  (corresponding to the block size of the device.)
206
207Single argument message commands:
208
209countbadblocks
210clearbadblocks
211disable
212enable
213quiet
214
215Device removal:
216---------------
217
218When finished, remove the device via the "dmsetup remove" command:
219
220$ sudo dmsetup remove dust1
221
222Quiet mode:
223-----------
224
225On test runs with many bad blocks, it may be desirable to avoid
226excessive logging (from bad blocks added, removed, or "remapped").
227This can be done by enabling "quiet mode" via the following message:
228
229$ sudo dmsetup message dust1 0 quiet
230
231This will suppress log messages from add / remove / removed by write
232operations.  Log messages from "countbadblocks" or "queryblock"
233message commands will still print in quiet mode.
234
235The status of quiet mode can be seen by running "dmsetup status":
236
237$ sudo dmsetup status dust1
2380 33552384 dust 252:17 fail_read_on_bad_block quiet
239
240To disable quiet mode, send the "quiet" message again:
241
242$ sudo dmsetup message dust1 0 quiet
243
244$ sudo dmsetup status dust1
2450 33552384 dust 252:17 fail_read_on_bad_block verbose
246
247(The presence of "verbose" indicates normal logging.)
248
249"Why not...?"
250-------------
251
252scsi_debug has a "medium error" mode that can fail reads on one
253specified sector (sector 0x1234, hardcoded in the source code), but
254it uses RAM for the persistent storage, which drastically decreases
255the potential device size.
256
257dm-flakey fails all I/O from all block locations at a specified time
258frequency, and not a given point in time.
259
260When a bad sector occurs on a hard disk drive, reads to that sector
261are failed by the device, usually resulting in an error code of EIO
262("I/O error") or ENODATA ("No data available").  However, a write to
263the sector may succeed, and result in the sector becoming readable
264after the device controller no longer experiences errors reading the
265sector (or after a reallocation of the sector).  However, there may
266be bad sectors that occur on the device in the future, in a different,
267unpredictable location.
268
269This target seeks to provide a device that can exhibit the behavior
270of a bad sector at a known sector location, at a known time, based
271on a large storage device (at least tens of gigabytes, not occupying
272system memory).
273