Продолжу тему вариантов загрузки FreeBSD. Кстати, исправления в zfsboot я закоммитил, как оказалось, ошибка была в другом месте, но всё та же, а в drvread её умело "обошли" ещё до изменений pjd@.
Некоторое время назад я участвовал в обсуждении темы использования разметки GPT и программного зеркала на основе GEOM_MIRROR. Это было в какой-то из рассылок, там я пообещал, что обязательно попробую данную конфигурацию. Проблема была в том, что у людей не получалось организовать GPT поверх gmirror. То ли загрузка не шла, то ли паника была.. Не помню уже.
В общем, настраивал я опять всё в virtualbox'е, всё на той же 8.2-STABLE. Для установки я использовал примерно такие команды (замечу, что я делаю это в тестовых целях, поэтому делается всё довольно просто, не для реального использования):
Первое - во время загрузки gptboot сообщил:
Тут есть небольшое разногласие между gptboot и GEOM_PART_GPT. Некоторое время назад я изменил алгоритм проверки корректности GPT в GEOM_PART_GPT. А именно, после прочтения основного заголовка GPT и проверки его контрольной суммы, резервный заголовок считывается по хранящемуся в основном заголовке адресу. В случае, когда основной заголовок повреждён, резервный заголовок ищется в конце диска. Так, например, во время загрузки созданной выше системы, можно увидеть сообщения:
В итоге, после окончания загрузки, в системе имеется зеркало и GPT на нём; две файловые системы, смонтированные по UFS меткам; swap раздел, подключенный по gpt метке.
Теперь нужно проверить "живучесть" такой системы. Первым испытанием будет исчезновение диска ad4. После отключения диска и запуска виртуальной машины загрузка прошла успешно. Отмечу только эти сообщения от GEOM:
Какие выводы можно сделать в заключение? Если грамотно использовать возможности GEOM классов, то обычно получаешь то, что запланировал. Важно понимать, что и как ты настраиваешь, а не просто копировать набор команд из какого-то howto. Умелое использование меток GEOM_LABEL поможет настроить "живучую" систему, в том плане, что она может без проблем загрузиться после таких воздействий, которые я проделал выше, и не только.
Не забывайте о подводных камнях при использовании GEOM_MIRROR - загрузочный код не знает о его существовании, а значит во время загрузки gptboot будет выполняться с того диска, с которого выбрана загрузка в BIOS. И он загрузит ядро с этого диска, и настройки loader.conf он прочитает оттуда же. Но после того как ядро загрузится и смонтирует файловые системы, данные могут оказаться другими. Например, в приведённых примерах, если не включить загрузку geom_mirror в loader.conf на ad6, то после синхронизации зеркала она будет выключена. Что может оказаться сюрпризом при следующей перезагрузке.
По поводу несогласованности действий gptboot и GEOM_PART_GPT, возможно я решу эту проблему, обсудив детали с pjd@, который переписал реализацию gptboot.
Некоторое время назад я участвовал в обсуждении темы использования разметки GPT и программного зеркала на основе GEOM_MIRROR. Это было в какой-то из рассылок, там я пообещал, что обязательно попробую данную конфигурацию. Проблема была в том, что у людей не получалось организовать GPT поверх gmirror. То ли загрузка не шла, то ли паника была.. Не помню уже.
В общем, настраивал я опять всё в virtualbox'е, всё на той же 8.2-STABLE. Для установки я использовал примерно такие команды (замечу, что я делаю это в тестовых целях, поэтому делается всё довольно просто, не для реального использования):
# gmirror label gm0 ad6 ad8 # gmirror load # gpart create -s gpt mirror/gm0 # gpart add -t freebsd-boot -s 128k mirror/gm0 # gpart add -t freebsd-swap -s 1G -l swap mirror/gm0 # gpart add -t freebsd-ufs -s 2G mirror/gm0 # gpart add -t freebsd-ufs mirror/gm0 # newfs -L rootfs /dev/mirror/gm0p3 # newfs -L usrfs /dev/mirror/gm0p4 # mount /dev/ufs/rootfs /mnt # mkdir /mnt/usr # mount /dev/ufs/usrfs /mnt/usr # cd /usr/src # make DESTDIR=/mnt installworld distribution installkernel # cat > /mnt/boot/loader.conf geom_mirror_load="YES" vfs.root.mountfrom="ufs:/dev/ufs/rootfs" ^D # cat > /mnt/etc/fstab # Device Mountpoint FStype Options Dump Pass# /dev/gpt/swap none swap sw 0 0 /dev/ufs/rootfs / ufs rw 1 1 /dev/ufs/usrfs /usr ufs rw 2 2 ^D # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 mirror/gm0Вроде бы ничего сложного нет:
- сначала создаётся зеркало mirror/gm0 на целых дисках ad6 и ad8;
- затем на зеркале создаётся таблица разделов GPT и 4 раздела - freebsd-boot для загрузочного кода, который умеет загружать с GPT, swap раздел и два (для примера) раздела с UFS - для корневой файловой системы и для /usr;
- затем создаются файловые системы с использованием символьных меток rootfs и usrfs;
- И в конце записывается загрузочный код.
Первое - во время загрузки gptboot сообщил:
gptboot: invalid backup GPT headerПричина понятна - GPT была создана поверх зеркала. Размер провайдера mirror/gm0 на 1 сектор меньше, чем размер диска, так как gmirror забирает последний сектор для хранения своих метаданных. Загрузчик gptboot ничего не знает о программном зеркале и ищет резервный заголовок GPT в конце диска, а там находятся метаданные gmirror.
Тут есть небольшое разногласие между gptboot и GEOM_PART_GPT. Некоторое время назад я изменил алгоритм проверки корректности GPT в GEOM_PART_GPT. А именно, после прочтения основного заголовка GPT и проверки его контрольной суммы, резервный заголовок считывается по хранящемуся в основном заголовке адресу. В случае, когда основной заголовок повреждён, резервный заголовок ищется в конце диска. Так, например, во время загрузки созданной выше системы, можно увидеть сообщения:
GEOM: ad4: the secondary GPT header is not in the last LBA. GEOM: ad6: the secondary GPT header is not in the last LBA. GEOM_MIRROR: Device mirror/gm0 launched (2/2).Эти сообщения уже идут от GEOM, который выполняя поиск метаданных на провайдерах ad4 и ad6 обнаружил GPT, ту же, что и gptboot. Но затем GEOM_MIRROR обнаружил свои метаданные и создал провайдер mirror/gm0, на котором, в свою очередь, тоже была обнаружена GPT, но с ней всё хорошо - все размеры, смещения и контрольные суммые корректны и совпадают.
В итоге, после окончания загрузки, в системе имеется зеркало и GPT на нём; две файловые системы, смонтированные по UFS меткам; swap раздел, подключенный по gpt метке.
# gmirror status Name Status Components mirror/gm0 COMPLETE ad4 ad6 # gpart show => 34 20971452 mirror/gm0 GPT (10G) 34 256 1 freebsd-boot (128K) 290 2097152 2 freebsd-swap (1.0G) 2097442 4194304 3 freebsd-ufs (2.0G) 6291746 14679740 4 freebsd-ufs (7.0G) # swapinfo Device 1K-blocks Used Avail Capacity /dev/gpt/swap 1048576 0 1048576 0% # mount /dev/ufs/rootfs on / (ufs, local) devfs on /dev (devfs, local, multilabel) /dev/ufs/usrfs on /usr (ufs, local)
Теперь нужно проверить "живучесть" такой системы. Первым испытанием будет исчезновение диска ad4. После отключения диска и запуска виртуальной машины загрузка прошла успешно. Отмечу только эти сообщения от GEOM:
GEOM: ad6: the secondary GPT header is not in the last LBA. GEOM_MIRROR: Force device gm0 start due to timeout. GEOM_MIRROR: Device mirror/gm0 launched (1/2).И вывод пары команд для подтверждения своих слов:
# gmirror status Name Status Components mirror/gm0 DEGRADED ad6 # gpart show => 34 20971452 mirror/gm0 GPT (10G) 34 256 1 freebsd-boot (128K) 290 2097152 2 freebsd-swap (1.0G) 2097442 4194304 3 freebsd-ufs (2.0G) 6291746 14679740 4 freebsd-ufs (7.0G)Теперь отключу автоматическую загрузку модуля geom_mirror и проверю, загрузится ли система. Загрузка прошла опять же без проблем, но слегка изменился вывод:
# dmesg | grep GEOM GEOM: ad6: the secondary GPT header is not in the last LBA. # kldstat Id Refs Address Size Name 1 1 0xc0400000 be46fc kernel # gpart show => 34 20971452 ad6 GPT (10G) [CORRUPT] 34 256 1 freebsd-boot (128K) 290 2097152 2 freebsd-swap (1.0G) 2097442 4194304 3 freebsd-ufs (2.0G) 6291746 14679740 4 freebsd-ufs (7.0G) # swapinfo Device 1K-blocks Used Avail Capacity /dev/gpt/swap 1048576 0 1048576 0% # mount /dev/ufs/rootfs on / (ufs, local) devfs on /dev (devfs, local, multilabel) /dev/ufs/usrfs on /usr (ufs, local)Таблица разделов помечена как повреждённая. В таком состоянии её нельзя изменять, а значит меньше шансов что-то испортить. Теперь, верну всё на свои места и снова загружусь:
# dmesg | grep GEOM GEOM: ad4: the secondary GPT header is not in the last LBA. GEOM: ad6: the secondary GPT header is not in the last LBA. GEOM_MIRROR: Device mirror/gm0 launched (1/2). GEOM_MIRROR: Device gm0: rebuilding provider ad4. # gmirror status Name Status Components mirror/gm0 DEGRADED ad4 (6%) ad6Как видите, всё работает.
Какие выводы можно сделать в заключение? Если грамотно использовать возможности GEOM классов, то обычно получаешь то, что запланировал. Важно понимать, что и как ты настраиваешь, а не просто копировать набор команд из какого-то howto. Умелое использование меток GEOM_LABEL поможет настроить "живучую" систему, в том плане, что она может без проблем загрузиться после таких воздействий, которые я проделал выше, и не только.
Не забывайте о подводных камнях при использовании GEOM_MIRROR - загрузочный код не знает о его существовании, а значит во время загрузки gptboot будет выполняться с того диска, с которого выбрана загрузка в BIOS. И он загрузит ядро с этого диска, и настройки loader.conf он прочитает оттуда же. Но после того как ядро загрузится и смонтирует файловые системы, данные могут оказаться другими. Например, в приведённых примерах, если не включить загрузку geom_mirror в loader.conf на ad6, то после синхронизации зеркала она будет выключена. Что может оказаться сюрпризом при следующей перезагрузке.
По поводу несогласованности действий gptboot и GEOM_PART_GPT, возможно я решу эту проблему, обсудив детали с pjd@, который переписал реализацию gptboot.