Показаны сообщения с ярлыком ZFS. Показать все сообщения
Показаны сообщения с ярлыком ZFS. Показать все сообщения

вторник, 7 августа 2012 г.

Обновление загрузчика

После долгого перерыва, не дождавшись каких-либо комментариев, я наконец-то закоммитил большую часть изменений в коде загрузчика в head/ ветку.

Немного об изменениях. Было добавлено два программных интерфейса, назовём их PART и DISK. Первый предоставляет функции для работы с различными таблицами разделов: поиск метаданных таблиц разделов, парсинг и формирование списков разделов, получение информации по каждому разделу и т.п. На данный момент поддерживаются GPT, MBR, EBR, BSD label и VTOC8. Набор поддерживаемых таблиц разделов определяется переменными make на этапе компиляции. Обычно это GPT, MBR+EBR и BSD label.

PART API можно использовать напрямую, как это теперь делает ZFS, либо через DISK API. DISK API предназначен для использования в дисковых драйверах загрузчика. Интерфейс вобрал в себя всё общее, что есть между драйверами дисков загрузчиков разных аппаратных архитектур. Это позволило, во-первых, значительно упростить код драйверов, а, во-вторых, унифицировать алгоритмы их работы относительно определения таблиц разделов. Причём, эти алгоритмы почти на 100% совпадают с используемыми ядром. Поэтому, теперь не должно возникать ситуаций, когда загрузчик видит одни разделы, а ядро другие. Раньше такое было вполне возможно.

Основные особенности, которые попали в CURRENT:
  • теперь loader умеет считать контрольную сумму для GPT заголовка и таблицы, а так же использовать резервную копию GPT;
  • PMBR так же научился работать с резервной GPT;
  • в качестве дополнительного бонуса, улучшенная поддержка EBR позволяет загрузить систему с логического тома. Правда boot0 делать этого не умеет, на сколько я помню.
  • Так как ZFS научилась читать таблицы разделов, теперь она не перебирает все возможные комбинации разделов, а тестирует только те, на которых ZFS может быть установлена. Т.е. это разделы с типом "freebsd" и "freebsd-zfs", так что, если у вас есть загрузочный пул на разделах с другим типом, это нужно исправлять.
От идеи с определением метаданных GEOM в загрузчике пока отказались. Так же остались ещё патчи для uboot и архитектур arm/powerpc, которые так никто и не протестировал.

Мой студент в GSoC прошёл первый "отборочный тур", пока с небольшим отставанием от графика, но надежда на то, что скоро у нас на x86 заработает загрузка через EFI есть.

Дальше я планирую провести серию тестов по загрузке системы в различных конфигурациях с разным размером дискового кеша. Сейчас по-умолчанию его размер всего 16 Кбайт, и как показали первые тесты, его увеличение даёт прирост в скорости загрузки на несколько секунд, по крайней мере на моей машине.

В свободное время почитал код различных библиотек, утилит, загрузчиков и UEFI шелла, а так же документацию, какую удалось найти. Теперь уже гораздо лучше представлю, как будет работать наш UEFI загрузчик. Так что, если студент не справится, его работа не пропадёт даром :)

понедельник, 2 апреля 2012 г.

Проблемы в работе zfsloader во FreeBSD

Сначала небольшой оффтопик - поддержка LDM уже включена во FreeBSD 10-CURRENT и в ближайшие пару недель будет перенесена в STABLE. В отличие от первоначальных патчей, текущая реализация умеет работать с дисками, размеченными GPT. А в остальном всё осталось примерно так же.

Теперь о теме сообщения. Возможно некоторые из вас замечали, что при загрузке FreeBSD c ZFS в качестве корневой файловой системы, наблюдается некоторая задержка между идентификацией дисков и началом загрузки ядра. Эта задержка в ряде случаев (например, большое количество дисков; много разделов; система в гостевой виртуальной машине) может составлять довольно ощутимое время.

Потратив некоторое время на изучение кода в каталоге sys/boot, могу сделать вывод, что работа нашего загрузчика zfsloader далеко не оптимальна. И корни этой проблемы растут с давних времён.

Во-первых, на данный момент из-за "ограниченности vs. универсальности" интерфейса libstand(3) нет никакой возможности определить количество найденных дисков из кода инициализации ZFS. Поэтому ZFS просто последовательно пробует открыть каждый диск поддерживаемый загрузчиком, а это 32 штуки (от "disk0:" до "disk31:").

Во-вторых, опять же, нет никакой возможности из кода инициализации ZFS узнать тип таблицы разделов и количество разделов в ней, чтобы проверить наличие ZFS на этих разделах. Поэтому выполняется простой перебор всех возможных разделов из диапазона от 1 до 128, например, выполняется попытка откыть "disk0p1:", если не удалось, то делается попытка открыть "disk0s1:" и т.д. до 128.

