Частный случай восстановление UFS2
Добавлено: 2010-07-25 21:07:50
ОТМАЗКА: Это не how-to и не know-how. Скорее, это лабораторная работа по частному случаю восстановления UFS. Может быть, кому-то и пригодится.
Итак.
Внезапно...
Внезапно система, на которой была спасена не одна дюжина миров и собрана дюжина Миров споткнулась на ровном месте, дёрнула 250Гным винтом и ушла в ребут, утянув вместе с собой в небытие UFS раздел с сорцами и торрентами.
Ступор... Single mode...
Беглый осмотр места проишествия показал: тип раздела не определяется как UFS, хотя тень раздела в виде метки /dev/gpt/work присутсутствует.
Хватаю первый попавшийся под руку микроскоп:
Один GPT раздел (id=0xee) (должен быть) в наличии. Вкуриваю http://en.wikipedia.org/wiki/GUID_Partition_Table, делаю дамп первого блока диска, сличаю с дампом другого диска (тоже GPT).
Всё в порядке и соответствует спецификации.
Следующая тулза, которая первой приходит на ум - Testdisk. Проверяю:
"Solaris /home" - не совсем то, что я ожидал увидеть, да и начинается с 66-огого блока (хорошо хоть не с 666
вместо 34-го.
ЗЫ: если testdisk сообщает про "write protected disk", значит нужно вколоть стимулятор:
Небольшое отступление: geom постоянно ругался на испорченные GPT-таблицы, взывая к необходимости исправить их. Testdisk упорно находил и предлагал сохранить NTFS раздел, который когда-то действительно имел место быть на этом диске. Я не менее упорно отказывался от NTFS, в безуспешных попытках ткнуть testdisk носом в потерявшийся UFS раздел. В результате наших боданий были напрочь затоптаны даже те небольшие остатки патриции, которые ещё имели место спастись на диске: раздел перестал определяться как /dev/gpt/work. Увы, кривизна моих рук не даёт мне покоя...
Перво-наперво надо потренироваться на кошках:
Призвал на помощь могущественно духа -
И пронаблюдал отдельно живой раздел:
Целиком живой диск:
Сравнил с тем, что есть на живом (системном) диске:
Далее опять небольшой монтаж: многократное взятие на анализы дампов суперблоков здоровых разделов и побайтовое сравнение с дампом больного раздела, взятие у больного на анализ backup-копий суперблока, которые повторяются каждые 32768 блоков, начиная со 128 от начала раздела, (при условии форматирования раздела с дефолтными параметрами), вкуривание 'man fs' и не только...
Запускаю, медитирую:
Даже вот так, только самое необходимое:
В качестве сухого экстракта: суперблок должен начинаться с адреса 0x10000 bytes (128 blocks) от начала раздела, корень файловой системы должен начинаться с адреса 0x94400, суперблок повторяется по адресам 0x1018400, 0x2018400, 0x3018400 и так далее.
Если считать от начала диска, то надо прибавить, соответственно, 0x4400 (34 blocks): адрес суперблока=0x14400, адрес корня файловой системы=0xA4400
Диагноз: в конкретном моём случае всё указывало на то, что суперблок (живой и здоровый) находится не на своём месте (testdisk всё-таки сумел записать на диск правильный superblock в неправильное место).
Небольшое отступление: здесь можно было выбрать иной путь: взять backup GPT header из последнего блока диска
поменять местами "Current LBA" и "Backup LBA", "Partition entries starting LBA" исправить с 0x1D1C510E на 0x2, пересчитать CRC32,
и вписать во 2-ой блок диска, но... Это было слишком сложно для меня и я поступил просто, но решительно:
Проверил:
В соответствии с диагнозом, было принято решение о пересадке superblocka через промежуточный контейнер:
Итак, пришло время взглянуть в глаза действительности:
Что-то уже прорисовывается! Но, прежде чем довериться fsck'у, небольшая пальпация:
Теперь, для успокоения душевных мук, можно полюбоваться на отсутствие различий между primary и backup копиями суперблока (что является первым признаком наметившегося выздоровления):
И это один из немногих случаев, когда можно радоваться тому, что ничего не видишь.
Затаив дыхание, запустил:
и ушёл нервно курить в сторонке, взывая к Великому и Ужасному Рэндому, чтобы по окончании проверки лицезреть кучу исправлений
в lost+found оказалось полсотни файлов, общим размером ~800 Мб)
Отступать некуда, монтирую:
Кажысь, всё на месте 
И последнее наведение гламурного глянца - зачистка хвостов NTFS, boot record которой начинается с адреса 0x7E00(=32256) и тянется примерно до 0x8B75(=40448), т.е., общим размером 8192:
Возвращаю в прежний вид /etc/fstab, контрольный ребут, transmission, 3 Мбайта потерянных данных в одном торренте из 50-ти (хм, всего-то)...
Радостный возглас !$@#
Холодный Guiness 1,2,3...
Занавес...
Небольшой ИТОГО:
- Для более-менее надёжной очистки диска от предыдущих разделов, надо обнулять 65,5 Кбайт в начале и в конце диска. Потом будет проще выковыривать.
- Сохранять расклад. Сохранять тем же dd'ом те же самые 65,5 Кбайт начала и конца диска. Чтоб было от чего плясать, в случае чего.
- GUID для Unix File System (UFS) partition вот такой 516E7CB6-6ECF-11D6-8FF8-00022D09712B, но первые три группы цифр идут в обратном порядке,
поэтому на диске они видятся вот так:
- В UFS2 по сравнению с UFS много неиспользуемых полей. Если кому интересно, вот ссылка http://flylib.com/books.php?ln=en&n=2&p ... 184&view=1
Использованные программы: c dd_rescue и ddrescue лично у меня не срослось. Пытался сделать образ диска, но скорость копирования была менее 1 Мб/с.
С dd тоже не срослось - образ писал на внешний USB, смонтированный fusefs-ntfs'ом и система не справлялась. Пока сижу смотрю, копируется. Ушёл спать - всё терминулось. Больше 92 Гб не смог скопировать - бросил эту затею.
Sleuthkit - могутный пакет, в пару к нему идёт Autopsy, перловый Веб-ГУЙ, особенно хорош для начинающих. Одно "НО" - работает только с образами диском (в моём случае не стали работать с /dev/ad2p1).
С ним у меня тоже не срослось, ввиду отсутствия полноценного образа. Хотя образ можно разбивать на части и грузить списком.
HEX-редакторы: lfhex - требует что-то из QT4, ghex - требует Gnoma, судя по всему, всё и сразу. Поскольку я сижу под XFCE4, ни QT4 ни Gnome у меня нет, поэтому отказался. Для любителей VI могу порекомендовать bvi (binary vi), полный аналог vi.
hexedit, chexedit - простые консольные, работают на ncurses, примерно одинаково функциональны. Я остановился на chexedit.
Пришлось много конвертировать hex-dec. Не придумал ничего лучшего, кроме пары алиасов:
Итак.
Внезапно...
Внезапно система, на которой была спасена не одна дюжина миров и собрана дюжина Миров споткнулась на ровном месте, дёрнула 250Гным винтом и ушла в ребут, утянув вместе с собой в небытие UFS раздел с сорцами и торрентами.
Ступор... Single mode...
Беглый осмотр места проишествия показал: тип раздела не определяется как UFS, хотя тень раздела в виде метки /dev/gpt/work присутсутствует.
Хватаю первый попавшийся под руку микроскоп:
Код: Выделить всё
# fdisk -p ad2
# /dev/ad2
g c484518 h16 s63
p 1 0xee 1 488395054Всё в порядке и соответствует спецификации.
Следующая тулза, которая первой приходит на ум - Testdisk. Проверяю:
Код: Выделить всё
# testdisk -> No Log -> Disk /dev/ad2 -> [EFI GPT] -> [Analyse]
TestDisk 6.11, Data Recovery Utility, April 2009
Christophe GRENIER <grenier@cgsecurity.org>
http://www.cgsecurity.org
Disk /dev/ad2 - 250 GB / 232 GiB - CHS 484518 16 63
Partition Start End Size in sectors
P Solaris /home 66 488395053 488394988ЗЫ: если testdisk сообщает про "write protected disk", значит нужно вколоть стимулятор:
Код: Выделить всё
# sysctl kern.geom.label.debug=16Перво-наперво надо потренироваться на кошках:
Код: Выделить всё
dd if=/dev/zero of=/flash/d64m.raw bs=1M count=64
mdconfig -a -t vnode -f /home/pablo/flash/d64m.raw -o async -u 0
gpart create -s gpt md0
gpart add -t freebsd md0
gpart modify -i 1 -l test md0
newfs -o time /dev/md0s1
mount /dev/gpt/test /mnt/tmp/Код: Выделить всё
# portinstall sysutils/scan_ffsКод: Выделить всё
$ scan_ffs -vs /dev/md0s1
block 128 id 4c34a367,be2d1218 size 32751
block 160 id 4c34a367,be2d1218 size 32751
ufs2 at 0 size 32751 mount /mnt/tmp time Wed Jul 7 22:55:19 2010Код: Выделить всё
$ scan_ffs -vs /dev/md0
block 162 id 4c34a367,be2d1218 size 32751 <== адреса блоков смещены на 34 блока. Superblock по адресу 0x14400
block 194 id 4c34a367,be2d1218 size 32751 <== хвост Суперблока по адресу 0x18400
ufs2 at 34 size 32751 mount /mnt/tmp time Wed Jul 7 22:55:19 2010 <== UFS2 находится со смещеним 34 от начала дискаКод: Выделить всё
$ scan_ffs -vs /dev/ad0
block 290 id 4b3a8ba7,7d0b56cf size 262144 <== superblock /, смещён на 128 блоков от начала диска, на размер boot-part'а
block 322 id 4b3a8ba7,7d0b56cf size 262144 <== magic
ufs2 at 162 size 262144 mount / time Wed Dec 30 05:07:19 2009Запускаю, медитирую:
Код: Выделить всё
> scan_ffs -v -l /dev/ad2
block 160 id 4a8f5548,f603e83e size 122098747 <== а вот нужное, с id=4a8f5548,f603e83e и size=122098747
block 162 id 0,0 size 122098747 <== здесь должен быть superblock
block 194 id 4a8f5548,f603e83e size 122098747 <== magic для UFS2 = 19 01 54 19
X: 488394988 34 4.2BSD 2048 16384 0 # <== строка для bsdlabel, которую подсказывает scan_ffs. Пока форматить повременю...
block 12098 id 0,0 size 122098747 <== тоже непонятно-что
block 239602 id 4b08bce0,6b8b4567 size 901552 <== какой-то старый хвост
block 376546 id 4a8f5548,f603e83e size 122098747 <== Cylinder Group 1 (если я не путаю нумерацию)
block 752898 id 4a8f5548,f603e83e size 122098747 <== Cylinder Group 2
block 1129250 id 4a8f5548,f603e83e size 122098747 <== Cylinder Group 3
... <scipped>Код: Выделить всё
> scan_ffs -v -b 0 -e 163 /dev/ad2
block 160 id 4a8f5548,f603e83e size 122098747 <== правильная запись в неправильном месте
block 162 id 0,0 size 122098747 <== неправильная запись в правильном месте
block 194 id 4a8f5548,f603e83e size 122098747 <== magic
ufs2 at 34 size 122098747 mount time Sat Aug 22 09:17:44 2009 <== точка последнего монтирования не определиласьЕсли считать от начала диска, то надо прибавить, соответственно, 0x4400 (34 blocks): адрес суперблока=0x14400, адрес корня файловой системы=0xA4400
Диагноз: в конкретном моём случае всё указывало на то, что суперблок (живой и здоровый) находится не на своём месте (testdisk всё-таки сумел записать на диск правильный superblock в неправильное место).
Небольшое отступление: здесь можно было выбрать иной путь: взять backup GPT header из последнего блока диска
Код: Выделить всё
# dd if=/dev/ad2 of=ad2_lbaB bs=512 count=1 iseek=488395054; chexedit ad2_lbaB
00000000 45 46 49 20 50 41 52 54 00 00 01 00 5C 00 00 00 6F DD A8 4B 00 00 00 00 2E 51 1C 1D EFI PART....\...o..K.....Q..
0000001C 00 00 00 00 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 0D 51 1C 1D 00 00 00 00 ............"........Q......
00000038 EE 23 D1 D7 89 FB 43 CF AC 3D 3F 7C E8 1D 4A 53 0E 51 1C 1D 00 00 00 00 80 00 00 00 .#....C..=?|..JS.Q..........
00000054 80 00 00 00 22 F8 63 99 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ....".c.....................и вписать во 2-ой блок диска, но... Это было слишком сложно для меня и я поступил просто, но решительно:
Код: Выделить всё
# gpart destroy ad2 <== мёртвой водой
# gpart create -s GPT ad2 <== живой водой
# gpart add -t freebsd-ufs ad2 <== определил
# gpart modify -i 1 -l work ad2 <== пометилКод: Выделить всё
# gpart show -l ad2
=> 34 488394988 ad2 GPT (233G)
34 488394988 1 work (233G)Код: Выделить всё
# dd if=/dev/ad2 of=ad2_superblock skip=194 bs=512 count=4
# dd if=/dev/zero of=/dev/ad2 bs=512 count=6 oseek=160
# dd if=ad2_superblock of=/dev/ad2 bs=512 count=4 oseek=162Код: Выделить всё
# scan_ffs /dev/ad2
ufs2 at 34 size 122098747 mount time Sat Aug 22 09:17:44 2009Код: Выделить всё
# fsdb -d /dev/gpt/work
** /dev/gpt/work
Editing file system `/dev/gpt/work'
Last Mounted on
current inode: directory
I=2 MODE=40755 SIZE=512
BTIME=Aug 22 09:17:44 2009 [0 nsec]
MTIME=Dec 11 22:05:25 2009 [0 nsec]
CTIME=Dec 11 22:05:25 2009 [0 nsec]
ATIME=Jun 13 00:26:01 2010 [0 nsec]
OWNER=root GRP=wheel LINKCNT=8 FLAGS=0 BLKCNT=4 GEN=206f2c6
fsdb (inum: 2)> ls
command `ls
'
slot 0 ino 2 reclen 12: directory, `.'
slot 1 ino 2 reclen 12: directory, `..'
slot 2 ino 3 reclen 16: directory, `.snap'
slot 3 ino 24541184 reclen 16: directory, `backup'
slot 4 ino 6571008 reclen 16: directory, `torrent'
slot 5 ino 21879808 reclen 16: directory, `public'
slot 6 ino 21903360 reclen 20: directory, `lost+found'
slot 7 ino 17805312 reclen 404: directory, `conf'
fsdb (inum: 2)> quitКод: Выделить всё
# diff <(ffsinfo -g 0 -i 2 -l 0x1 /dev/gpt/work) <(ffsinfo -g -1 -i 2 -l 0x1 /dev/gpt/work)Затаив дыхание, запустил:
Код: Выделить всё
# fsck -y -t ufs /dev/gpt/workОтступать некуда, монтирую:
Код: Выделить всё
# mount -o noatime /dev/gpt/work /work/
# ll /work
total 32
drwxr-xr-x 8 root wheel - 512 11 дек 2009 ./
drwxr-xr-x 23 root wheel - 512 15 июл 12:02 ../
drwxrwx--- 2 root operator - 512 18 сен 2009 .snap/
drwxr-xr-x 8 root wheel - 512 12 июн 21:28 backup/
drwxr-xr-x 3 root wheel - 512 14 дек 2009 conf/
drwx------ 6 root wheel - 16896 22 авг 2009 lost+found/
drwxrwxr-x 2 pablo pablo - 512 14 июн 13:37 public/
drwxr-xr-x 9 pablo pablo - 512 28 фев 13:39 torrent/И последнее наведение гламурного глянца - зачистка хвостов NTFS, boot record которой начинается с адреса 0x7E00(=32256) и тянется примерно до 0x8B75(=40448), т.е., общим размером 8192:
Код: Выделить всё
# dd if=/dev/zero of=/dev/ad2 oseek=63 bs=512 count=16Радостный возглас !$@#
Холодный Guiness 1,2,3...
Занавес...
Небольшой ИТОГО:
- Для более-менее надёжной очистки диска от предыдущих разделов, надо обнулять 65,5 Кбайт в начале и в конце диска. Потом будет проще выковыривать.
- Сохранять расклад. Сохранять тем же dd'ом те же самые 65,5 Кбайт начала и конца диска. Чтоб было от чего плясать, в случае чего.
- GUID для Unix File System (UFS) partition вот такой 516E7CB6-6ECF-11D6-8FF8-00022D09712B, но первые три группы цифр идут в обратном порядке,
поэтому на диске они видятся вот так:
Код: Выделить всё
B6 7C 6E 51 CF 6E D6 11 8F F8 00 02 2D 09 71 2BИспользованные программы: c dd_rescue и ddrescue лично у меня не срослось. Пытался сделать образ диска, но скорость копирования была менее 1 Мб/с.
С dd тоже не срослось - образ писал на внешний USB, смонтированный fusefs-ntfs'ом и система не справлялась. Пока сижу смотрю, копируется. Ушёл спать - всё терминулось. Больше 92 Гб не смог скопировать - бросил эту затею.
Sleuthkit - могутный пакет, в пару к нему идёт Autopsy, перловый Веб-ГУЙ, особенно хорош для начинающих. Одно "НО" - работает только с образами диском (в моём случае не стали работать с /dev/ad2p1).
С ним у меня тоже не срослось, ввиду отсутствия полноценного образа. Хотя образ можно разбивать на части и грузить списком.
HEX-редакторы: lfhex - требует что-то из QT4, ghex - требует Gnoma, судя по всему, всё и сразу. Поскольку я сижу под XFCE4, ни QT4 ни Gnome у меня нет, поэтому отказался. Для любителей VI могу порекомендовать bvi (binary vi), полный аналог vi.
hexedit, chexedit - простые консольные, работают на ncurses, примерно одинаково функциональны. Я остановился на chexedit.
Пришлось много конвертировать hex-dec. Не придумал ничего лучшего, кроме пары алиасов:
Код: Выделить всё
alias dec='printf "%d\n" $1'
alias hex='printf "0x%x\n" $1'