Упс, я разметил свой жесткий диск... Восстановление информации после разметки HDD

Перевод статьи Oops, I partitioned my drive.. с любезного согласия Dustin J. Mitchell

Вчера я облажался. Я был на местном хакерспейсе, а WiFi там не работал. Я спешил и был разочарован, поэтому вытащил флешку и попытался ее стереть. Достаточно сказать, что USB-флешка не определилась как /dev/sda. Я очистил GPT-запись на моем ноутбуке. Диск был зашифрован, благодаря буферу все поработало некоторое время, потом вдруг замигало приглашение суперпользователя root и .. больше ничего.

После того, как я вытер холодный пот, я спокойно собрался и вышел. Далее будет история о том, как я оправился от этого с помощью советов Джейка Уоткинса (:dividehex). В системе не было безвозвратных данных. Все мои работы хранятся в системе управления версиями, и я, понятно дело, предварительно разместил все исходники на github. Даже мой домашний каталог dotfiles находится в github (в частном репозитории). Но я провел несколько недель, сидя за этим ноутбуком (Linux  в качестве настольной ОС может использоваться только в очень долгосрочной перспективе!). К сожалению, одна из немногих вещей, которых не было в репозитории - моих заметок. Восстановление с нуля займет несколько недель.

Усложним задачу. В моем ноутбуке ThinkPad Х1 Carbon отсутствует порт Ethernet. Только WiFi. 

Создание резервной копии

ОК, нужно остановить "кровотечение".

Я загрузился с Live-USB флешки, которую я использовал для установки системы "с нуля". Сделав это, я попробовал найти пропавший диск через Рабочий стол ОС:

ssh root@ramanujan dd if=/dev/sda > laptop-disk.img

На поиск ушло около 8 часов, но это дало мне время, чтобы произвести некоторые другие исследования, выпить пиво Baltic Porter (многозадачность!) и поспать.

Поиск удаленных данных на жестком диске

Так что ситуация такова, что у меня есть таблица разделов с единым томом размером в 256 ГБ с файловой системой FAT32. Где-то на диске все мои данные, вероятно, по-прежнему остаются нетронутыми. Но где же они?

Джейк предложил поискать резервную копию таблицы разделов GPT, которая находится в конце диска. В консоли gdisk расширенные опции позволили мне изучить эту таблицу, но она тоже была пуста. Второй совет Джейка: попытаться найти подпись криптоконтейнера LUKS.

dd if=/dev/sda | od -c | grep 'L   U   K   S'

В конечном итоге, запись таблицы обнаружилась в начале раздела, это 05364000000 (735051776 в десятичной системе) байтов на диске. 512 - размер сектора, это сектор 1435648.

В консоли gdisk я создал раздел, начинающийся на этом месте и следующий до конца диска.

# cryptsetup luksDump /dev/sda1
LUKS header information for /dev/sda1

Version:        1
Cipher name:    aes
Cipher mode:    xts-plain64
Hash spec:      sha1
Payload offset: 4096
MK bits:        512
MK digest:      e2 f9 fa 7d 44 dc 82 f5 3c 39 1d e2 ac 6e e3 d2 d0 f5 2b 1b
MK salt:        05 8b a0 ee 7a bf 37 73 7b 15 c1 7a 41 0b 46 19
                56 68 e1 36 f7 7c b3 d0 74 bf 21 98 a1 e6 75 7b
MK iterations:  13750
UUID:           4057691b-b580-4d05-afd3-9e2efe8d65d3
...

Похоже, я обнаружил исчезнувшую информацию.

# cryptsetup luksOpen /dev/sda1 secret

# mount /dev/mapper/secret /mnt

Однако это не сработало. Это не раздел в формате ext4 - это физический том lvm. Udev  уже запустил pvscan, так что мне просто нужно активировать группу томов:

# vgscan -a y fedora
# mount /dev/fedora/root /mnt
# mount /dev/fedora/home /mnt/home

В этот момент пришло время для создания очередной резервной копии. Я использовал TAR, чтобы сбросить содержимое обоих разделов, сохранить архив на моем рабочем столе машины. Это заняло около часа. Сейчас я чувствую себя намного лучше: у меня есть мои заметки, уцелевшие после настройки системы, и все остальное. Но я не потерял данные - могу я восстановить их полностью?

Перестройка

Я перезагрузился с живой USB-флэшки, просто чтобы сбросить все, что я и сделал с диском до этого. Я понимаю, что /dev/sda1- это, наверное, не правильный номер раздела для полной файловой системы, так что я перешел к /dev/sda3 (удаленив и повторно создав с того же первого/последнего секторов). Еще одна перезагрузка.

