пятница, 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.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.

57 комментариев:

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

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

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

    ОтветитьУдалить
  4. Анонимный11 июля 2011 г., 23:10

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

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

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

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

    ОтветитьУдалить
  7. а не более правильно использовать другую схему?
    1. создаются разделы GPT
    2. делается зеркалирование каждого раздела отдельно
    тогда заголовки будут на своих местах ;)

    ОтветитьУдалить
  8. У этого метода тоже есть свои недостатки, к тому же, в 10-ке поведение gptboot и GEOM_PART_GPT уже синхронизировано.

    ОтветитьУдалить
    Ответы
    1. в 9.1 вошли эти изменения?

      Удалить
    2. Добрый день! Обновил 8.4, до 9.3, создал сырое зеркало из одного диска, сделал на нем разметку GPT и т.д. и т.п., перенес систему, добавил в зеркало второй диск. Все грузится и работает, но при загрузке пишется, что копия GPT повреждена и gpart show/status говорит, что gm0 и его разделы CORRUPT. Пожалуйста подскажите, 10.1 ведет себя аналогично?

      Удалить
    3. Возможно GPT вы создали не на зеркале, а на физическом диске. Возможно у вас BIOS какого-нибудь софтового рейда записывает что-то в конец диска и портит GPT. Покажите что у вас выводит gpart list и какие сообщения пишутся при загрузке.

      Удалить
    4. Добрый день! Спасибо за ответ! При загрузке пишется:

      GEOM: ada0: the secondary GPT table is corrupt or invalid.
      GEOM: ada0: using the primary only -- recovery suggested.
      GEOM: ada1: the secondary GPT table is corrupt or invalid.
      GEOM: ada1: using the primary only -- recovery suggested.
      GEOM_MIRROR: Device mirror/gm0 launched (2/2).
      GEOM: mirror/gm0: the secondary GPT table is corrupt or invalid.
      GEOM: mirror/gm0: using the primary only -- recovery suggested.

      gpart list выдает следующее:

      Geom name: mirror/gm0
      modified: false
      state: CORRUPT
      fwheads: 255
      fwsectors: 63
      last: 488397133
      first: 34
      entries: 128
      scheme: GPT
      Providers:
      1. Name: mirror/gm0p1
      Mediasize: 65536 (64k)
      Sectorsize: 512
      Stripesize: 0
      Stripeoffset: 17408
      Mode: r0w0e0
      rawuuid: 66b9f6c4-2c5f-11e5-9e0c-d8fee3a8642c
      rawtype: 83bd6b9d-7f41-11dc-be0b-001560b84f0f
      label: (null)
      length: 65536
      offset: 17408
      type: freebsd-boot
      index: 1
      end: 161
      start: 34
      2. Name: mirror/gm0p2
      Mediasize: 8589934592 (8.0G)
      Sectorsize: 512
      Stripesize: 0
      Stripeoffset: 82944
      Mode: r1w1e1
      rawuuid: 7018a92c-2c5f-11e5-9e0c-d8fee3a8642c
      rawtype: 516e7cb5-6ecf-11d6-8ff8-00022d09712b
      label: swap
      length: 8589934592
      offset: 82944
      type: freebsd-swap
      index: 2
      end: 16777377
      start: 162
      3. Name: mirror/gm0p3
      Mediasize: 536870912 (512M)
      Sectorsize: 512
      Stripesize: 0
      Stripeoffset: 82944
      Mode: r1w1e2
      rawuuid: 7b955cf3-2c5f-11e5-9e0c-d8fee3a8642c
      rawtype: 516e7cb6-6ecf-11d6-8ff8-00022d09712b
      label: root
      length: 536870912
      offset: 8590017536
      type: freebsd-ufs
      index: 3
      end: 17825953
      start: 16777378
      4. Name: mirror/gm0p4
      Mediasize: 1073741824 (1.0G)
      Sectorsize: 512
      Stripesize: 0
      Stripeoffset: 536953856
      Mode: r1w1e2
      rawuuid: 817f1432-2c5f-11e5-9e0c-d8fee3a8642c
      rawtype: 516e7cb6-6ecf-11d6-8ff8-00022d09712b
      label: var
      length: 1073741824
      offset: 9126888448
      type: freebsd-ufs
      index: 4
      end: 19923105
      start: 17825954
      5. Name: mirror/gm0p5
      Mediasize: 1073741824 (1.0G)
      Sectorsize: 512
      Stripesize: 0
      Stripeoffset: 1610695680
      Mode: r1w1e2
      rawuuid: 84222a49-2c5f-11e5-9e0c-d8fee3a8642c
      rawtype: 516e7cb6-6ecf-11d6-8ff8-00022d09712b
      label: tmp
      length: 1073741824
      offset: 10200630272
      type: freebsd-ufs
      index: 5
      end: 22020257
      start: 19923106
      6. Name: mirror/gm0p6
      Mediasize: 8589934592 (8.0G)
      Sectorsize: 512
      Stripesize: 0
      Stripeoffset: 2684437504
      Mode: r1w1e2
      rawuuid: 88f45840-2c5f-11e5-9e0c-d8fee3a8642c
      rawtype: 516e7cb6-6ecf-11d6-8ff8-00022d09712b
      label: usr
      length: 8589934592
      offset: 11274372096
      type: freebsd-ufs
      index: 6
      end: 38797473
      start: 22020258
      7. Name: mirror/gm0p7
      Mediasize: 230195025920 (214G)
      Sectorsize: 512
      Stripesize: 0
      Stripeoffset: 2684437504
      Mode: r1w1e2
      rawuuid: 8e1d2eb2-2c5f-11e5-9e0c-d8fee3a8642c
      rawtype: 516e7cb6-6ecf-11d6-8ff8-00022d09712b
      label: data
      length: 230195025920
      offset: 19864306688
      type: freebsd-ufs
      index: 7
      end: 488397133
      start: 38797474
      Consumers:
      1. Name: mirror/gm0
      Mediasize: 250059349504 (232G)
      Sectorsize: 512
      Mode: r6w6e17

      Удалить
    5. Здесь не вся информация, которую показывает `gpart list`. Мне нужна информация о дисках ada0 и ada1.

      Удалить
    6. Ах да, если gpart не видит таблиц разделов на дисках, покажите тогда вывод `geom disk list`

      Удалить
    7. Пока был отдельный диск ada0 и зеркало из одного диска ada1, gpart list показывала их оба, после добавления ada0 в зеркало, перестала показывать. Вот вывод geom disk list (без Geom name: cd0):

      Geom name: ada0
      Providers:
      1. Name: ada0
      Mediasize: 250059350016 (232G)
      Sectorsize: 512
      Mode: r1w1e1
      descr: WDC WD2500AAKX-001CA0
      lunid: 50014ee0ae0b8aa7
      ident: WD-WMAYW2072016
      fwsectors: 63
      fwheads: 16

      Geom name: ada1
      Providers:
      1. Name: ada1
      Mediasize: 250059350016 (232G)
      Sectorsize: 512
      Mode: r1w1e1
      descr: WDC WD2500AAKX-001CA0
      lunid: 50014ee2067d489a
      ident: WD-WMAYV0091942
      fwsectors: 63
      fwheads: 16

      Я могу удалить диск из зеркала и сделать все, что поможет Вам диагностировать проблему. Этот компьютер стоит за стенкой (в случае ошибок всегда доступны single user mode и LiveFS), но, есть еще несколько похожих компьютеров, которые находятся очень далеко, поэтому хочется понять, как удаленно обновить их без последствий. Кстати, если просто добавить kern.geom.part.check_integrity="0" в /boot/loader.conf, FreeBSD, обновленная с 8.4 до 9.3, загрузится с зеркала, созданного, в предыдущей версии системы путем добавления ранее размеченного диска с MBR в gmirror и последующего добавления второго диска? Извините за кучу вопросов и заранее огромное спасибо за помощь.

      Удалить
    8. На всякий случай, версия ОС - FreeBSD 9.3-RELEASE-p19 #0 r285262.

      Удалить
    9. Размер диска 250059350016/512=488397168 секторов.
      Размер зеркала должен быть 488397167 секторов - 250059349504/512 = 488397167.
      Выглядит вроде всё корректно. Если сделать gpart recover mirror/gm0 после перезагрузки всё повторяется?

      Удалить
    10. Сделал gpart recover mirror/gm0, после перезагрузки все повторилось.

      Удалить
    11. Сделайте дамп последних 34 секторов диска и вышлите мне на почту, посмотрим что там есть, возможно причина будет видна.
      dd if=/dev/ada0 of=~/disk.dump iseek=488397134

      Удалить
    12. Сделал и отправил на @yandex.ru.

      Удалить
  9. У вас опечатка: vfs.root.mountftom

    Отрадно, что это никак не повлияло на работоспособность.

    ОтветитьУдалить
  10. *
    FreeBSD 9.2/10.0
    ***
    # make DESTDIR=/mnt installworld distribution installkernel
    пишет что команда installworld не известна ...
    папка cd /usr/src пустая.
    Вы сами то пробовали так делать или статья с коленки?

    ОтветитьУдалить
    Ответы
    1. Я не ставил себе цель написать инструкцию. Если Вы не знаете, что выполняет данная команда, то не нужно подвергать свою систему риску быть уничтоженной.

      Удалить
  11. Помогите решить проблему:

    при загрузке вижу: gptboot: backup GPT header checksum mismatch

    далее в логах:
    ada0 at ahcich0 bus 0 scbus0 target 0 lun 0
    ada0: ATA-8 SATA 3.x device
    ada0: Serial Number WD-WMAYP0E8PKPS
    ada0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 8192bytes)
    ada0: Command Queueing enabled
    ada0: 476938MB (976771055 512 byte sectors: 16H 63S/T 16383C)
    ada0: Previously was known as ad4
    ada1 at ahcich1 bus 0 scbus1 target 0 lun 0
    ada1: ATA-8 SATA 3.x device
    ada1: Serial Number WD-WMAYP0E7PAY1
    ada1: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
    ada1: Command Queueing enabled
    ada1: 476940MB (976773168 512 byte sectors: 16H 63S/T 16383C)
    ada1: Previously was known as ad6
    ada2 at ahcich4 bus 0 scbus4 target 0 lun 0
    ada2: ATA-8 SATA 3.x device
    ada2: Serial Number WD-WMC1P0D214M8
    ada2: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
    ada2: Command Queueing enabled
    ada2: 1907729MB (3907029168 512 byte sectors: 16H 63S/T 16383C)
    ada2: Previously was known as ad12
    ada3 at ahcich5 bus 0 scbus5 target 0 lun 0
    ada3: ATA-8 SATA 3.x device
    ada3: Serial Number WD-WMC1P0D90ZVN
    ada3: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
    ada3: Command Queueing enabled
    ada3: 1907729MB (3907029168 512 byte sectors: 16H 63S/T 16383C)
    ada3: Previously was known as ad14

    GEOM: mirror/gm0: the secondary GPT table is corrupt or invalid.
    GEOM: mirror/gm0: using the primary only -- recovery suggested.
    GEOM: mirror/gm1: the secondary GPT table is corrupt or invalid.
    GEOM: mirror/gm1: using the primary only -- recovery suggested.

    [root@srv3 ~]# gmirror status
    Name Status Components
    mirror/gm0 COMPLETE ada0 (ACTIVE)
    ada1 (ACTIVE)
    mirror/gm1 COMPLETE ada2 (ACTIVE)
    ada3 (ACTIVE)

    [root@srv3 ~]# gpart status
    Name Status Components
    mirror/gm0p1 CORRUPT mirror/gm0
    mirror/gm0p2 CORRUPT mirror/gm0
    mirror/gm0p3 CORRUPT mirror/gm0
    mirror/gm1p1 CORRUPT mirror/gm1

    [root@srv3 ~]# gpart show
    => 34 976770987 mirror/gm0 GPT (466G) [CORRUPT]
    34 1024 1 freebsd-boot (512K)
    1058 16777216 2 freebsd-swap (8.0G)
    16778274 959992746 3 freebsd-ufs (458G)
    976771020 1 - free - (512B)

    => 34 3907029100 mirror/gm1 GPT (1.8T) [CORRUPT]
    34 3906994176 1 freebsd-ufs (1.8T)
    3906994210 34924 - free - (17M)

    [root@srv3 ~]# gpart recover mirror/gm0
    mirror/gm0 recovered
    ничего не делает, после перезагрузки видим те же ошибки.

    Облазил весь интернет - не смог найти решение. Как быть?

    ОтветитьУдалить
    Ответы
    1. Предлагаю сделать дамп последних 33 секторов провайдера mirror/gm0 и mirror/gm1 и глядя на них попробовать предположить, кто туда пишет данные. Возможно там будет какая-то знакомая сигнатура.

      Удалить
  12. Этот комментарий был удален автором.

    ОтветитьУдалить
  13. Здравствуйте!
    Большое спасибо за Ваши разработки и полезную информацию!
    Но Вы писали:
    "По поводу несогласованности действий gptboot и GEOM_PART_GPT, возможно я решу эту проблему, обсудив детали с pjd@, который переписал реализацию gptboot.
    ...
    ...в 10-ке поведение gptboot и GEOM_PART_GPT уже синхронизировано."

    Как то оно нет. ;-(
    Я сейчас пытался создать программное зеркало на SSD на основе свежего релиза FreeBSD 10.3 и обнаружил, что при создании GPT+gmirror в любом варианте (в нормальном режиме загрузки или при загрузке с CD) gmirror убивает таблицы GPT.
    Если делать в нормальном режиме загрузки прибивается последняя, бэкапная таблица GPT, и при этом не создаётся gmirror.
    Если делать при загрузке с CD, то gmirror создаётся, но GPT сносится целиком. Естественно, при обоих вариантах система слетает.
    Это фича или баг? Вместит ли почтовый ящик "pjd@" миллион наилучших пожеланий по поводу предотвращения подобных проблем? ;-)

    ОтветитьУдалить
    Ответы
    1. pjd@ ужа давно не занимается geom.
      Описанные вами симптомы говорят о неверной последовательности действий. Чтобы всё работало как описано в этой статье, нужно сначала создать gmirror, потом ПОВЕРХ этого зеркала создавать GPT.
      Нужно понять для чего это делается: когда вы создаёте зеркало, размер "диска" уменьшается на 1 сектор, этот сектор забирает себе gmirror. После этого вы можете создавать GPT, чтобы gpart не смог испортить сектор, который взял gmirror. Никак иначе.

      Удалить
  14. Спасибо!
    В разные времена и разными спецами предлагались разные варианты решений, причём мнения насчёт лучшего варианта в последнее время успели поменяться на противоположные (даже относительно рекомендаций хэндбука). ;-)
    "Warning: Creating a mirror out of the boot drive may result in data loss if any data has been stored on the last sector of the disk. This risk is reduced if creating the mirror is done promptly after a fresh install of FreeBSD. The following procedure is also incompatible with the default installation settings of FreeBSD 9.X which use the new GPT partition scheme. GEOM will overwrite GPT metadata, causing data loss and possibly an unbootable system."

    Кстати, сейчас статья в хэндбуке стала совсем никакой:
    https://www.freebsd.org/doc/handbook/geom-mirror.html

    Я уже успел пересоздать зеркало по рекомендациям этой статьи (gmirror+GPT). Оказалось, что они уже не работают, по крайней мере, во FreeBSD 10.3
    С необходимыми корректировками зеркало заработало, но GEOM и GEOM_MIRROR каждый по своему сообщают, что "mirror/gm0 GPT (224G) [CORRUPT]".
    Всё работает, но:
    # gpart status mirror/gm0
    Name Status Components
    mirror/gm0p1 CORRUPT mirror/gm0
    .................................

    Просьба доктору подсказать: "Жить будем?" ;-)
    Есть ли критерий оценки работоспособности созданного зеркала?
    Диски по очереди удалять с ребутом?

    ОтветитьУдалить
    Ответы
    1. Кстати, сейчас в /etc/fstab можно только так:
      # Device Mountpoint FStype Options Dump Pass#
      /dev/mirror/gm0p2 none swap sw 0 0
      /dev/mirror/gm0p3 / ufs rw 1 1

      Удалить
    2. Критерий оценки прост - на работающей системе не должно быть сообщений о CORRUPT от GEOM_PART, и GEOM_MIRROR должен быть в состоянии COMPLETE/ACTIVE.
      Всё описанное в данной статье работало и работает на любых версиях FreeBSD которые выходили с тех времён. Ничего в том коде не менялось. Возможны только две проблемы - это ваш BIOS/SoftRAID выполняет модификацию секторов в конце диска, либо вы продолжаете выполнять действия в неверном порядке ;)

      Удалить
    3. Протестировал с удалением одного из дисков зеркала. Всё работает с такой руганью при загрузке:
      # dmesg | grep GEOM
      GEOM_MIRROR: Device gm0: provider ada1 marked as inactive, skipping.
      GEOM: ada1: the secondary GPT table is corrupt or invalid.
      GEOM: ada1: using the primary only -- recovery suggested.
      GEOM_MIRROR: Device gm0: provider diskid/DISK-BTJR528407P7240AGN marked as inactive, skipping.
      GEOM: diskid/DISK-BTJR528407P7240AGN: the secondary GPT table is corrupt or invalid.
      GEOM: diskid/DISK-BTJR528407P7240AGN: using the primary only -- recovery suggested.
      GEOM_MIRROR: Force device gm0 start due to timeout.
      GEOM_MIRROR: Device mirror/gm0 launched (1/2).
      GEOM: mirror/gm0: the secondary GPT table is corrupt or invalid.
      GEOM: mirror/gm0: using the primary only -- recovery suggested.

      Сделать трюк с полным отключением зеркала в моём случае крайне неудобственно, поскольку это требует корректировки fstab (а у меня крайне неудобный и медленный IPMI).
      Удивляет крайне медленное восстановление зеркала при возвращении диска. На SSD это ожидалось быстрее.
      Кстати, имеет ли смысл отключать журналирование на SSD?
      TRIM подключил (для каждой партиции пришлось отдельно), хотя и руганью от tunefs.

      Удалить
    4. А можно ли как-то провернуть с зеркалом трюк типа:
      # gpart restore -F mirror/gm0 < ada0.gpt
      или после деактивации дисков (мне не удаётся (в "single mode" при загрузке с CD) остановить зеркало через "gmirror stop -f gm0"):
      # gpart backup ada0 > ada0.gpt
      ?
      Или это бесполезное занятие?
      При моих вчерашних экспериментах над GPT+mirror я не смог исправить проблему с помощью этого. При повторной попытке настройки зеркала всё слетало опять.

      Удалить
    5. У вас GPT создано на диске ada1, а не на зеркале mirror/gm0.
      Сначала нужно создать зеркало, после - GPT на этом зеркале. При корректном создании сообщений "GEOM: mirror/gm0: the secondary GPT table is corrupt or invalid." быть не должно.
      Если разделы не смонтированы и в конце диска есть свободное место, то трюк с backup + restore помочь должен.

      Удалить
    6. Извините, но Вы невнимательно прочитали. Я специально написал, что сделал Mirror+GPT, и он заработал с такой проблемой. Сообщение о повреждении GPT возникло только после перезагрузки вновь созданного сервера (специально контролировал).
      Упомянутый вариант GPT+mirror (кстати, ранее официально рекомендовавшийся для FreeBSD) я безуспешно пытался реализовать днём раньше. Кстати, там тестовое зеркало не создавалось даже на отдельном, втором, ещё пустом диске. После перезагрузки зеркала как будто никогда не было, а у GPT оказывалась затёрта таблица в конце диска. Экспериментов на эту тему было проделано много.
      Странно, что для Mirror+GPT у меня не сработало монтирование по меткам в рекомендованных Вами вариантах "/dev/gpt/swap" и "/dev/ufs/root_fs". Никаких "/dev/ufs" не создаётся и вообще никак не удаётся указать устройство по меткам. Моя таблица GPT имеет вид:
      1 freebsd-boot 34 990
      2 freebsd-swap 1024 4194304 swap
      3 freebsd-ufs 4195328 4194304 root_fs

      Я провёл эксперимент насчёт восстановления резервной копии GPT. Делал "gpart recover mirror/gm0". До перезагрузки всё хорошо, но после перезагрузки GPT опять без резервной копии в конце диска. Проверял и исправлял с загрузкой с CD.

      У меня большие сомнения, что это аппаратные глюки, поскольку у сервера нет RAID-контролёра, а диски из хорошо известной серии - "INTEL SSDSC2BP240G4 L2010420". Больше похоже на глюк GEOM_MIRROR, который опять раздружился с GEOM_PART_GPT.
      Был бы очень благодарен за помощь в разборках с этой сложной проблемой. Вы могли бы связаться со мной по почте (она сейчас доступна в профиле)? Я бы переслал Вам для диагностики содержимое последних секторов (уже сделал) и т.п.

      Удалить
    7. Кстати, ещё один нюанс. Мне не удаётся никакими способами (вариантов много, не считая полного удаления) остановить зеркало и выгрузить gmirror (в single mode и с CD). Сначала идут строки, что зеркало разобрано, а потом идёт строка, что зеркало опять собрано.
      Тоже не глюк? ;-)

      Удалить
    8. Извините, что влезаю, сам спотыкался, и Андрей мне помог. Загрузитесь в verbose mode и внимательно изучите логи на предмет упоминания RAID.

      Удалить
    9. Я читал внимательно. То что вы думали что вы делали и то что показывает ядро - не совпадает.
      Если бы вы создали GPT на зеркале то такого сообщения бы не было:
      GEOM: ada1: the secondary GPT table is corrupt or invalid.
      GEOM: ada1: using the primary only -- recovery suggested.

      Ядро сообщило бы:
      GEOM: ada1: the secondary GPT header is not in the last LBA.

      А так же не было бы таких сообщений:
      GEOM: mirror/gm0: the secondary GPT table is corrupt or invalid.
      GEOM: mirror/gm0: using the primary only -- recovery suggested.

      > Экспериментов на эту тему было проделано много.
      Нужно просто понять что выполняет каждая команда, тогда жксперименты будут не нужны.

      > Никаких "/dev/ufs" не создаётся и вообще никак не удаётся указать устройство по меткам.
      Чтобы метки в /dev/ufs/ создались нужно указывать их в newfs -L
      А так же файловая система не должна быть смонтирована не через метку. При монтировании с использованием другого имени все метки в /dev уничтожаются.

      GEOM_MIRROR и GEOM_PART_GPT используют на десятках тысяч машин уже много лет, если бы описываемые вами проблемы были, их вероятно бы уже кто-то заметил. ;-)

      > Сначала идут строки, что зеркало разобрано, а потом идёт строка, что зеркало опять собрано. Тоже не глюк? ;-)
      Не глюк. Это нормальное поведение и соответствует вашими настройкам. Метаданные вашего зеркала доступны через несколько провайдеров. Когда вы останавливаете gmirror, автоматический процесс retaste находит метаданные зеркала на другом провайдере и запускает зеркало снова. Об этом можно догадаться прочитав логи. Чтобы этого избежать рекомедуется отключать неиспользуемые классы GEOM_LABEL через sysctl kern.geom.label.xxx.enable=0. В вашем случае это disk_ident.

      Удалить
    10. Спасибо!
      Я, конечно, уничтожил возможные следы зеркала и GPT (от варианта GPT+mirror) перед тем как попробовать создать Mirror+GPT. Но на этом этапе что-то могло сработать неправильно и при создании Mirror+GPT gmirror наткнулся где-то на остатки старого.
      Других идей нет. Буду пытаться разобраться с этим.

      Удалить
    11. Извините, а монтирование через /dev/label - нормальное решение для использования с gmirror?
      Например, /dev/label/swap вместо /dev/gpt/swap (я где-то встречал упоминания о проблемах с монтирование swap в gmirror).

      Удалить
    12. > а монтирование через /dev/label - нормальное решение для использования с gmirror?

      Вполне, если вам удобно - почему бы и нет?

      Удалить
    13. Тяжёлый случай жизни.
      Решил переделать по второму примеру в хэндбуке (в сочетании с метками). Разобрал (наконец) зеркало. При этом удалил метаданные на выведенном из зеркала диске через через "gmirror remove gm0 ada0" (в порядке паранойи попробовал ещё "gmirror clear ada0"). Потом разрушил зеркало на втором диске "gmirror destroy -f gm0". Попробовал найти и уничтожить предполагавшуюсю там таблицу GPT через "gpart show ada1" "gpart destroy -F ada1". Но таблицы GPT там не оказалось. Всё равно забил весь диск нулями через "dd if=/dev/zero of=/dev/ada1 bs=512". Дальше сработал по мануалу.
      При этом всегда и постоянно выставлял "sysctl kern.geom.debugflags=16" и "sysctl kern.geom.label.disk_ident.enable=0".
      Как только создал зеркало, файловую систему с метками, скопировал данные с ada0 через dump+restore и перезагрузился, обнаружил, что опять резервная таблица GPT на зеркале повреждена.

      Удалить
  15. >Кстати, сейчас в /etc/fstab можно только так:
    ># Device Mountpoint FStype Options Dump Pass#

    Неправда. Использовать метки в fstab по-прежнему можно. Для этого нужно их создать и чтобы они были неотключены в glabel.

    ОтветитьУдалить
    Ответы
    1. Я реально попробовал сделать как было здесь расписано (с метками (да, знаю о них) и т.п.) - не прокатило.
      Вот такой вариант не работает:
      /dev/gpt/swap none swap sw 0 0
      /dev/ufs/root_fs / ufs rw 1 1
      /dev/ufs/tmp_fs /tmp ufs rw,noatime 2 2

      Сервер "Supermicro" 2013 года, но с (вероятно) недавно поставленными Intel SSD. (Получил сервак в работу только что.)

      Удалить
  16. Пробовал создать GPT поверх зеркала с помощью установочного диска FreeBSD 11. Безрезультатно. Стабильно после перезагрузки говорит, что
    GEOM: mirror/gm0: the secondary GPT table is corrupt or invalid.
    GEOM: mirror/gm0: using the primary only -- recovery suggested.
    gmirror пишет в последний сектор. Вторая таблица GPT создается в предпоследнем секторе. Что происходит после перезапуска машины - понять пока не могу.
    GPT создаю именно в mirror/gm0.

    ОтветитьУдалить
    Ответы
    1. gptboot может выполнять перезапись GPT при загрузке (он меняет флаги на разделах - bootme, bootonce, bootfailed). Возможно там имеется какая-то проблема или проблема связана с вашим BIOS. Нужно искать кто портит метаданные.
      Как проверить:
      1. Создаёте GPT на зеркале. Сохраняете первые и последние 40 секторов с зеркала или диска (большой разницы нет), + вывод gpart list. Выключаете машину.
      2. Цепляете диски к другой системе, проверяете в каком состоянии зеркало и GPT. Снова сохраняете первые и последние 40 секторов и вывод gpart list.
      3. Возвращаете диски обратно, загружаетесь и снова сохраняете первые и последние 40 секторов и gpart list.
      4. Сравниваете результаты и делаете выводы.

      Удалить
  17. Загрузка с компакта на другой машине:

    root@:~ # grep GEOM /var/log/messages
    Feb 7 09:38:29 kernel: GEOM_MIRROR: Device mirror/gm0 launched (1/1).
    Feb 7 09:38:29 kernel: GEOM: mirror/gm0: the secondary GPT table is corrupt or invalid.
    Feb 7 09:38:29 kernel: GEOM: mirror/gm0: using the primary only -- recovery suggested.
    root@:~ # gmirror status
    Name Status Components
    mirror/gm0 COMPLETE ada1 (ACTIVE)
    root@:~ # gpart show
    => 40 488397088 mirror/gm0 GPT (233G) [CORRUPT]
    40 488397088 - free - (233G)


    На исходной машине:

    root@:~ # gmirror status
    Name Status Components
    mirror/gm0 COMPLETE ada0 (ACTIVE)
    root@:~ # gpart show
    => 40 488397088 mirror/gm0 GPT (233G) [CORRUPT]
    40 488397088 - free - (233G)

    root@:~ # grep GEOM /var/log/messages \
    ?
    Feb 7 10:03:18 kernel: GEOM_MIRROR: Device mirror/gm0 launched (1/1).
    Feb 7 10:03:18 kernel: GEOM: mirror/gm0: the secondary GPT table is corrupt or
    invalid.
    Feb 7 10:03:18 kernel: GEOM: mirror/gm0: using the primary only -- recovery su
    ggested.
    root@:~ #


    Дампы все есть.

    ОтветитьУдалить
    Ответы
    1. Не, давайте делать всё в точности как написано выше. Нужен вывод gpart list, а не gpart show.
      1. Сразу после создания:
      # gpart list > list.00
      # dd if=/dev/mirror/gm0 of=./primary.00 count=40
      # dd if=/dev/mirror/gm0 of=./secondary.00 skip=`diskinfo mirror/gm0 | awk '{print $4-40}'`
      2. После загрузки:
      # gpart list > list.01
      # dd if=/dev/mirror/gm0 of=./primary.01 count=40
      # dd if=/dev/mirror/gm0 of=./secondary.01 skip=`diskinfo mirror/gm0 | awk '{print $4-40}'`

      Удалить
    2. root@:~ # gpart destroy mirror/gm0
      mirror/gm0 destroyed
      root@:~ # gmirror status
      Name Status Components
      mirror/gm0 COMPLETE ada0 (ACTIVE)
      root@:~ # gmirror destroy gm0
      GEOM_MIRROR: Device gm0: provider mirror/gm0 destroyed.
      GEOM_MIRROR: Device gm0 destroyed.
      root@:~ # diskinfo ada0
      ada0 512 250059350016 488397168 0 0 484521 16 6
      3
      root@:~ # dd if=/dev/zero of=/dev/ada0 count=40
      40+0 records in
      40+0 records out
      20480 bytes transferred in 0.045746 secs (447692 bytes/sec)
      root@:~ # dd if=/dev/zero of=/dev/ada0 oseek=488397127
      dd: /dev/ada0: end of device
      42+0 records in
      41+0 records out
      20992 bytes transferred in 0.039999 secs (524811 bytes/sec)
      root@:~ # gmirror label -v gm0 ada0
      GEOM_MIRROR: Device mirror/gm0 launched (1/1).
      Metadata value stored on ada0.
      Done.
      root@:~ # gpart create -s gpt mirror/gm0
      mirror/gm0 created
      root@:~ # gpart add -t freebsd-boot -s 128K mirror/gm0
      mirror/gm0p1 added
      root@:~ # gpart add -t freebsd-swap -s 4G mirror/gm0
      mirror/gm0p2 added
      root@:~ # gpart add -t freebsd-ufs -s 2G mirror/gm0
      mirror/gm0p3 added
      root@:~ # gpart add -t freebsd-ufs mirror/gm0
      mirror/gm0p4 added
      root@:~ # gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 mirror/gm0
      partcode written to mirror/gm0p1
      bootcode written to mirror/gm0
      root@:~ # gpart list > /tmp/list.00
      root@:~ # dd if=/dev/mirror/gm0 of=/tmp/primary.00 count=40
      40+0 records in
      40+0 records out
      20480 bytes transferred in 0.011387 secs (1798523 bytes/sec)
      root@:~ # dd if=/dev/mirror/gm0 of=/tmp/secondary.00 skip=`diskinfo mirror/gm0 |
      awk '{print $4-40}'`
      40+0 records in
      40+0 records out
      20480 bytes transferred in 0.011399 secs (1796690 bytes/sec)

      Сейчас сделаю на другой машине и отпишусь.

      Удалить
    3. Разница в выводе gpart list, кроме "state", в кол-ве entries: 128 при создании и 152 после перезапуска. В primary отличий нет. Secondary отличается.

      Удалить
    4. Отправьте мне на email все полученные файлы и /var/run/dmesg.boot.

      Удалить
  18. Большая просьба сообщить чем завершилось дело по последнему инциденту.
    Он в точности совпал с моим, который был раньше.

    ОтветитьУдалить
    Ответы
    1. Ничем. На сколько я помню, выяснили, что вероятно BIOS выполняет запись данных в область backupt GPT header. Вот PR на тему https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=218026.

      Удалить
    2. Спасибо, понятно. Близко к моим выводам.
      Я предполагал, что это делает хитрый контролёр внутри SSD, но с учётом обнаруженных аналогичных проблем с USB-устройствами больше похоже на хитрый BIOS. ;-)

      Удалить