I would like to test some disk rescue methods before applying them in real life, in particular the ability for ddrescue to restore bad blocks from several disk copies, assuming one bad block is not bad in every copy.

As devices are represented by files under Linux, I think it would be possible to mark bad blocks in a file. Say I have created a reference file and two copies like here:

dd if=/dev/random of=/tmp/file bs=1024 count=32768
cp /tmp/file /tmp/file1
cp /tmp/file /tmp/file2

How do I emulate bad blocks in file1 and file2 as if they were device files?

Solutions here, here by Kamil Maciorowski and here are a good path to the solution, but do not provide a complete method for my use case


Thanks to the suggestions from Kamil Maciorowski and his answers elsewhere, I could build the following process and test it:

1) create a test file and compute its hash to check future recovery

dd if=/dev/urandom of=/tmp/file bs=512 count=32768 status=progress
sha256sum /tmp/file
f90c19308f9f216bf7dece09dd849eb40e97cdef86c6c37f28fbaf9a7bd07503  /tmp/file

2) Create a device with it

loopdev=\`losetup -f --show /tmp/file\`
echo $loopdev

3) Create corrupted devices with bad blocks thanks to devicemapper

dmsetup create file1 << EOF
    0  2048 linear $loopdev 0
 2048  4096 error
 6144  26624 linear $loopdev 6144

dmsetup create file2 << EOF
    0  30720 linear $loopdev 0
 30720  2048 error

ls -l /dev/mapper/
lrwxrwxrwx 1 root root       7 mai   30 09:27 file1 -> ../dm-2
lrwxrwxrwx 1 root root       7 mai   30 09:27 file2 -> ../dm-3

Notice that in each line, the first number is the position and second one the size, so in the last one, the sum is the size of the file : 6144 + 26624 = 32768, and 30720 + 2048 = 32768

The line 6144 26624 linear $loopdev 6144 means: copy device $loopdev from offset 6144 (in bytes) to file1 at offset 6144 (in bytes) and for a size of 26624 bytes.

4) Check i/o errors at expected locations

dd if=/dev/mapper/file1 of=/dev/null count=2048
dd if=/dev/mapper/file1 of=/dev/null count=2049
dd: error reading '/dev/mapper/file1': Input/output error
dd if=/dev/mapper/file2 of=/dev/null count=30720
dd if=/dev/mapper/file2 of=/dev/null count=30721
dd: error reading '/dev/mapper/file2': Input/output error

At this stage, the OP question is answered. Let's go further to finish the test:

5) test ddrescue : good blocks only

ddrescue -B -v -n /dev/mapper/file1 /tmp/file1 /tmp/log
percent rescued:  87.50%
sha256sum /tmp/file1
0d344253f69688e23dd4558c2ffdabb0325f85848f7e65788ea5c9441e7a700c  /tmp/file1

6) Repair successfully bad blocks with the second copy

ddrescue -B -v -c 16 -r 2 /dev/mapper/file2 /tmp/file1 /tmp/log
percent rescued: 100.00%
sha256sum /tmp/file1
f90c19308f9f216bf7dece09dd849eb40e97cdef86c6c37f28fbaf9a7bd07503  /tmp/file1

7) If required (not 100%), try to rescue bad blocks with the 1st copy

ddrescue -B -v -c 16 -r 2 /dev/mapper/file1 /tmp/file1 /tmp/log

8) Cleanup

dmsetup remove file1
dmsetup remove file2
unset loopdev
rm /tmp/file* /tmp/log

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.