воскресенье, 20 ноября 2011 г.

FreeBSD mini-summit в Москве

В субботу 19-го ноября в Москве, в офисе компании Рамблер прошёл "русскоязычный FreeBSD mini-summit". Организация этого мероприятия произошла довольно спонтанно, буквально три недели назад во внутренней рассылке Глеб Смирнов предложил провести встречу, подобную той, что была летом в Киеве, и вот - собралось почти 30 человек. Кроме коммитеров FreeBSD на саммите были гости из NetBSD, а так же интересующиеся ребята из Яндекса, Рамблера и Вадим Гончаров :).
 Планировалось, что каждый участник расскажет о том, чем занимается в данное время и, возможно, будет подготовлено несколько докладов. Так же, в планах было провести некоторое время за "хаканьем" кода, но, к сожалению, я уже не успел на этом поприсутствовать.
Итак, немного о темах докладов и обсуждений.
Глеб Смирнов (glebius@) рассказал о новой реализации CARP, почему ему не нравилась старая, что уже сделано и что ещё предстоит сделать. Во время обсуждения прозвучало несколько интересных вопросов и предложений, которые, как мне показалось, Глеб взял на заметку. 
Лев Серебряков (lev@) рассказал о своих проектах по переработке кода модуля geom_raid5 и системе оповещения о событиях в geom.
Александр Черников (melifaro@) рассказал для чего нужен MPLS, об уже проделанной работе по реализации поддержки MPLS во FreeBSD и bird, о текущих проблемах в интерфейсах ядра, тормозящих разработку.
Андрей Пантюхин (sat@) рассказал о проблемах в нашей систем управления rc.d и пытался выяснить какими решениями пользуются присутствующие для обхода этих проблем.
Сергей Скворцов (skv@) выступил с докладом о некритичных, но усложняющих жизнь проблемах в системе портов и предложил варианты по их решению.
Игорь Сысоев (автор nginx) рассказал о проблемах во FreeBSD, мешающих ему, как разработчику высокопроизводительного сервера, а так же поделился мыслями о том, какие API  ему хотелось бы видеть во FreeBSD.
Руслан Ермилов (ru@) задал вопрос присутствующим - нужен ли нам проект по переводу man-страниц? Сошлись на том, что проект нужен, но для продолжения этой работы необходимы свежие силы. Причём как среди переводящих, так и среди редакторов, и рецензентов.
В целом, мероприятие прошло успешно, но, половины дня для такого количества человек всё же было маловато.

вторник, 8 ноября 2011 г.

Ликбез по UEFI

Многие пользователи ПК имеют представление о том, что такое BIOS, для чего и как он работает. Но в последнее время появилась альтернатива, стремительно вытесняющая BIOS с наших ПК, а на серверном оборудовании уже прочно обосновавшаяся - это EFI и его более современный родственник UEFI.

Extensible Firmware Interface (EFI) впервые был предложен компанией Intel в качестве замены BIOS для своей новой 64-битной платформы IA64 (Itanium). Позднее Intel выпустила обновлённую спецификацию EFI 1.10, которая уже не привязывалась к платформе Itanium и могла использоваться для x86.

Чтобы труды Intel не пропали зря и народ обратил внимание на EFI был организован Unified EFI Forum, куда вошло несколько крупных компаний и который занялся дальнейшим развитием спецификации EFI. Чем он уже десять лет успешно занимается и на данный момент актуальной версией спецификации является UEFI 2.3.1.

Что же описывает эта спецификация? Честно говоря - МНОГО всего. Более 2000 страниц, и это только один из нескольких документов. UEFI firmware уже можно сравнивать с операционными системами. Для UEFI есть свои драйверы, свои сервисы и приложения. Даже есть свой шелл, который описан в отдельном документе UEFI Shell Specification. А вообще, конечно, идея правильная. Хорошо, когда всё стандартизовано и есть конкуренция, чего нельзя было сказать о BIOS.

Кстати, таблица GPT тоже описана в спецификации UEFI.

Итак, как же всё это работает? Разработчик аппаратной платформы пишет firmware, которая соответствует спецификациям UEFI и выполняет действия по описанным протоколам. Существует несколько инструментариев для разработчика связанных с UEFI компонентов. Некоторые из них - закрытые и коммерческие, некоторые - с открытым исходным кодом и свободно распространяемые. Разрабатывать firmware на ассемблере теперь нет нужды, хотя это тоже возможно. К интрументариям разработчика прилагаются все необходимые библиотеки и заголовочные файлы для разработки на языке Си. То же относится и к драйверам, и к EFI приложениям.

Так вот, эта firmware подобно BIOS помещается во flash память и в общем-то, цель у неё такая же - инициализировать оборудование для работы и передать управление операционной системе. Архитектурно она организована модульно и состоит из нескольких уровней, выполняющихся на различных этапах загрузки с момента включения питания. Подробную схему того, какие модули выполняются в какой момент времени, можно посмотреть в UEFI Platform Initialization Specification. Если в кратце, то это: предварительная инициализация памяти, процессоров, устройств и подготовка окружения для запуска следующих уровней firmware; загрузка драйверов устройств и запуск менеджера загрузки, который выполняет выбор устройства и запуск загрузчика операционной системы.

