1*4882a593Smuzhiyundm-dust 2*4882a593Smuzhiyun======= 3*4882a593Smuzhiyun 4*4882a593SmuzhiyunThis target emulates the behavior of bad sectors at arbitrary 5*4882a593Smuzhiyunlocations, and the ability to enable the emulation of the failures 6*4882a593Smuzhiyunat an arbitrary time. 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunThis target behaves similarly to a linear target. At a given time, 9*4882a593Smuzhiyunthe user can send a message to the target to start failing read 10*4882a593Smuzhiyunrequests on specific blocks (to emulate the behavior of a hard disk 11*4882a593Smuzhiyundrive with bad sectors). 12*4882a593Smuzhiyun 13*4882a593SmuzhiyunWhen the failure behavior is enabled (i.e.: when the output of 14*4882a593Smuzhiyun"dmsetup status" displays "fail_read_on_bad_block"), reads of blocks 15*4882a593Smuzhiyunin the "bad block list" will fail with EIO ("Input/output error"). 16*4882a593Smuzhiyun 17*4882a593SmuzhiyunWrites of blocks in the "bad block list will result in the following: 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun1. Remove the block from the "bad block list". 20*4882a593Smuzhiyun2. Successfully complete the write. 21*4882a593Smuzhiyun 22*4882a593SmuzhiyunThis emulates the "remapped sector" behavior of a drive with bad 23*4882a593Smuzhiyunsectors. 24*4882a593Smuzhiyun 25*4882a593SmuzhiyunNormally, a drive that is encountering bad sectors will most likely 26*4882a593Smuzhiyunencounter more bad sectors, at an unknown time or location. 27*4882a593SmuzhiyunWith dm-dust, the user can use the "addbadblock" and "removebadblock" 28*4882a593Smuzhiyunmessages to add arbitrary bad blocks at new locations, and the 29*4882a593Smuzhiyun"enable" and "disable" messages to modulate the state of whether the 30*4882a593Smuzhiyunconfigured "bad blocks" will be treated as bad, or bypassed. 31*4882a593SmuzhiyunThis allows the pre-writing of test data and metadata prior to 32*4882a593Smuzhiyunsimulating a "failure" event where bad sectors start to appear. 33*4882a593Smuzhiyun 34*4882a593SmuzhiyunTable parameters 35*4882a593Smuzhiyun---------------- 36*4882a593Smuzhiyun<device_path> <offset> <blksz> 37*4882a593Smuzhiyun 38*4882a593SmuzhiyunMandatory parameters: 39*4882a593Smuzhiyun <device_path>: 40*4882a593Smuzhiyun Path to the block device. 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun <offset>: 43*4882a593Smuzhiyun Offset to data area from start of device_path 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun <blksz>: 46*4882a593Smuzhiyun Block size in bytes 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun (minimum 512, maximum 1073741824, must be a power of 2) 49*4882a593Smuzhiyun 50*4882a593SmuzhiyunUsage instructions 51*4882a593Smuzhiyun------------------ 52*4882a593Smuzhiyun 53*4882a593SmuzhiyunFirst, find the size (in 512-byte sectors) of the device to be used:: 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun $ sudo blockdev --getsz /dev/vdb1 56*4882a593Smuzhiyun 33552384 57*4882a593Smuzhiyun 58*4882a593SmuzhiyunCreate the dm-dust device: 59*4882a593Smuzhiyun(For a device with a block size of 512 bytes) 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun:: 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun $ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 512' 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun(For a device with a block size of 4096 bytes) 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun:: 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun $ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 4096' 70*4882a593Smuzhiyun 71*4882a593SmuzhiyunCheck the status of the read behavior ("bypass" indicates that all I/O 72*4882a593Smuzhiyunwill be passed through to the underlying device; "verbose" indicates that 73*4882a593Smuzhiyunbad block additions, removals, and remaps will be verbosely logged):: 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun $ sudo dmsetup status dust1 76*4882a593Smuzhiyun 0 33552384 dust 252:17 bypass verbose 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun $ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=128 iflag=direct 79*4882a593Smuzhiyun 128+0 records in 80*4882a593Smuzhiyun 128+0 records out 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun $ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct 83*4882a593Smuzhiyun 128+0 records in 84*4882a593Smuzhiyun 128+0 records out 85*4882a593Smuzhiyun 86*4882a593SmuzhiyunAdding and removing bad blocks 87*4882a593Smuzhiyun------------------------------ 88*4882a593Smuzhiyun 89*4882a593SmuzhiyunAt any time (i.e.: whether the device has the "bad block" emulation 90*4882a593Smuzhiyunenabled or disabled), bad blocks may be added or removed from the 91*4882a593Smuzhiyundevice via the "addbadblock" and "removebadblock" messages:: 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 addbadblock 60 94*4882a593Smuzhiyun kernel: device-mapper: dust: badblock added at block 60 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 addbadblock 67 97*4882a593Smuzhiyun kernel: device-mapper: dust: badblock added at block 67 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 addbadblock 72 100*4882a593Smuzhiyun kernel: device-mapper: dust: badblock added at block 72 101*4882a593Smuzhiyun 102*4882a593SmuzhiyunThese bad blocks will be stored in the "bad block list". 103*4882a593SmuzhiyunWhile the device is in "bypass" mode, reads and writes will succeed:: 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun $ sudo dmsetup status dust1 106*4882a593Smuzhiyun 0 33552384 dust 252:17 bypass 107*4882a593Smuzhiyun 108*4882a593SmuzhiyunEnabling block read failures 109*4882a593Smuzhiyun---------------------------- 110*4882a593Smuzhiyun 111*4882a593SmuzhiyunTo enable the "fail read on bad block" behavior, send the "enable" message:: 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 enable 114*4882a593Smuzhiyun kernel: device-mapper: dust: enabling read failures on bad sectors 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun $ sudo dmsetup status dust1 117*4882a593Smuzhiyun 0 33552384 dust 252:17 fail_read_on_bad_block 118*4882a593Smuzhiyun 119*4882a593SmuzhiyunWith the device in "fail read on bad block" mode, attempting to read a 120*4882a593Smuzhiyunblock will encounter an "Input/output error":: 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun $ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=1 skip=67 iflag=direct 123*4882a593Smuzhiyun dd: error reading '/dev/mapper/dust1': Input/output error 124*4882a593Smuzhiyun 0+0 records in 125*4882a593Smuzhiyun 0+0 records out 126*4882a593Smuzhiyun 0 bytes copied, 0.00040651 s, 0.0 kB/s 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun...and writing to the bad blocks will remove the blocks from the list, 129*4882a593Smuzhiyuntherefore emulating the "remap" behavior of hard disk drives:: 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun $ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct 132*4882a593Smuzhiyun 128+0 records in 133*4882a593Smuzhiyun 128+0 records out 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun kernel: device-mapper: dust: block 60 removed from badblocklist by write 136*4882a593Smuzhiyun kernel: device-mapper: dust: block 67 removed from badblocklist by write 137*4882a593Smuzhiyun kernel: device-mapper: dust: block 72 removed from badblocklist by write 138*4882a593Smuzhiyun kernel: device-mapper: dust: block 87 removed from badblocklist by write 139*4882a593Smuzhiyun 140*4882a593SmuzhiyunBad block add/remove error handling 141*4882a593Smuzhiyun----------------------------------- 142*4882a593Smuzhiyun 143*4882a593SmuzhiyunAttempting to add a bad block that already exists in the list will 144*4882a593Smuzhiyunresult in an "Invalid argument" error, as well as a helpful message:: 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 addbadblock 88 147*4882a593Smuzhiyun device-mapper: message ioctl on dust1 failed: Invalid argument 148*4882a593Smuzhiyun kernel: device-mapper: dust: block 88 already in badblocklist 149*4882a593Smuzhiyun 150*4882a593SmuzhiyunAttempting to remove a bad block that doesn't exist in the list will 151*4882a593Smuzhiyunresult in an "Invalid argument" error, as well as a helpful message:: 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 removebadblock 87 154*4882a593Smuzhiyun device-mapper: message ioctl on dust1 failed: Invalid argument 155*4882a593Smuzhiyun kernel: device-mapper: dust: block 87 not found in badblocklist 156*4882a593Smuzhiyun 157*4882a593SmuzhiyunCounting the number of bad blocks in the bad block list 158*4882a593Smuzhiyun------------------------------------------------------- 159*4882a593Smuzhiyun 160*4882a593SmuzhiyunTo count the number of bad blocks configured in the device, run the 161*4882a593Smuzhiyunfollowing message command:: 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 countbadblocks 164*4882a593Smuzhiyun 165*4882a593SmuzhiyunA message will print with the number of bad blocks currently 166*4882a593Smuzhiyunconfigured on the device:: 167*4882a593Smuzhiyun 168*4882a593Smuzhiyun countbadblocks: 895 badblock(s) found 169*4882a593Smuzhiyun 170*4882a593SmuzhiyunQuerying for specific bad blocks 171*4882a593Smuzhiyun-------------------------------- 172*4882a593Smuzhiyun 173*4882a593SmuzhiyunTo find out if a specific block is in the bad block list, run the 174*4882a593Smuzhiyunfollowing message command:: 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 queryblock 72 177*4882a593Smuzhiyun 178*4882a593SmuzhiyunThe following message will print if the block is in the list:: 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun dust_query_block: block 72 found in badblocklist 181*4882a593Smuzhiyun 182*4882a593SmuzhiyunThe following message will print if the block is not in the list:: 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun dust_query_block: block 72 not found in badblocklist 185*4882a593Smuzhiyun 186*4882a593SmuzhiyunThe "queryblock" message command will work in both the "enabled" 187*4882a593Smuzhiyunand "disabled" modes, allowing the verification of whether a block 188*4882a593Smuzhiyunwill be treated as "bad" without having to issue I/O to the device, 189*4882a593Smuzhiyunor having to "enable" the bad block emulation. 190*4882a593Smuzhiyun 191*4882a593SmuzhiyunClearing the bad block list 192*4882a593Smuzhiyun--------------------------- 193*4882a593Smuzhiyun 194*4882a593SmuzhiyunTo clear the bad block list (without needing to individually run 195*4882a593Smuzhiyuna "removebadblock" message command for every block), run the 196*4882a593Smuzhiyunfollowing message command:: 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 clearbadblocks 199*4882a593Smuzhiyun 200*4882a593SmuzhiyunAfter clearing the bad block list, the following message will appear:: 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun dust_clear_badblocks: badblocks cleared 203*4882a593Smuzhiyun 204*4882a593SmuzhiyunIf there were no bad blocks to clear, the following message will 205*4882a593Smuzhiyunappear:: 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun dust_clear_badblocks: no badblocks found 208*4882a593Smuzhiyun 209*4882a593SmuzhiyunListing the bad block list 210*4882a593Smuzhiyun-------------------------- 211*4882a593Smuzhiyun 212*4882a593SmuzhiyunTo list all bad blocks in the bad block list (using an example device 213*4882a593Smuzhiyunwith blocks 1 and 2 in the bad block list), run the following message 214*4882a593Smuzhiyuncommand:: 215*4882a593Smuzhiyun 216*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 listbadblocks 217*4882a593Smuzhiyun 1 218*4882a593Smuzhiyun 2 219*4882a593Smuzhiyun 220*4882a593SmuzhiyunIf there are no bad blocks in the bad block list, the command will 221*4882a593Smuzhiyunexecute with no output:: 222*4882a593Smuzhiyun 223*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 listbadblocks 224*4882a593Smuzhiyun 225*4882a593SmuzhiyunMessage commands list 226*4882a593Smuzhiyun--------------------- 227*4882a593Smuzhiyun 228*4882a593SmuzhiyunBelow is a list of the messages that can be sent to a dust device: 229*4882a593Smuzhiyun 230*4882a593SmuzhiyunOperations on blocks (requires a <blknum> argument):: 231*4882a593Smuzhiyun 232*4882a593Smuzhiyun addbadblock <blknum> 233*4882a593Smuzhiyun queryblock <blknum> 234*4882a593Smuzhiyun removebadblock <blknum> 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun...where <blknum> is a block number within range of the device 237*4882a593Smuzhiyun(corresponding to the block size of the device.) 238*4882a593Smuzhiyun 239*4882a593SmuzhiyunSingle argument message commands:: 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun countbadblocks 242*4882a593Smuzhiyun clearbadblocks 243*4882a593Smuzhiyun listbadblocks 244*4882a593Smuzhiyun disable 245*4882a593Smuzhiyun enable 246*4882a593Smuzhiyun quiet 247*4882a593Smuzhiyun 248*4882a593SmuzhiyunDevice removal 249*4882a593Smuzhiyun-------------- 250*4882a593Smuzhiyun 251*4882a593SmuzhiyunWhen finished, remove the device via the "dmsetup remove" command:: 252*4882a593Smuzhiyun 253*4882a593Smuzhiyun $ sudo dmsetup remove dust1 254*4882a593Smuzhiyun 255*4882a593SmuzhiyunQuiet mode 256*4882a593Smuzhiyun---------- 257*4882a593Smuzhiyun 258*4882a593SmuzhiyunOn test runs with many bad blocks, it may be desirable to avoid 259*4882a593Smuzhiyunexcessive logging (from bad blocks added, removed, or "remapped"). 260*4882a593SmuzhiyunThis can be done by enabling "quiet mode" via the following message:: 261*4882a593Smuzhiyun 262*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 quiet 263*4882a593Smuzhiyun 264*4882a593SmuzhiyunThis will suppress log messages from add / remove / removed by write 265*4882a593Smuzhiyunoperations. Log messages from "countbadblocks" or "queryblock" 266*4882a593Smuzhiyunmessage commands will still print in quiet mode. 267*4882a593Smuzhiyun 268*4882a593SmuzhiyunThe status of quiet mode can be seen by running "dmsetup status":: 269*4882a593Smuzhiyun 270*4882a593Smuzhiyun $ sudo dmsetup status dust1 271*4882a593Smuzhiyun 0 33552384 dust 252:17 fail_read_on_bad_block quiet 272*4882a593Smuzhiyun 273*4882a593SmuzhiyunTo disable quiet mode, send the "quiet" message again:: 274*4882a593Smuzhiyun 275*4882a593Smuzhiyun $ sudo dmsetup message dust1 0 quiet 276*4882a593Smuzhiyun 277*4882a593Smuzhiyun $ sudo dmsetup status dust1 278*4882a593Smuzhiyun 0 33552384 dust 252:17 fail_read_on_bad_block verbose 279*4882a593Smuzhiyun 280*4882a593Smuzhiyun(The presence of "verbose" indicates normal logging.) 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun"Why not...?" 283*4882a593Smuzhiyun------------- 284*4882a593Smuzhiyun 285*4882a593Smuzhiyunscsi_debug has a "medium error" mode that can fail reads on one 286*4882a593Smuzhiyunspecified sector (sector 0x1234, hardcoded in the source code), but 287*4882a593Smuzhiyunit uses RAM for the persistent storage, which drastically decreases 288*4882a593Smuzhiyunthe potential device size. 289*4882a593Smuzhiyun 290*4882a593Smuzhiyundm-flakey fails all I/O from all block locations at a specified time 291*4882a593Smuzhiyunfrequency, and not a given point in time. 292*4882a593Smuzhiyun 293*4882a593SmuzhiyunWhen a bad sector occurs on a hard disk drive, reads to that sector 294*4882a593Smuzhiyunare failed by the device, usually resulting in an error code of EIO 295*4882a593Smuzhiyun("I/O error") or ENODATA ("No data available"). However, a write to 296*4882a593Smuzhiyunthe sector may succeed, and result in the sector becoming readable 297*4882a593Smuzhiyunafter the device controller no longer experiences errors reading the 298*4882a593Smuzhiyunsector (or after a reallocation of the sector). However, there may 299*4882a593Smuzhiyunbe bad sectors that occur on the device in the future, in a different, 300*4882a593Smuzhiyununpredictable location. 301*4882a593Smuzhiyun 302*4882a593SmuzhiyunThis target seeks to provide a device that can exhibit the behavior 303*4882a593Smuzhiyunof a bad sector at a known sector location, at a known time, based 304*4882a593Smuzhiyunon a large storage device (at least tens of gigabytes, not occupying 305*4882a593Smuzhiyunsystem memory). 306