ddrescue, "размер на диске" меньше общего размера, что может повлиять на производительность при записи в NTFS
Предыстория в моем предыдущем вопросе и мой собственный ответ на него.
В один момент у меня было два частичных изображения, созданные ddrescue
: один файл в файловой системе NTFS, а другой - в ext4.
Я заметил довольно рано в процессе, что "размер на диске" для обоих изображений был намного меньше, чем общий размер, указывая (если я не ошибаюсь), что эти файлы были записаны как "разреженные", т.е. данные фактически не были распределены по соответствующим томам, учитывались только те данные, которые уже были спасены. Но ни в коем случае я не использовал -S
включи мой ddrescue
команды, которые указывают, что выходной файл должен быть записан как "разреженный".
Примечание: то, что я сделал, использовало -R
переключатель ("реверс") в начале, предполагая, что он сразу выделит весь размер входного жесткого диска (идея заключалась в том, что это приведет к "более чистому" выводу, записывая все данные последовательно на принимающий раздел, поэтому чтобы сохранить целостность файла образа, даже если что-то пойдет не так с файловой системой, и мне придется восстановить восстановление…); он действительно увеличил отображаемый размер файла до 931,5 ГБ, но на самом деле "размер на диске" был увеличен только на тот небольшой объем данных, который был скопирован на этом этапе.
Таким образом, главный вопрос будет: как объяснить эту редкость? Почему ddrescue
копия не последовательная по умолчанию?
Затем, поскольку у меня было два частичных изображения, каждое из которых содержало некоторые действительные данные, отсутствующие в другом, я сделал следующее:
- Я попытался скопировать спасенные области из второго изображения в разделе ext4, отсутствующего в первом изображении, в это первое изображение в разделе NTFS, которое должно было быть очень быстрым, оба изображения находились на одном здоровом жестком диске емкостью 2 ТБ (Seagate). ST2000DX001 с максимальной скоростью записи, близкой к 200 МБ / с). Но оказалось, что это было очень медленно: всего 660 КБ / с.
- Поэтому я остановился и сделал наоборот: я сделал
ddrescue
скопируйте спасенные области из первого изображения (в NTFS), отсутствующего во втором изображении, во второе изображение (в ext4). И теперь я получил скорость копирования 43000 КБ / с или 43 МБ / с, что было значительно выше и ближе к нормальной скорости копирования на том же жестком диске этого класса и емкости.
Второй вопрос: может ли это странное поведение быть связано с проблемой производительности, с которой я столкнулся при записи в NTFS? Известно ли, что в драйвере Linux NTFS возникают проблемы с большими "разреженными" файлами?
2 ответа
Этот ответ исследует поведение ddrescue
ответить на главный вопрос. Если вы не заинтересованы в процедуре тестирования, то можете перейти к моим выводам и интерпретации ближе к концу.
Testbed
$ uname -a
Linux foo 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/issue
Ubuntu 14.04.5 LTS \n \l
$ ddrescue -V
GNU ddrescue 1.17
…
Файловая система btrfs; это не должно иметь значения, пока оно поддерживает разреженные файлы.
тестирование
Сначала я получил 8 МБ случайных данных:
dd if=/dev/urandom of=random.chunk bs=1M count=8
Затем я сделал это петлевое устройство и вспомнил его название:
loopdev=`sudo losetup -f --show random.chunk`
Затем я создал еще одно устройство, которое состояло из
- кусок 0: не читается, 1 МиБ
- кусок 1: нули, 2 МиБ
- кусок 2: не читается, 4 МиБ
- кусок 3: данные из
random.chunk
, 8 МиБ - кусок 4: не читается, 16 МиБ
Код (здесь используется синтаксис документа):
sudo dmsetup create mydevice << EOF
0 2048 error
2048 4096 zero
6144 8192 error
14336 16384 linear $loopdev 0
30720 32768 error
EOF
Я подтвердил с gdisk -l /dev/mapper/mydevice
что общий размер составляет 31 Мб, как и должно быть.
Фактическое чтение сделано с:
ddrescue /dev/mapper/mydevice normal.raw normal.log
ddrescue -R /dev/mapper/mydevice normalR.raw normalR.log
ddrescue -S /dev/mapper/mydevice sparse.raw sparse.log
ddrescue -RS /dev/mapper/mydevice sparseR.raw sparseR.log
И результаты ls -hls *.raw
являются
10M -rw-rw-r-- 1 kamil kamil 15M Sep 10 00:37 normal.raw
10M -rw-rw-r-- 1 kamil kamil 15M Sep 10 00:37 normalR.raw
8.0M -rw-rw-r-- 1 kamil kamil 15M Sep 10 00:37 sparse.raw
8.0M -rw-rw-r-- 1 kamil kamil 15M Sep 10 00:37 sparseR.raw
Конечно, я подтвердил cmp
что все четыре файла идентичны, когда вы их читаете. Четыре файла журнала содержали одну и ту же карту ошибочных и исправных секторов.
Заметить, что
- 15 МиБ означает, что последний кусок отсутствует;
- 10 MiB обозначает кусок 1 и кусок 3;
- 8 MiB указывает только блок 3.
очищающий
sudo dmsetup remove mydevice
sudo losetup -d $loopdev
unset loopdev
rm random.chunk normal.raw normal.log normalR.raw normalR.log sparse.raw sparse.log sparseR.raw sparseR.log
Выводы
- Когда дело доходит до размера файла, не имеет значения, читаете ли вы наоборот (
-R
) или нет. - Не читаемый кусок в самом конце входного файла не влияет на общий размер выходного файла.
- Непонятные фрагменты, которые вносят вклад в общий размер файла, всегда редки (если целевая файловая система, конечно, поддерживает это).
-
-S
опция влияет только на блоки нулей, которые были фактически прочитаны из входного файла.
интерпретация
Выше были факты. Этот раздел больше похож на мое мнение.
Кажется ddrescue
пытается сэкономить дисковое пространство всякий раз, когда он может сделать это без дополнительной работы. Когда вы используете -S
инструмент должен выполнить некоторые вычисления, чтобы проверить, являются ли данный блок данных всеми нулями. Если есть ошибка чтения, ему не нужно ничего вычислять, это может сделать фрагмент разреженным в выходном файле без затрат.
Решение
Вы написали:
с использованием
-R
переключатель ("реверс") в начале, предполагая, что он сразу выделит весь размер входного жесткого диска
Мы только что увидели, что это ложное предположение. На самом деле вы описали, что -p
делает. ddrescue -p
предварительно выделит место на диске для выходного файла. Когда я делал это во время моих тестов, выходной файл имел 31 МБ и не был разреженным (даже при -S
).
Я сделал другой тест самостоятельно.
- Я создал простой шаблон ddrescue log/map файл, содержащий это:
0x00000000 0x100000 ?
0x100000 0x3FE00000 +
0x3FF00000 0x100000 ?
(Это означает: в пределах одного ГБ данных всего первый и последний МБ не были опробованы, остальные считаются "спасенными".)
- Я запустил ddrescue с этим файлом журнала / карты, используя эту команду (с восстановленным образом из восстановления жесткого диска емкостью 1 ТБ в качестве входных данных, обрезав вывод в 1 ГБ):
ddrescue -s 1073741824 [rescued_image_file] [test1GB] [test1GB.log]
Полученный файл [test1GB] имеет общий размер 1 ГБ, как и ожидалось, но "размер на диске" 2 МБ, что означает, что были выделены только данные, которые были фактически скопированы (первый и последний МБ).
- Затем я запустил ddrescue с этим файлом размером 1 ГБ, на этот раз без шаблона, сначала без, а затем с ключом -S ("редкие записи").
ddrescue [test1GB] [test1GB-NS] [test1GB-NS.log]
ddrescue -S [test1GB] [test1GB-S] [test1GB-S.log]
И кажется, что:
- [test1GB-NS] (не разреженный) имеет "размер на диске" 1 ГБ - поэтому весь файл был выделен и скопирован, даже пустые сектора; в то время как...
- [test1GB-S] (sparse) имеет "размер на диске" всего 1,2 МБ или 1114112 байт - это означает, что пустые сектора не были выделены, даже те, которые содержатся в первом и последнем МБ.
Я думал, что "разреженность" была концепцией "все или ничего", как и сжатие файлов, но, очевидно, существует такая вещь, как "частично разреженный" файл, и действительно, ddrescue, похоже, экономит место таким образом, что обязательно преимущество (и может действительно повлиять на производительность); должен быть переключатель, чтобы он распределял полный размер выходного файла на лету (в отличие от предварительного выделения, которое может быть очень длинным, если вход большой), так же, как это делается (очевидно) при прямой записи на устройство или раздел.