Для чего нужны драйверы? Драйверы должны поставляться производителями периферийных устройств. Они используются firmware для организации взаимодействия между устройством и UEFI приложением. С их помощью firmware может организовывать так называемые Runtime и Boot Services. Эти сервисы, в свою очередь, предоставляют набор функций, которые могут использовать UEFI приложения, сами драйверы, а так же загрузчик операционной системы.

Например, на сервере есть какой-то RAID контроллер с UEFI драйвером. Этот драйвер предоставляет базовые возможности доступа к содержимому своих RAID-массивов на блочном уровне через Boot Services. Т.е. например, загрузчик или какое-то другое UEFI приложение, используя определённые в спецификации API и протоколы, может прочитать информацию с тома RAID контроллера и, к примеру, выполнить загрузку ядра операционной системы. После загрузки ядро должно завершить работу с Boot Services и использовать свой полнофункциональный драйвер.

Другой пример - драйвер для сетевого адаптера может предоставить доступ к сети для загрузки операционной системы, либо для какого-то UEFI приложения, работающего с сетью. Эти драйверы могут предоставлять доступ к адаптеру не только в качестве Boot Services, но и как Runtime Services. Т.е. если у операционной системы нет драйвера для такого адаптера, то она может использовать стандартный API и продолжать работу с адаптером (на практике о таком использовании сетевых UEFI драйверов никто не слышал ;).

Вернёмся от драйверов к менеджеру загрузки. В его задачи входит выбор устройства загрузки и UEFI приложения в соответствии с настроенным порядком загрузки. Порядок определяется глобальными переменными из NVRAM, т.е. грубо говоря, настройками "BIOS". Например, если после инициализации UEFI firmware на сервере выбрать запуск меню настроек, то там отобразится список, порядок пунктов в котором будет выбран на основании этих самых глобальных переменных из NVRAM. В этом же списке могут оказаться дополнительные драйверы, загрузчики операционных систем, дополнительные UEFI приложения, найденные на EFI разделах дисков.

В спецификации UEFI в главе о таблице разделов GPT определены только два зарезервированных уникальных идентификатора GUID для типов разделов. Один из них используется для EFI System Partition. Этот раздел в таблице GPT используется для хранения дополнительных UEFI приложений, драйверов и загрузчиков операционных систем. Внутри этого раздела находится файловая система FAT с некоторыми дополнительными возможностями и требованиями. Сами же приложения представляют собой бинарники в формате PE/COFF (Microsoft Portable Executable and Common Object File Format).
Т.е. при желании можно смонтировать этот раздел и посмотреть, что там находится. Как, впрочем, и разместить там дополнительные приложения. Только необходимо поддерживать требуемую иерархию и именование файлов в файловой системе.

Дополнительные приложения могут выполнять самые разные функции. Например, это могут быть программы для диагностики оборудования, сетевые приложения, утилиты для работы с дисками и разделами, наконец - командный интерпретатор UEFI Shell.

суббота, 29 октября 2011 г.

Отчёт: Август - Октябрь

Последнее время на блог всё не находилось времени. Завал на работе, командировки, проверки, комиссии, отмена перехода на зимнее время... В общем, хочу рассказать обо всём понемногу.

Во-первых, хочу ещё раз поздравить Александра Черникова с награждением коммит битом за его настойчивость в продвижении своих патчей :).

По причине отсутствия времени и заморозки кода коммитил мало. Глядя на архив почты можно отметить:
  • добавление в man gpart секции BOOTSTRAPPING, посвящённой образам загрузочного кода, которые используется во FreeBSD с различными таблицами разделов;
  • исправления в gpart(8), fdisk(8), boot0cfg(8);
  • ликвидирована возможная в некоторых случаях паника в geom_part.
Что касается netmond, то всё что было "указано" в ТЗ - решено, заказчик доволен. Окончательную версию можно брать здесь.

Сейчас взялся за решение нескольких PR касающихся bsnmpd, в частности решил переделать реализацию доступа к информации о дисках и разделах в модуле hostres.

В geom_part_gpt была добавлена поддержка Boot Camp. Конфигурироваться из FreeBSD оно не может, но система может обнаруживать наличие Boot Camp и стараться не сломать его, если будут производиться какие-либо изменения в таблице GPT.

И ещё, после командировки заезжал в Москву, посетил офис Яндекса:



По внутреннему обустройству видно, что ребята живут на работе и им это нравится :)

вторник, 9 августа 2011 г.

netmond на FreeBSD amd64

Обращаюсь к тем, кто использует у себя в хозяйстве netmond. Если у вас есть возможность протестировать его работу на FreeBSD amd64, попробуйте вот эту версию. Из отличий от того, что есть в портах:
  • включены патчи, которые идут отдельно к порту;
  • теперь оно компилируется на amd64 без проблем;
  • часть дублирующего базовые возможности системы кода удалена;
  • убраны лишние зависимости.
От тестирования интересует на сколько сильно его работа отличается от того, как оно работало раньше (на amd64 замечены непонятные аномалии). Как оно ведёт себя на большом количестве объектов. Если кто-то попробует, буду благодарен за краткий отчёт мне на email.

среда, 27 июля 2011 г.

Доступ к образам дисков VirtualBox из host системы

В списке рассылки freebsd-emulation был задан вопрос "как получить доступ к содержимому образа диска от VirtualBox?". Задача показалась мне интересной.

