пятница, 18 марта 2011 г.

Варианты загрузки FreeBSD: gmirror + GPT + UFS

Продолжу тему вариантов загрузки FreeBSD. Кстати, исправления в zfsboot я закоммитил, как оказалось, ошибка была в другом месте, но всё та же, а в drvread её умело "обошли" ещё до изменений pjd@.
Некоторое время назад я участвовал в обсуждении темы использования разметки 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.mountftom="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.

6 коммент.:

  1. АнонимныйApr 4, 2011 07:06 AM

    Спасибо, крайне познавательно. "не для реального использования" - речь идёт о разбивке диска или об используемом способе разбивки диска?

    ОтветитьУдалить
  2. Я имел в виду количество и размеры партиций, параметры создаваемых файловых систем, настройки системы в целом.

    ОтветитьУдалить
  3. АнонимныйApr 6, 2011 06:20 AM

    bu7cher, ещё раз уточню: может ли быть такая схема (gmirror на весь диск и gpt) быть использована и рекомендована в production?

    ОтветитьУдалить
  4. АнонимныйJul 11, 2011 12:10 PM

    >может ли быть такая схема (gmirror на весь диск и gpt)
    >быть использована и рекомендована в production?

    тоже интересно ...

    ОтветитьУдалить
  5. Использовать её можно точно, а вот рекомендовать - я не знаю, лично для меня не видно каких-то сложностей, запрещающих её использовать. Каких-то особенностей в сравнении с другими схемами я тоже не вижу.

    ОтветитьУдалить
  6. АнонимныйDec 13, 2011 08:28 AM

    Я как раз на тикие грабли наскочил.
    http://forums.freebsd.org/showthread.php?t=28306
    Попробую по статье переделать.

    ОтветитьУдалить