dd conv=sync,noerror
(або conv=noerror,sync
) пошкоджує ваші дані.
Залежно від помилки вводу / виводу та використовуваного блоку (більший за розмір фізичного сектора?), Вхідні та вихідні адреси фактично не синхронізуються, а закінчуються неправильними зміщеннями, що робить копію марною для зображень файлової системи та інших речі, де компенсації мають значення.
Дуже багато місць рекомендують використовувати conv=noerror,sync
при роботі з поганими дисками. Я раніше давав таку ж рекомендацію. Це спрацювало для мене, коли мені довелося відновити поганий диск деякий час тому.
Однак тестування дозволяє припустити, що це насправді взагалі не є надійним.
Використання losetup
та dmsetup
створення A error B
пристрою:
truncate -s 1M a.img b.img
A=$(losetup --find --show a.img)
B=$(losetup --find --show b.img)
i=0 ; while printf "A%06d\n" $i ; do i=$((i+1)) ; done > $A
i=0 ; while printf "B%06d\n" $i ; do i=$((i+1)) ; done > $B
Пристрої циклу A, B виглядають так:
# head -n 3 $A $B
==> /dev/loop0 <==
A000000
A000001
A000002
==> /dev/loop1 <==
B000000
B000001
B000002
Отже, це A, B із збільшенням чисел, які допоможуть нам перевірити компенсації пізніше.
Тепер, щоб помістити помилку читання між двома, люб’язно надавши пристрою Linux пристрої:
# dmsetup create AerrorB << EOF
0 2000 linear $A 0
2000 96 error
2096 2000 linear $B 48
EOF
Цей приклад створює AerrorB
як у 2000
секторах A
, за ними 2*48
секторами помилок, а за ними 2000
секторами B
.
Просто для підтвердження:
# blockdev --getsz /dev/mapper/AerrorB
4096
# hexdump -C /dev/mapper/AerrorB
00000000 41 30 30 30 30 30 30 0a 41 30 30 30 30 30 31 0a |A000000.A000001.|
00000010 41 30 30 30 30 30 32 0a 41 30 30 30 30 30 33 0a |A000002.A000003.|
[...]
000f9fe0 41 31 32 37 39 39 36 0a 41 31 32 37 39 39 37 0a |A127996.A127997.|
000f9ff0 41 31 32 37 39 39 38 0a 41 31 32 37 39 39 39 0a |A127998.A127999.|
000fa000
hexdump: /dev/mapper/AerrorB: Input/output error
Так він читається до A127999\n
тих пір , оскільки кожен рядок має 8 байт, що становить 1024000 байт, що становить 2000 секторів у 512 байт. Здається, все в порядку ...
Чи змішаться?
for bs in 1M 64K 16K 4K 512 42
do
dd bs=$bs conv=noerror,sync if=/dev/mapper/AerrorB of=AerrorB.$bs.gnu-dd
busybox dd bs=$bs conv=noerror,sync if=/dev/mapper/AerrorB of=AerrorB.$bs.bb-dd
done
ddrescue /dev/mapper/AerrorB AerrorB.ddrescue
Результати:
# ls -l
-rw-r--r-- 1 root root 2113536 May 11 23:54 AerrorB.16K.bb-dd
-rw-r--r-- 1 root root 2064384 May 11 23:54 AerrorB.16K.gnu-dd
-rw-r--r-- 1 root root 3145728 May 11 23:54 AerrorB.1M.bb-dd
-rw-r--r-- 1 root root 2097152 May 11 23:54 AerrorB.1M.gnu-dd
-rw-r--r-- 1 root root 2097186 May 11 23:54 AerrorB.42.bb-dd
-rw-r--r-- 1 root root 2048004 May 11 23:54 AerrorB.42.gnu-dd
-rw-r--r-- 1 root root 2097152 May 11 23:54 AerrorB.4K.bb-dd
-rw-r--r-- 1 root root 2097152 May 11 23:54 AerrorB.4K.gnu-dd
-rw-r--r-- 1 root root 2097152 May 11 23:54 AerrorB.512.bb-dd
-rw-r--r-- 1 root root 2097152 May 11 23:54 AerrorB.512.gnu-dd
-rw-r--r-- 1 root root 2162688 May 11 23:54 AerrorB.64K.bb-dd
-rw-r--r-- 1 root root 2097152 May 11 23:54 AerrorB.64K.gnu-dd
-rw-r--r-- 1 root root 2097152 May 11 23:54 AerrorB.ddrescue
Тільки з розмірів файлів ви можете сказати, що в деяких блоках не так.
Контрольні суми:
# md5sum *
8972776e4bd29eb5a55aa4d1eb3b8a43 AerrorB.16K.bb-dd
4ee0b656ff9be862a7e96d37a2ebdeb0 AerrorB.16K.gnu-dd
7874ef3fe3426436f19ffa0635a53f63 AerrorB.1M.bb-dd
6f60e9d5ec06eb7721dbfddaaa625473 AerrorB.1M.gnu-dd
94abec9a526553c5aa063b0c917d8e8f AerrorB.42.bb-dd
1413c824cd090cba5c33b2d7de330339 AerrorB.42.gnu-dd
b381efd87f17354cfb121dae49e3487a AerrorB.4K.bb-dd
b381efd87f17354cfb121dae49e3487a AerrorB.4K.gnu-dd
b381efd87f17354cfb121dae49e3487a AerrorB.512.bb-dd
b381efd87f17354cfb121dae49e3487a AerrorB.512.gnu-dd
3c101af5623fe8c6f3d764631582a18e AerrorB.64K.bb-dd
6f60e9d5ec06eb7721dbfddaaa625473 AerrorB.64K.gnu-dd
b381efd87f17354cfb121dae49e3487a AerrorB.ddrescue
dd
погоджується ddrescue
лише з розмірами блоків, які, можливо, вирівняні до нашої зони помилок ( 512
, 4K
).
Давайте перевіримо необроблені дані.
# grep -a -b --only-matching B130000 *
AerrorB.16K.bb-dd: 2096768:B130000
AerrorB.16K.gnu-dd: 2047616:B130000
AerrorB.1M.bb-dd: 2113152:B130000
AerrorB.1M.gnu-dd: 2064000:B130000
AerrorB.42.bb-dd: 2088578:B130000
AerrorB.42.gnu-dd: 2039426:B130000
AerrorB.4K.bb-dd: 2088576:B130000
AerrorB.4K.gnu-dd: 2088576:B130000
AerrorB.512.bb-dd: 2088576:B130000
AerrorB.512.gnu-dd: 2088576:B130000
AerrorB.64K.bb-dd: 2113152:B130000
AerrorB.64K.gnu-dd: 2064000:B130000
AerrorB.ddrescue: 2088576:B130000
Хоча самі дані, здається, присутні, вони, очевидно, не синхронізовані; компенсації повністю не збиті для bs = 16K, 1M, 42,64K ... тільки ті, які мають зміщення, 2088576
є правильними, як це можна перевірити на оригінальному пристрої.
# dd bs=1 skip=2088576 count=8 if=/dev/mapper/AerrorB
B130000
Це очікувана поведінка dd conv=noerror,sync
? Я не знаю, і дві реалізовані в dd
мене доступні навіть не згодні між собою. Отриманий результат дуже марний, якщо ви використовували dd
вибір із ефективним блоком.
Вище була проведена з використанням dd (coreutils) 8.25
, BusyBox v1.24.2
, GNU ddrescue 1.21
.