Немного погуглив нашёл вот такое описание формата. Прочитав его, немного покопался в исходниках VirtualBox и вот, за пару вечеров написал GEOM модуль для доступа к этим образам.

Модуль простенький, рассчитан он на одну версию метаданных (хотя добавить старые версии не сложно, но лень и не на чем тестировать), предоставляет доступ только для чтения. Код можно посмотреть здесь. Пользоваться просто - загружаете модуль, подключаете образ диска через mdconfig и, теоретически, он должен обнаружиться и для него будет создан провайдер с суффиксом .vdi. Примерно вот так:

# make 
# make load
/sbin/kldload -v /usr/home/butcher/work/vbox/mod/geom_vdi.ko
Loaded /usr/home/butcher/work/vbox/mod/geom_vdi.ko, id=5
# sysctl debug.bootverbose=1
debug.bootverbose: 0 -> 1
# mdconfig -f 10G_GPT_UFS.vdi
md0
GEOM_VDI: valid signature detected.
GEOM_VDI: Provider md0.vdi created.
# gpart show md0.vdi
=>      34  20971453  md0.vdi  GPT  (10G)
        34       256        1  freebsd-boot  (128k)
       290   2097152        2  freebsd-swap  (1.0G)
   2097442   4194304        3  freebsd-ufs  (2.0G)
   6291746  14679741        4  freebsd-ufs  (7G)

# geom vdi list
Geom name: md0.vdi
dataoffset: 41472
blocksoffset: 512
blockscount: 10240
blocksize: 1048576
mediasize: 10737418240
Providers:
1. Name: md0.vdi
   Mediasize: 10737418240 (10G)
   Sectorsize: 512
   Mode: r0w0e0
Consumers:
1. Name: md0
   Mediasize: 468754944 (447M)
   Sectorsize: 512
   Mode: r0w0e0

четверг, 30 июня 2011 г.

ipfw call / return

28 июня официально начался "Code Slush for 9.0-RELEASE", который так же известен как "Feature Freeze". Т.е. теперь в head/ бранч не разрешается вносить новый функционал. Цель этого мероприятия - стабилизировать состояние системы и сосредоточиться на поиске и исправлении ошибок. На 17-ое июля запланирован "Code Freeze" после которого последует выход первой бета версии FreeBSD 9.0.

Теперь о теме. Вадим Гончаров, узнав о предстоящем "Code Slush", выдал очередной патч для ipfw, который во что бы то ни стало должен оказаться в 9.0-RELEASE. :)
Патч добавляет два новых действия в ipfw: "call" и "return". Первая команда выполняет "вызов" подпрограммы, вторая - возврат из подпрограммы к следующему правилу. На практике, конечно, никаких подпрограмм не вызывается. Команда "call" принимает в качестве аргумента номер правила, к которому нужно выполнить переход. Переход осуществляется аналогично тому, как это делается для команды "skipto", только он может осуществляться в любом направлении по отношению к текущему правилу. Кроме того, перед выполнением перехода команда "call" сохраняет во внутреннем стеке номер своего правила в качестве точки возвращения. Размер стека ограничен 16 элементами. Это значит, что "подпрограмма" может содержать в себе другие вызовы "call" в другие "подпрограммы".
Возврат из "подпрограммы" осуществляется размещением правила с командой "return". У неё нет аргументов. Она находит в стеке первый элемент (по дисциплине LIFO), извлекает сохранённый номер правила и осуществляет возврат к следующему правилу с номером большим на 1.

Теперь о применении этого. Несомненно, есть несколько задач, в которых данный функционал может оказаться полезным. Но в то же время, скорость появления этого патча и практически полное отсутствие его тестирования ставит под сомнение плюсы, которые можно получить от него. Так что, если найдутся желающие на широких каналах протестировать этот функционал, было бы неплохо. Для этого, в общем-то, достаточно скачать образ 9.0-CURRENT и протестировать ;)

Кстати, Hiroki Sato сообщил о возобновлении сборки снепшотов FreeBSD CURRENT на ресурсе allbsd.org. Что является отличной новостью, для меня по крайней мере. Обычно для тестирования чего-либо бывает быстрее скачать образ и установить систему, чем обновляться из исходников.

пятница, 24 июня 2011 г.

Что нового?

Последние несколько недель в свободное время занимался обработкой открытых PR. В основном они были связаны с ipfw, dummynet и ipfw_nat, но не все. В общем, сократил количество открытых проблем где-то на полтора десятка, может даже на два. Считать, если честно - лень :)

Что хотелось бы отметить - это несколько исправлений и патчей, добавляющих новую функциональность. Желательно бы их получше оттестировать перед MFC. И, кстати говоря, вот уже почти неделю назад должен был начаться "code slush" в связи с подготовкой к выпуску 9.0-RELEASE.

Итак, первое исправление затрагивает kern/136695, kern/147720 и kern/150798. Связано оно с функцией форвардинга пакетов в ipfw и использованием динамических правил. Теперь реализация аналога reply-to из PF не должна составить труда и в ipfw (описание этого случая можно найти у Вадима Гончарова в блоге).

Следующее исправление связано с kern/122109, kern/129093 и kern/157379. Оно делает поведение ipfw_nat более похожим на natd. Возможно, те кто говорил, что ipfw_nat работает не так с правилами, с которыми работает natd, теперь вздохнут с облегчением. Теперь ipfw_nat будет более "гуманно" относится к пакетам, которые libalias не захотела обрабатывать. Раньше такие пакеты просто отбрасывались, что приводило к симптомам, хорошо показанным в перечисленных PR.