После этого я запустил установщик и попробовал установить вокруг существующих данных. Я думаю, что я могу сделать минимальную установку в свободном пространстве, особенно после того, как Anaconda меня успокоила, что ей потребуется всего 3.1 Гб.

Короче говоря, это была ложь. Анаконда - это ужасный и глючный кусок программного обеспечения. Например, если вы установите размер раздела - вместо этого будет случайным образом выбран другой размер. Тьфу.

По факту, Анаконде необходимо около 15 Гб для процедуры установки. Так что мне нужно урезать /dev/sda3. Я изменил размеры логических томов все время, но все работает с точностью наоборот -- мне нужно сжать физический объем. Это оказалось немного сложнее. Вначале, после открытия тома LUKS, я запускаю команду pvresize:

pvresize --setphysicalvolumesize 210g /dev/mapper/secret

Появилась ошибка, говорит мне, что есть пространство за новосозданным последним пространством. Нужно вычесть из последнего расстояние, что последней степени называется $boundary. Запуск осуществляется с помощью команды pvdisplay /dev/mapper/secret - отсюда получаем общее физическое пространство и называем это $total. Затем используем pvmove для переноса:

pvmove --alloc anywhere /dev/mapper/secret:$boundary-$total /dev/mapper/secret:0-$boundary

и перезапускаем команду pvresize.

Теперь надо изменить размер контейнера LUKS, который расположен в PV. Это потребует немного арифметики. Lvm использует "GiB" - это нормальная единица измерения, а не глупое измерение заводской утилиты. Поэтому 210g - это 225485783040 байт, которые (поделить на 512) составляют 440401920 секторов на жестком диске.

cryptsetup resize --size 440401920 /dev/mapper/secret

ОК, сжал PV, а также LUKS контейнер, и теперь мне нужно сжать еще и раздел. Это означает удаление и повторное добавление раздела через консольеую утилиту gdisk. Начальный сектор остается неизменным, в то время как последний сектор рассчитывается как $startingsector + 440401920 - 1. Значение -1 важно, я указал _lastsector, не первый сектор следующего раздела. Было бы грустно потерять 512 байт данных, когда я меньше всего этого ожидаю. Тип файловой системы не имеет значения - я использовал ФС по умолчанию, но я заметил, что anaconda использует 0700.

Перезагрузка компьютер и запуск установки снова. Пусть Анаконда делает свое дело, потому что она не станет слушать меня, если я попытаюсь настроить ее. Анаконда выбрала другое имя (fedora_ramanujan) для новой группы томов. Если бы она этого не сделала, мне пришлось бы переименовывать самому. Перезагрузка - и у меня на машине свежая система.

Если бы я был умным, я бы захотел запустить 'yum upgrade", но нет же. Об этом я расскажу чуть ниже.

Идея в том, что у меня теперь есть установленный UEFI и все необходимые загрузочные разделы, однако раздел зашифрован. Изменение сводится к редактированию файла /boot/efi/EFI/fedora/grub.cfg, замене нового VG со старым VG, и новым LUKS UUID на место старого LUKS uuid-идентификатора (от 'cryptsetup dumpLuks'). Перезагрузимся, введем пароль, и .. "добро пожаловать в аварийный режим!". Немного покопавшись, я понял, что все мои разделы монтируются правильно, но журнал фиксирует сбои установки /boot/efi, потому что отсутствует модуль для vfat.

Сложности kernel

Ядро и initrd, конечно, находятся в /boot, и в версии, установленной с Live USB флешкой. Модули ядра находятся modules в корне /, а также обновленные несколько месяцев спустя версии. Они не совпадают.

Быстрое исправление заключается в том, чтобы смонтировать новый LUKS контейнер и скопировать в /lib/modules над собой /lib/modules на старый контейнер. Это заставляет меня копии всех модулей, что Анаконда была установлена, и позволяет мне загрузиться в рабочую систему .. почти. Интернет не работает.

Это, наверное, происходит потому, что я использую старую версию ядра с обновленной системой. Обновление до последней версии ядра это исправляет. Это сложно при отсутствии WiFi, поэтому я смотрю на пакеты на моем рабочем столе, копирую их на USB флешку (будучи очень осторожным, чтобы не переразметить мой десктопный жесткий диск в процессе!), и запускаю команду

yum reinstall /mnt/usb/kernel-*

на ноутбуке после того, как USB-накопитель примонтирован. Перезагрузка - и все опять в норме. Это не самое интересное времяпровождение за последние 20 часов. Но это было забавным приключением.