I'm considering backing up some data to DVDs/BDs. (I know about DVDisaster.) I've read somewhere that the outer sectors on a DVD are more likely to wear down than the inner ones. This suggests that over time, the blocks in the second half of an image are more likely to be corrupted than those in the first half. So my question is, is there a way to write the same data to 2 DVD images, such that
- one can mount either DVD, possibly in 2 steps (eg mount an iso file stored on the DVD), but without copying everything to HD first and manipulating it
- the main data should be written to the 2 DVDs in significantly different order
If I'm not being clear, here is what a possible solution could be.
Suppose for a second there existed a linux driver that could mount an iso image backwards. So, I give it an iso file, and when it wants the 1st sector, it reads the last 2048 bytes of the file backwards, instead of the first 2048 bytes in normal order. I don't know if such a driver exists, but if it did, it would be one solution to my problem because I could do this: put my data in an iso image; compute a second image as the first one backwards; encapsulate each image into a simple UDF filesystem with only one file; write the two UDF filesystems to different DVDs. Now, when I plug in either DVD, I could just mount the single iso file to get back my data. Furthermore, the data would be written to the 2 DVDs in different ways, so if both DVDs each lose the last 1/3 of their sectors, I could still retrieve it all (by hand, but it would be possible).
Other possible solutions would be a general driver to permute/rotate/reorder arbitrary-size blocks in an arbitrary block device. Or perhaps, is there a way to store a file in a UDF file system using a specific order of sectors? Given that UDF is a full-fledged file system, that is definitely possible, but is there a tool to do it?
Thanks!!
Edit: As I explained under the first reply, I don't mean to replace DVDisaster, but to complement it. Consider 2 strategies for backing up 4G of data. Strategy A: use 2 identical DVDs, each with 15% ecc from DVDisaster. Strategy B: use 2 DVDs, each with 15% ecc, but with the additional permutation thing I mention above (on 1 of the 2 DVDs). I claim that because of the wear patterns of DVDs (specifically, the correlation of errors), after a certain time, the probability of full recovery from B is significantly larger than from A (all other things being equal).
Edit2: To substantiate my claim that DVDisaster isn't a cure for everything, here is a script demonstrating how DVDisaster with 33% ECC data suffers data loss with only 1.3% corruption. The apparent contradiction is that 33% only applies to the "best case" corruption, not to "any" corruption. FYI, I'm creating a file spanning the entire filesystem in test.1.udf
, changing only the last sector in the file to zero in test.2.udf
, computing ecc data for both, and comparing the sectors, including the ecc data. The point is that if test.1.udf
is your data and you lose the sectors that are different and only those, you cannot possibly recover test.1.udf
because test.2.udf
is another possibility.
n_blocks=8192
tdir=$(mktemp -d)
mkudffs -b 2048 test.1.udf $n_blocks
sudo mount test.1.udf $tdir -o bs=2048
sudo chown $USER.$USER $tdir
n=$(df -B 2K $tdir | tail -n 1 | awk '{print $4}')
let n-=1
dd if=/dev/urandom of=$tdir/file bs=2K count=$n 2>/dev/null
last=$(od <$tdir/file -Ad -t x1 | tail -n 2 | head -n 1 | cut -d ' ' -f 2-)
sudo umount $tdir
start_of_last_block=$(od <test.1.udf -Ad -t x1 | grep -A 1 "$last" | tail -n 1 | awk '{print $1}')
last_block=$(($start_of_last_block / 2048))
dd if=test.1.udf bs=2K count=$(($last_block - 1)) >test.2.udf 2>/dev/null
dd if=/dev/zero bs=2K count=1 >>test.2.udf 2>/dev/null
dd if=test.1.udf bs=2K skip=$last_block count=$(($n_blocks - $last_block)) >>test.2.udf 2>/dev/null
n_blocks_with_ecc=$(echo "$n_blocks * 133 / 100" | bc)
echo "add dvdisaster ecc data, using in total $n_blocks_with_ecc"
#run dvdisaster on the 2 files, then...
n_blocks_different=$(for i in $(seq 0 $(($n_blocks_with_ecc - 1))); do
if [ $((($i / 100) * 100)) -eq $i ]; then
echo "$i..." >&2
fi
diff -q <(dd if=test.1.udf bs=2K skip=$i count=1 2>/dev/null) \
<(dd if=test.2.udf bs=2K skip=$i count=1 2>/dev/null) >/dev/null || echo $i
done | wc -l)
echo "number of blocks different: $n_blocks_different / $n_blocks_with_ecc ($(echo "scale=6; $n_blocks_different / $n_blocks_with_ecc * 100" | bc)%)"
Output:
number of blocks different: 145 / 10895 (1.330800%)