Теперь о новом функционале в ipfw_nat - kern/157867. Это аналог опции globalport для natd. Если у вас сконфигурировано несколько NAT'ов, то теперь можно одним правилом заставить ipfw проверять пакет сразу для всех таблиц трансляций. Для этого добавлено новое "кодовое слово"- nat global. Пакет будет обрабатываться в соответствии с конфигурацией той таблицы, в которой найдётся подходящее состояние.


В модуль libalias, обрабатывающий FTP соединения внесены изменения kern/157957, благодаря которым он корректно работает при использование опции redirect_port для ipfw_nat. Кстати, Глеб Смирнов изменил обработку опций NAT для ipfw(8). Теперь командная строка не ограничена длиной NAT_BUF_LEN и при настройках NAT можно указывать сколько угодно опций.

Кроме того, для ipfw setfib добавлена поддержка tablearg - kern/156410.

Еще было несколько мелких исправлений, которые не так интересны. Но в общем, за большинство из этих изменений и исправлений можно поблагодарить Александра Черникова. Именно у него хватило терпения и желания, копаться в коде, который местами далеко не очевиден, писать патчи и продвигать их, чтобы они оказались в системе.

Да, ещё. По проблеме с загрузкой с ZFS. Вчера John Baldwin добавил исправление в загрузочный код, которое, вероятно исправит большинство проблем.

четверг, 9 июня 2011 г.

Выравнивание разделов в gpart. Итоги.

Некоторое время назад я публиковал заметку с патчами на тему выравнивания разделов. С того времени этот функционал несколько раз подвергался изменениям. Больше никаких изменений в этой области я не планирую, поэтому опишу то что сделано.

Многие из вас слышали, что некоторые современные жесткие диски уже выпускаются с размером сектора в 4 Кбайт. Хотя на данный момент я не слышал ни об одном из них, который бы честно в этом признавался. Все они продолжают рапортовать о том, что у них размер сектора равен 512 Байтам. В связи с чем часто возникают проблемы с производительностью при работе с такими дисками. Для обхода этой проблемы есть несколько решений. Одно из последних появилось во FreeBSD 9.0 совсем недавно - с ревизией r222520.

Александр Мотин добавил в драйвер ada(4) новый quirk - ADA_Q_4K. Который говорит драйверу установить geom провайдеру размер stripesize равным 4 Кбайта. На основе этой информации все консьюмеры этого провайдера могут проявлять свой "интеллект" и пытаться выполнить некоторые оптимизации при работе.

В драйвер уже "вшита" информация о некоторых диска, размер сектора которых 4 Кбайт. Для них stripesize будет установлен автоматически. Для других же дисков, которые не прописаны в драйвере, можно установить данный quirk через loader.conf. Так, для диска ada3 это будет примерно так:

# echo 'kern.cam.ada.3.quirks="1"' >> /boot/loader.conf

проверить работоспособность можно, например, так:

# geom disk list ada3
Geom name: ada3
Providers:
1. Name: ada3
   Mediasize: 80026361856 (74G)
   Sectorsize: 512
   Stripesize: 4096
   Stripeoffset: 0
   Mode: r2w2e4
   descr: SAMSUNG HD080HJ/P
   ident: S0DEJ1NL817767
   fwsectors: 63
   fwheads: 16


Теперь вернёмся к gpart(8). Я добавил туда поддержку stripesize, а так же возможность вручную задавать нужное выравнивание:

# gpart
usage: gpart add -t type [-a alignment] [-b start] [-s size] [-i index] [-l label] [-f flags] geom
 ...
       gpart resize -i index [-a alignment] [-s size] [-f flags] geom 

У двух подкоманд "add" и "resize" появилась новая опция -a alignment. Которую можно задавать как в секторах, так и в байтах. Наличие этой опции влияет на то, как gpart рассчитывает границы разделов. Например, если вы хотите, чтобы раздел был выравнен по границе в 4 Кбайт, то достаточно указать "-a 4k" дополнительно к команде "gpart add". При использовании stripesize выравнивание можно не задавать, оно будет "подхвачено" автоматически.

Для проверки, выравнен раздел или нет, можно использовать команду diskinfo(8):
# diskinfo -v ada0p3
ada0p3
        512             # sectorsize
        75731098112     # mediasize in bytes (70G)
        147912301       # mediasize in sectors
        4096            # stripesize
        1024            # stripeoffset
        146738          # Cylinders according to firmware.
        16              # Heads according to firmware.
        63              # Sectors according to firmware.
        S0DEJ1NL817767  # Disk ident.

#  echo 1024 % 4096 | bc
1024
Следующая после diskinfo(8) команда подсчитывает остаток от деления между stipeoffset и желаемым выравниванием. Если получаемое значение не ноль, значит раздел не выравнен.

четверг, 26 мая 2011 г.

Назначение различных образов загрузочного кода во FreeBSD

Со времени появления поддержки таблиц GPT и файловой системы ZFS во FreeBSD содержимое каталога /boot довольно сильно изменилось. Я имею ввиду, сколько различных образов загрузочного кода теперь там находится.

