Предыстория в моем предыдущем вопросе и мой собственный ответ на него.

В один момент у меня было два частичных образа, созданных ddrescue: один файл в файловой системе NTFS, а другой в ext4.

Я заметил довольно рано в процессе, что «размер на диске» для обоих изображений был намного меньше, чем общий размер, указывая (если я не ошибаюсь), что эти файлы были записаны как «разреженные», то есть, что пустой данные фактически не были распределены по соответствующим томам, учитывались только те данные, которые уже были спасены. Но я ни разу не использовал ключ -S в моих командах ddrescue , который указывает, что выходной файл должен быть записан как «разреженный».

Примечание: в начале я использовал ключ -R («реверс»), предполагая, что он сразу выделит весь размер входного жесткого диска (идея заключалась в том, что это приведет к «более чистому» выводу, запись всех данных последовательно на принимающий раздел, чтобы сохранить целостность файла образа, даже если что-то пойдет не так с файловой системой, и мне придется восстановить восстановление…); он действительно увеличил отображаемый размер файла до 931,5 ГБ, но на самом деле «размер на диске» был увеличен только на тот небольшой объем данных, который был скопирован на этом этапе.

Таким образом, главный вопрос будет: как объяснить эту редкость? Почему копия ddrescue по умолчанию не является последовательной?

Затем, поскольку у меня было два частичных изображения, каждое из которых содержало некоторые действительные данные, отсутствующие в другом, я сделал следующее:

  • Я попытался скопировать спасенные области из второго изображения в разделе ext4, отсутствующего в первом изображении, в это первое изображение в разделе NTFS, которое должно было быть очень быстрым, так как оба изображения были на одном здоровом жестком диске емкостью 2 ТБ (Seagate). ST2000DX001 с максимальной скоростью записи, близкой к 200 МБ / с). Но оказалось, что это было очень медленно: всего 660 КБ / с.
  • Поэтому я остановился и сделал обратное: я сделал ddrescue скопировать спасенные области из первого изображения (в NTFS), отсутствующего во втором изображении, во второе изображение (в ext4). И теперь я получил скорость копирования 43000 КБ / с или 43 МБ / с, что было значительно выше и ближе к нормальной скорости копирования на том же жестком диске этого класса и емкости.

Второй вопрос: может ли это странное поведение быть связано с проблемой производительности, с которой я столкнулся при записи в NTFS? Известно ли, что драйвер NTFS в Linux имеет проблемы с большими «разреженными» файлами?

2 ответа2

1

Этот ответ исследует поведение 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).

0

Я сделал другой тест самостоятельно.

- Я создал простой шаблон 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, похоже, экономит место таким образом - что не является обязательно преимущество (и может действительно повлиять на производительность); должен быть переключатель, позволяющий распределять полный размер выходного файла «на лету» (в отличие от предварительного выделения, которое может быть очень длинным, если ввод большой), так же, как это делается (очевидно) при прямой записи на устройство или раздел.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .