Попался интересный случай в практике — понадобилось восстановить данные из частично скопированного с помощью ddrescue образа с умирающего диска. Подробности под катом.
Прежде следует упомянуть, что образ был снят частично, т.к. снятие полного образа заняло бы больше месяца из-за участившихся ошибок чтения с диска. На момент отмены копирования образ был снят примерно на 60% от терабайтного диска, причем было известно, что примерно треть этого размера занято данными.
Перво на перво смотрим на таблицу файлов:
gpart show ada1
=> 0 155189223 ada1 GPT (989G)
155189223 153092089 1 freebsd-boot (32k)
0 153092089 2 freebsd-ufs (986G)
153092089 2097128 3 freebsd-swap (3G)
155189217 6 - free - (3.0k)
Таблица вроде нормальная.
Пробуем сделать fsck для второго раздела и видим:
fsck_ffs /dev/ada1p2
BAD SUPER BLOCK: VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST
ALTERNATE
ioctl IGCINFO): Inappropriate ioctl for device
Тут, как видим, fsck не может прочитать данные из альтернативного суперблока. Но на это есть возможность явно указать fsck из какого блока брать данные о ФС. Узнать расположение блоков можно с помощью ключа -N утилиты создания новой ФС newfs:
newfs -N /dev/ada1p2
[..skipped..]
160, 376512, 752864, 1129216, 1505568, 1881920, 2258272, 2634624, 3010976, 3387328
[..skipped..]
Берем первый попавшийся суперблок, т.е. 160 и с его помощью проверяем ФС:
fsck_ffs -b 160 /dev/ada1p2
Alternate super block location 160
** /dev/ada1p2
** Last Mounted on
** Phase 1 - Check Blocks and Sizes
[..skipped..]
Если при этом получаем ошибку:
160 is not a file system superblock
То это означает что выбрали поврежденный или неверно определенный суперблок и используем другой номер из вывода newfs.
После проверки ФС проверяем, испрваилась ли проблема:
fsck_ffs /dev/ada1p2
И снова видим ту же ошибку, что в первый раз. Вот тут я нашел замечание, что fsck нужен именно последний суперблок для беспрепятственного запуска. Где его взять? Я решил эту задачу скопировав этот суперблок 3387328 с оригинала:
dd if=/dev/ada0p2 skip=3387328 of=/dev/ada1p2 seek=3387328 bs=512 count=16
После чего видим:
fsck_ffs /dev/ada1p2
** /dev/ada1p2
** Last Mounted on
** Phase 1 - Check Blocks and Sizes
[..skipped..]
Если проверка прошла нормально — мы обычным образом монтируем раздел и копируем файлы.
Источники вдохновения: https://forums.freebsd.org/threads/16984/ и https://forums.freebsd.org/threads/47833/ а так же документация у fsck и newfs.