> ls /boot/*boot* /boot/*mbr*
/boot/boot              /boot/boot1             /boot/gptboot           /boot/pmbr
/boot/boot0             /boot/boot2             /boot/gptzfsboot        /boot/pxeboot
/boot/boot0sio          /boot/cdboot            /boot/mbr               /boot/zfsboot
В этой заметке я попробую восполнить недостаток документации и описания этих файлов, рассказав для чего они необходимы.

Итак, по-порядку. BIOS передаёт управление загрузочному коду, хранящемуся в MBR. Его задача - найти на диске загрузочный код следующей ступени, который для таблицы разделов MBR обычно находится в первом секторе активного раздела. Т.е. он должен прочитать таблицу разделов MBR, найти в ней раздел, помеченный активным и передать управление коду, находящемуся в первом секторе этого раздела. Эти задачи выполняет код, копия которого находится в файле /boot/mbr. Более продвинутая его версия - это менеджер загрузки /boot/boot0. Он имеет простейший функционал взаимодействия с пользователем - меню для выбора раздела или диска, с которого выполнять загрузку.

Далее вступает в работу загрузочный код первой ступени /boot/boot1. Он схож по функционалу с тем, что делает /boot/mbr. Разница в том, что он должен считать таблицу разделов BSD и код второй ступени загрузки /boot/boot2. Обычно они используются вместе в виде образа /boot/boot. Т.е. /boot/boot это склееные вместе /boot/boot1 и /boot/boot2.

Вторая ступень загрузки уже более функциональна и может считывать файлы с UFS. Задача этого кода загрузить и передать управление загрузчику /boot/loader (третьей ступени), либо самому ядру /boot/kernel/kernel.

Загрузочный код /boot/zfsboot выполняет те же функции, что и /boot/boot, но для файловой системы ZFS. Он тоже состоит из двух частей. Первая часть аналогично boot1 необходима для поиска и запуска второй ступени, которая уже может прочитать файлы с ZFS и запустить ядро, либо третью ступень /boot/zfsloader.

Теперь что касается GPT. Для таблицы GPT во FreeBSD пока нет подобного /boot/boot0 менеджера загрузки. Но для систем, которые не используют EFI, загрузка с GPT происходит аналогично тому, как это делается для MBR. Т.е. BIOS передаёт управление загрузочному коду, находящемуся в первом секторе диска. А там должна находиться копия /boot/pmbr. Этот код выполняет поиск раздела с типом "freebsd-boot" по таблице GPT. Если он находит его, то загружает его содержимое в память и передаёт туда управление.

Здесь уже могут быть варианты. Первый - /boot/gptboot. Его задача проверить корректность таблиц и заголовков GPT (посчитать и сверить контрольные суммы), а затем найти в таблице раздел с типом "freebsd-ufs", попытаться загрузить с этого раздела /boot/loader или ядро. Если это не получается, он ищет следующий раздел. Кроме того, не так давно pjd@ добавил поддержу специальных GPT-атрибутов bootme и bootonce, с помощью которых можно устанавливать приоритетность загрузки разделов, на случай, если несколько копий/версий FreeBSD находятся на одном диске.

Второй вариант - /boot/gptzfsboot. Этот код представляет собой комбинацию zfsboot  и gptboot. Он выполняет поиск GPT разделов с типом "freebsd-zfs", на которых он ищет пулы. На самом деле логика его работы немного сложнее, так как пулы могут состоять из нескольких устройств. Но цель его - загрузка /boot/zfsloader или ядра с ZFS пула.

В заключение несколько слов о том, где должен располагаться загрузочный код, для того чтобы он выполнил свои задачи. Думаю, не надо упоминать о том, что находясь в каталоге /boot он выполниться никак не сможет, поэтому эти образы должны быть записаны в определённый области на диске. Для записи загрузочного кода на диск обычно используется команда "gpart bootcode", но некоторые образы требуют специальных "манипуляций".

Например, образы mbr, boot0, pmbr должны быть записаны в первый сектор диска. Образ /boot/boot - в начало MBR раздела с типом "freebsd". Образы gptboot и gptzfsboot должны быть записаны на GPT раздел с типом "freebsd-boot". Специальные манипуляции нужны для загрузочного кода zfsboot. Первые 512 байт его должны быть записаны в начало раздела или диска, на котором создан ZFS пул. Оставшаяся часть должна быть записана со смещением в 512 кбайт от начала диска или раздела. Т.е. для случая, когда пул создан на целом диске ada0, загрузочный код записывается вот так:
# dd if=/boot/zfsboot of=/dev/ada0 count=1
# dd if=/boot/zfsboot of=/dev/ada0 skip=1 seek=1024

четверг, 28 апреля 2011 г.

Метки разделов и выравнивание в gpart


На этой неделе я опубликовал два патча, в тестировании которых мне нужна помощь, возможно, среди читателей найдутся желающие :)

Первый патч предназначен для решения проблемы с метками разделов, которые, как известно, реализуются сейчас классом GEOM_LABEL. Основная проблема в том, что для приемлемой работы с метками GEOM_LABEL предъявляет некоторые требования к провайдерам. Например, обнаружение меток GEOM_LABEL выполняет только во время tasting. Изменение меток может быть обнаружено только при условии использования механизма spoiling с последующим retaste. Что при существующей реализации класса GEOM_PART не представляется возможным.
Класс GEOM_PART управляет таблицей разделов и метки этих разделов хранятся в таблице, а не на провайдере раздела. Поэтому, при изменении метки механизм spoiling'а не запускается для провайдера раздела.

Предлагаемый мной патч отключает реализацию меток gpt/gptid в GEOM_LABEL и добавляет новый класс PART::LABEL. Он тесно связан с классом PART и, кроме того, имеет несколько функциональных отличий от GEOM_LABEL. Во-первых, он не использует механизм tasting, объекты класса и его провайдеры создаются по инициативе класса PART. Во-вторых, он не использует механизм spoiling, поэтому его провайдеры существуют всё время, а не исчезают, когда какой либо связанный провайдер начинает использоваться. Благодаря этому устраняется проблема с изменением меток, которые становятся видны сразу после изменения. И, на мой взгляд, удобнее, когда метки в /dev существуют всегда. К тому же, кроме реализации gpt/gptid я добавил поддержку меток в схемы PC98 и APM.

Я планирую включить этот патч в head/ примерно через неделю. Второй патч не вносит изменений в ядро. Он добавляет к утилите gpart(8) новую опцию "-а alignment", при использовании которой gpart выполняет выравнивание создаваемых разделов на заданную величину. Например так:

# gpart create -s gpt md0
md0 created
# gpart show md0
=>    34  409533  md0  GPT  (200M)
      34  409533       - free -  (200M)

# gpart add -t freebsd-boot -s 128k -a 4k md0
md0p1 added
# gpart add -t freebsd-ufs -s 60m -a 4k md0
md0p2 added
# gpart add -t freebsd-ufs -a 4k md0
md0p3 added
# gpart show md0
=>    34  409533  md0  GPT  (200M)
      34       6       - free -  (3.0K)
      40     256    1  freebsd-boot  (128K)
     296  122880    2  freebsd-ufs  (60M)
  123176  286384    3  freebsd-ufs  (139M)
  409560       7       - free -  (3.5K)

четверг, 14 апреля 2011 г.

web-камера в skype во FreeBSD - теперь работает!

Использование Web-камеры во FreeBSD некоторое время назад было довольно больной темой. Проблема частично решилась с появлением webcamd и cuse4bsd. Нет, конечно в портах было несколько модулей ядра, реализующих поддержку небольшого списка web-камер, но, к сожалению, такие камеры редко ставят на ноутбуки, да и в продаже их найти сложно.

Два проекта cuse4bsd и webcamd добавили поддержку огромного количества различных камер во FreeBSD. Cuse4bsd - это модуль ядра и библиотека, предоставляющая программный интерфейс для работы с этим модулем. Если вкратце, то используя эту библиотеку в своём приложении вы можете создать псевдоустройство (в нашем случае это /dev/video0), к которому могут обращаться другие программы. Все обращения к этому устройству, такие как ioctl, read, write, и другие через libcuse4bsd перенаправляются к вашему приложению. Вы можете их обработать и отправить результат обратно.

Точно так же webcamd использует эту библиотеку и модуль ядра. Сам же webcamd довольно интересное приложение - он включает в себя часть ядра linux. Если взглянуть в его исходный код, то можно найти кучу обёрток для различных функций, типов, макросов, структур ядра linux, которые позволяют скомпилировать драйверы различных устройств и использовать их в приложении.
Webcamd через libusb может обращаться к различным камерам и тюнерам, которые подключены в системе. В то же время, он создаёт устройства /dev/videoX и используя драйверы, что взяты из ядра linux, выполняет их на уровне пользователя.  Другими словами webcamd  организует взаимодействие между linux-драйвером, реальным устройством и приложениями, которые обращаются из FreeBSD к /dev/videoX.

Всё бы хорошо, большинство web-камер работает, к ним можно обращаться из pwcview, mplayer, vlc и других програм, кроме skype. Это бинарник для linux и он ни в какую не хочет работать с современными камерами. Причин несколько. Skype использует только video4linux1 API и от камеры хочет данные только в определённом формате. Кстати, эти проблемы не специфичные для FreeBSD, в linux они тоже присутствуют.
Но в linux есть решение - пакет libv4l, который включает в себя несколько библиотек - v4l2convert и v4l1compat. Первая осуществляет конвертацию форматов данных, вторая предназначена для приложений, использующих устаревший API video4linux1.

Так вот, используя эти библиотеки в linux можно заставить skype работать с современными камерами. Но во FreeBSD режим эмуляции linux не поддерживает API Video4Linux2, поэтому использовать libv4l не получится.
Системные вызовы (в данном случае это ioctl с кодами V4L2), которые будут идти от libv4l к ядру FreeBSD не будут обработаны, так как они не реализованы.

Но! :)
Мы можем поблагодарить Juergen Lock (nox@). Он выложил патчи, реализующие V4L2 в режиме linux эмуляции. Теперь, используя libv4l камеры работают и в skype, а так же и во Flash в браузере.

Патчи есть для 8-ки и 9-ки. libv4l для linux в портах вроде пока ещё нет, но думаю это вопрос времени. Я нашёл в поисковике такой пакет libv4l-0.6.2-1.fc10.i386.rpm и установил его как учат вот тут.
После этого слегка модифицировал стартовый скрипт skype:

!/bin/sh
export LD_PRELOAD=/usr/lib/libv4l/v4l2convert.so
/usr/local/share/skype/skype --resources=/usr/local/share/skype $@



PS. Вы конечно поняли, что про webcamd я не просто так рассказывал, он у меня тоже установлен и настроен.

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

среда, 16 марта 2011 г.

Варианты загрузки FreeBSD: ZFS пул без таблиц разделов

В списках рассылки freebsd-fs@ и freebsd-stable@ было несколько жалоб на то, что FreeBSD 8.2 и предыдущие сборки 8-STABLE не грузятся при использовании загрузочного кода zfsboot. Сам я никогда его не использовал, у меня везде "стандартная" схема - GPT + 3 раздела (freebsd-boot, freebsd-swap и freebsd-zfs). Решил я проверить эту проблему.

Почти два дня я провел, совмещая работу и эксперименты в virtualbox'е. И это я ещё не все возможные варианты попробовал. У меня была виртуальная машина с 8.1-STABLE, я обновил её и оставил /usr/obj для установки собранной системы на другие образы дисков.

Первым вариантом для тестирования я выбрал ZFS пул, создаваемый на целом диске без использования таблиц разделов. Выбор пал на такую конфигурацию благодаря одному моему коллеге, которого я уже упоминал как-то в своём блоге. Он написал статью, обобщив свой опыт по установке FreeBSD на ZFS. Он же периодически подкидывает мне ссылки на обсуждение своей статьи. Там-то как раз и обсуждался такой метод установки. Установку можно описать буквально несколькими командами (набираю по памяти, мог что-нибудь забыть):

# zpool create z ad6
# zfs create z/root
# cd /usr/src
# make DESTDIR=/z/root installworld distribution installkernel
# zpool set bootfs=z/root z
# zpool set cachefile=/z/root/boot/zfs/zpool.cache z
# cat > /z/root/boot/loader.conf
zfs_load="YES"
vfs.root.mountfrom="zfs:z/root"
^D
# echo 'zfs_enable="YES"' > /z/root/etc/rc.conf
# touch /z/root/etc/fstab
# zfs set mountpoint=none z
# zpool export z
# dd if=/boot/zfsboot of=/dev/ad6 count=1
# dd if=/boot/zfsboot of=/dev/ad6 skip=1 seek=1024

Проблема подтвердилась сразу. Самое неприятное, что никакого удобного способа отладить загрузочный код я не видел. Единственное, что приходило на ум - читать код и вставлять printf'ы в определённые места, для того чтобы хоть как-то отслеживать процесс выполнения загрузочного кода.

Чтение исходников - это часто бывает полезным. Вот, например, объяснение последних двух команд - почему именно такие параметры? ;) Это можно понять из исходного кода.

Образ загрузочного кода zfsboot состоит из двух частей - zfsboot1 и zfsboot2. Первая часть предназначена для записи в первый сектор диска, куда BIOS обычно передаёт управление для загрузки системы. Грубо говоря, zfsboot1 - это образ MBR с небольшой частью загрузочного кода, который выполняет некоторые стандартные манипуляции для загрузчика, загружает zfsboot2, а так же предоставляет ему некоторые сервисные функции. Написан он на ассемблере. Вторая часть - zfsboot2, написана на Си. Она уже обладает значительно большим функционалом, и размер у неё, соответственно, побольше. В частности, она выполняет поиск ZFS пула и загружает из него zfsloader.

Так вот, первая команда dd выполняет запись zfsboot1 в первый сектор диска. Вторая команда выполняет запись zfsboot2 по смещению в 512 кбайт. Это место внутри ZFS во FreeBSD специально зарезервировано под загрузочный код:

/*
 * Size and offset of embedded boot loader region on each label.
 * The total size of the first two labels plus the boot area is 4MB.
 */