В-третьих, из-за привязанности к интерфейсу libstand(3), код работы с дисковыми устройствами выполняет чтение таблицы разделов, её проверку и т.д. на каждый вызов open(2). Т.е. когда код инициализации ZFS открывает "disk0:", затем открывает каждый его раздел. Все эти действия приводят к повторному чтению таблицы разделов.

Это частично компенсируется наличием уровня блочного кэша (да, даже у загрузчика он есть). Но размер его всего 16 кБайт, поэтому промахи имеют место быть, особенно для случая с GPT, когда таблица разделов занимает от 34 секторов.

В-четвёртых, для случая с GPT не проверяется ни контрольная сумма, ни резервная таблица с заголовком. Т.е. возможен вариант, когда у второй ступени загрузочного кода gptzfsboot и zfsloader будут разные представления о таблицах разделов.

В итоге, я написал вот такой вот патч, который решает часть проблем, но всё же далеко не идеален. Хотя, судя по отзывам увеличивает скорость инициализации загрузчика на порядок.

В идеале же хочется выделить логику работы с таблицами разделов (а он встречается в sys/boot не один и не два раза) в отдельные файлы с необходимым интерфейсом, не зависящим от libstand(3). Но пока работа в этом направлении идёт неспешно.

среда, 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)

пятница, 23 июля 2010 г.

Максимальный размер freebsd-boot партиции

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

Но в общем-то, к чему я это рассказываю. Обнаружилась неожиданная особенность. Он вопреки всем мануалам, которых уже полно в Сети, создал партицию с типом freebsd-boot в таблице GPT размером в 1 МБ. В итоге, при загрузке он получал сообщение "Boot loader too large". Покопавшись немного в исходниках я выяснил, что это сообщение выдаёт код PMBR. На ассемблере последний раз я писал, наверное, ещё в универе, так что пришлось немного "помедитировать" над его кодом, хорошо что в нём отличные комментарии :)

В итоге решил добавить некоторые изменения в мануал gpart(8):
  • для параметров -s и -b можно использовать суффиксы k, m, g и т.д.;
  • размер партиции freebsd-boot не должен быть больше 545 Кбайт.

четверг, 22 апреля 2010 г.

sade - редактор диска, часть 4

После небольшого перерыва решил продолжить эпопею с sade.

От marcel@ по прежнему тишина, поэтому думаю придётся отказаться от использования geom_part.so в пользу libgeom. В связи с этим предстоит частичное дублирование кода из geom_part.so у себя. В основном это будет код записи загрузочного кода и автоподбора параметров. Но зато стандартно и без лишних костылей...

После непродолжительных обсуждений в IRC и некоторого обдумывания придумал, как примерно будет выглядеть интерфейс для работы с ZFS и создания файловых систем. К тому же решил, что будет полезной возможность создания RAID при помощи GEOM классов. Поэтому добавил главное меню, в котором пока 3 пункта:
[Image]
Пока что работает только второй, но дело сдвинулось с мёртвой точки.

По моей логике работа с sade будет выглядеть примерно так:
  1. Сначала пользователь может зайти в раздел RAID (если ему нужно это) и там выбрать устройства, которые он планирует объединить в RAID. Причём кроме обычных gmirror и gstripe думаю туда же добавить и возможность создания ZFS пула из нескольких устройств (т.е. mirror, raidz, raidz2). Возможно стоит туда же втиснуть возможность конфигурирования gjournal, geli,... Но про последние пока не думал, да и не использовал я их по сути.
  2. После создания конфигурации для RAID, либо сразу, если она не нужна, пользователь заходит во второй пункт. Тут уже открывается список устройств, из которых можно выбрать только одно (единовременно) и дальше типовой функционал gpart. Создание схемы, добавление партиций на неё и запись загрузочного кода. Сюда же входит создание разметки BSD. Для ZFS будет отдельный редактор, больше похожий на редактор файловых систем. Он будет открываться при выборе ZFS пула из списка устройств. Или когда пользователь выберет в списке возможных схем "создание ZFS пула".

    Вообще, работу с ZFS думаю реализовать по аналогии с партициями. Создание пула соответствует созданию схемы, а создание датасетов - созданию партиций. Т.е. например, когда в редакторе партиций нажать Enter на партиции с типом freebsd-zfs, то будет предложено создать пул на ней (если конечно там его ещё нет), после чего откроется редактор ZFS, в котором можно создавать датасеты.
  3. После создания партиций пользователь должен будет выйти в главное меню и выбрать третий пункт. Это будет тоже отдельный редактор, над созданием которого сейчас я начинаю работать. Это будет список, пока я планирую выводить 4 столбика:
    имя_провайдера<--->тип_ФС<--->Размер<--->Точка монтирования

    В список поддерживаемых ФС пока планирую включить: ufs, zfs, swap. Ещё там может отображаться "empty" и "unknown". "empty" для свежесозданных партиций, а "unknown" для случая когда нет прав для того чтобы определить тип ФС или ещё чего-то непредвиденного.