#define VDEV_BOOT_OFFSET        (2 * sizeof (vdev_label_t))
#define VDEV_BOOT_SIZE          (7ULL << 19)                    /* 3.5M */
 

Как видно из комментария, его размер может достигать трёх с половиной мегабайт. На данный момент в 9.0-CURRENT с ZFS v28 его размер чуть больше 32кбайт, но для "ровного" числа  он создаётся размером 64 кбайт, в которых чуть меньше половины забито нулями, + 512 байт от zfsboot1.

Вернёмся к решению проблемы. Как мне стало известно из переписки с людьми, сообщившими о проблеме, не работает zfsboot в 9.0-CURRENT примерно с сентября 2010 года. А именно тогда туда были внесены крупные изменения. Методом printf'а я нашёл, что зависание происходит в функции drvread, которая вызывает код чтения секторов диска из zfsboot1. Сравнив содержимое этой функции с тем, что было до тех изменений было замечено всего одно маленькое отличие.
Я вернул убранную строчку и всё заработало. Попутно, была обнаружена ошибка в ассемблерном коде, появившаяся после внедрения ZFS v28. Сейчас я выполняю дополнительные тесты для проверки, не повлияет ли это изменение на другие варианты загрузки, о которых, возможно, напишу позднее. Для тех, кому нужен загрузочный код zfsboot сейчас, то пропатченную версию из 8.2-STABLE можно взять здесь.

Так же, тестируя уже рабочий код zfsboot'а в virtualbox'е обнаружилась другая проблема - если в системе присутствует несколько дисков, а диск с пулом не является первым в списке BIOS'а, то не удаётся загрузиться выбрав устройство загрузки из меню BIOS'а. Возможно это особенность BIOS'а virtualbox'а. Если кто-то может проверить на реальном железе, буду рад комментарию.

среда, 9 марта 2011 г.

Что нового?

... давно ничего не писал сюда (по-моему, сообщение, начинающееся с таких слов, уже было :)
На самом деле я переодически вспоминаю про блог, захожу, смотрю статистику, но почему-то не возникало желания черкнуть что-нибудь. А сегодня вот возникло.

Много всего произошло со времени написания последнего сообщения. На мой взгляд, наиболее интересные и обсуждаемые события (которые мне запомнились):
  1. Официальное объявление об окончании IPv4 адресов;
  2. Выход двух релизов FreeBSD - 7.4 и 8.2;
  3. Выход релиза Debian/kFreeBSD;
  4. Возобновление работ над новой программой установки FreeBSD;
  5. ZFS v28 наконец-то интегрирована в систему.
Забавно было наблюдать за всеобщим ажиотажем вокруг исчерпания адресного пространства IPv4. На различных сайтах то и дело появлялись новости "до исчерпания осталось N дней", и под конец люди уже часы считали. И вот, свершилось. В рассылках, форумах, чатах на несколько дней сразу активизировалось тестирование IPv6. Много вопросов о настройке, об обнаруженных проблемах... Но, прошёл месяц и что-то пыл активистов слегка угас :)
Сужу по организации где работаю я, ну и по ряду контор в нашей "деревне". У всех IPv4 адресов хватает, запасались заранее. Я даже /48 сетку IPv6 себе зарегистрировал почти 2 года назад... Хочется конечно потестировать IPv6, но в нашем городе никто из провайдеров не может обеспечить условий, на данный момент единственный способ - туннели. Изредка почитываю книжку "IPv6 Администрирование сетей", но времени пока на это нет.