Вот как-то так..

среда, 24 февраля 2010 г.

JA2 во FreeBSD

Много лет назад, когда я ещё жил в общежитии университета, у нас ещё не было ни локальной сети, ни Интернета. Тогда мы с соседями убивали время за играми... Мне особенно нравились различные RPG и пошаговые стратегии. Одной из таких игр была Jagged Alliance 2. Довольно неплохая игра для того времени.

Я обнаружил её в портах FreeBSD, и что интересно, сейчас она уже распространяется с открытым исходным кодом. Захотелось посмотреть, как она будет выглядеть сейчас. Установка игры из порта games/jaggedalliance2 не вызвала никаких сложностей. Проблему вызвало только отсутствие файлов ресурсов игры - карты, озвучка, ролики и т.п. Они в состав порта не входили. Нужны были оригинальные диски с игрой. Диски когда-то у меня были (я покупал 1С-овскую "Gold" версию), но вот найти их мне не удалось, смутно припоминалось, что возможно я подарил их племяннику жены...

Ну что ж.. После успешной установки сдаваться так просто не хотелось, немного погуглив :) я нашёл нужные мне исошники. Скачал, но опять же на них ресурсы были запакованы инсталлятором. Пришлось
воспользоваться компьютером жены с Windows, где я и установил игру. :)

После этого я создал на своём ZFS пуле новый датасет установиви свойство casesensitivity в значение insensitive для того чтобы не возникло проблем с регистром символов в именах файлов и каталогов:
> sudo zfs create -o casesensitivity=insensitive -o mountpoint=/usr/local/share/ja2 zroot/data
И скопировал с компьютера жены каталог Data в созданный датасет. После этого запустил из коммандной строки ja2, игра тут же закрылась и в домашнем каталоге создался подкаталог ~/.ja2 в котором я отредактировал файл ~/.ja2/ja2.ini и указал там путь к файлам ресурсов:
#Tells ja2-stracciatella where the binary datafiles are located
data_dir = /usr/local/share/ja2
Но игра и в этот раз не запустилась, ругнувшись на файлы ресурсов... Посмотрев в содержимое архива с исходниками я обнаружил, что там в параметрах make упоминается RUSSIAN_GOLD, которого нет среди опций порта. А ведь ISO'шки с игрой у меня были именно версии Gold. Я быстренько поправил Makefile порта добавив ещё одну опцию RUSSIAN_GOLD и пересобрал игру. Запустив новый бинарник игра запустилась в окошечке и вполне неплохо выглядела. По Alt+Enter она может разворачиваться на полный экран и обратно.


После этого я решил оформить патч и отправить PR для внесения изменений в порт. Патч получился таким:
--- jaggedalliance2/Makefile     2009-06-14 12:41:39.000000000 +0400
+++ jaggedalliance2/Makefile     2010-02-01 08:27:31.825416359 +0300
@@ -7,6 +7,7 @@
 PORTNAME=       ja2
 PORTVERSION=    0.12
+PORTREVISION=   1
 CATEGORIES=     games
 MASTER_SITES=   http://deponie.yamagi.org/freebsd/distfiles/ \
                 http://tron.homeunix.org/ja2/
@@ -34,7 +35,8 @@ OPTIONS=       DUTCH   "Compile for Dutch versio
                 GERMAN  "Compile for German version (choose ONE)"       Off \
                 ITALIAN "Compile for Italian version (choose ONE)"      Off \
                 POLISH  "Compile for Polish version (choose ONE)"       Off \
-                RUSSIAN "Compile for Russian version (choose ONE)"      Off
+                RUSSIAN "Compile for Russian version (choose ONE)"      Off \
+                RUSSIAN_GOLD "Compile for Russian Gold version (choose ONE)"    Off
 .include 
@@ -52,6 +54,8 @@ MAKE_ARGS+=    LNG=ITALIAN
 MAKE_ARGS+=     LNG=POLISH
 .elifdef WITH_RUSSIAN
 MAKE_ARGS+=     LNG=RUSSIAN
+.elifdef WITH_RUSSIAN_GOLD
+MAKE_ARGS+=     LNG=RUSSIAN_GOLD
 .else
 IGNORE= no language has been chosen. Please choose the appropriate language for your game CD
 .endif
Вроде все изменения тривиальные и объяснять нечего... Сам PR можно посмотреть здесь. Через три недели патч был одобрен и изменения были внесены. Такая большая задержка получилась из-за ожидания ответа мэйнтейнера, который так и не ответил...