Следуя уже устоявшейся традиции релизы FreeBSD были выпущены позднее предполагаемой даты. Если взглянуть на release notes, то видно, что разработка не стоит на месте и было сделано много нового. Хотя, я хронически сижу на CURRENT, и мне эти изменения как-то не особо заметны. Спасибо release notes'ам за весь список :)
Работа по подготовке и выпуску релизов проделана немалая, но не обошлось и без ложки дёгтя в бочке мёда. Как только стало известно о релизах, в списках рассылки и в gnats появились отчёты об обнаруженных проблемах. О чём это говорит? Народ не особо-то жаждет принимать участие в тестировании BETA версий, все надеются на то, что за них это сделают разработчики. А разработчики невсегда могут проверить всё и во всех возможных ситуациях.
От сюда вытекает целая тема для размышления - что запускать в промышленную эксплуатацию RELEASE, STABLE или может CURRENT? И я склоняюсь больше к последним двум, но это только моя точка зрения и она основана на моём опыте, моих задачах и количестве машин :)

Debian GNU/kFreeBSD - ещё одна штука, о которой много говорили. Даже в IRC канале разработчиков FreeBSD её вспоминали не раз и не два. Мнения разные, но стоит признать и принять то, что разработчики Debian достаточно настырные ребята. Я скачал один ISO образ, установил вчера в VirtualBox'е, но пока не смотрел.

Возобновление работ над новой программой установки было быстрым и неожиданным. Если не помните, то Warner Losh некоторое время назад начал работу над интеграцией PC-BSD'шной программы установки. Он даже в head/ уже интегрировал её. И вот, тут появился Nathan Whitehorn с ещё одним инсталлятором - bsdinstall. Причём появился он так внезапно и активно внедряя свой инсталлятор, что даже Warner растерялся. А ещё этот процесс сопровождался обновлением библиотеки libdialog.
Надо заметить, что новая библиотека libdialog коренным образом отличается от нашей старой. Она, конечно, в плане возможностей стала значительно интереснее, но всё так же не позволяет делать то, что хотелось мне реализовать в sade, в связи с чем я и сделал customdlg.
В итоге, Nathan и Warner нашли общий язык и согласились, что стоит объединить усилия и создать нечто на основе того, что уже сделано ими. Это нечто планируется сделать инсталлятором по-умолчанию для FreeBSD 9.0+, релиз которой, кстати, уже не за горами.
Что же касается sade, то Nathan признаёт, что он удобнее его partedit'а и было бы неплохо, интегрировать его в систему. Вот только нужно опять убить кучу времени на изучение этой libdialog и адаптацию того, что уже написано под неё :(

ZFS v28 уже в head/. Я вчера обновил систему на домашнем компе, но ZFS пока не обновлял. На первый взгляд вроде всё работает после обновления, хотя некоторые жалуются на аномально высокую нагрузку. Через пару дней попробую обновиться...

О своей деятельности сказать особо нечего, закрыл несколько PR связанных с паниками в GEOM, в ноду ng_one2many добавил новый алгоритм NG_ONE2MANY_XMIT_FAILOVER (патч от Максима Игнатенко). Вчера добавил новый ключик для команды `gpart show -p`. Предназначен он для вывода имён провайдеров вместо индексов разделов:

> gpart show -p
=>       34  156301421    ada0  GPT  (75G)
         34        512  ada0p1  freebsd-boot  (256K)
        546    8388608  ada0p2  freebsd-swap  (4.0G)
    8389154  147912301  ada0p3  freebsd-zfs  (71G)