Сначала небольшой оффтопик - поддержка 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). Но пока работа в этом направлении идёт неспешно.
Теперь о теме сообщения. Возможно некоторые из вас замечали, что при загрузке 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). Но пока работа в этом направлении идёт неспешно.
Я конечно наглею, но может к нему как то можно прикрутить загрузку и с GPT/UFS ну и совсем уж мечты об EUFI :)
ОтветитьУдалитьШай-бу! Шай-бу! :)
ОтветитьУдалитьсудя по этому тексту улучшение загрузчика очень правильная работа
2 Анонимный
ОтветитьУдалитьне то слово, в настоящее время имеем целую пачку загрузчиков, каждый из которых как то и при каких то условиях работает, но это как то не очень удобно, а порой до неприличия криво.
Нужно различать загрузочный код, который помещается в специальные области диска и загрузчик (loader или zfsloader). Задача последнего предоставить интерактив, если нужно, и загрузить ядро с файловой системы. И поддержка GPT/UFS у zfsloader имеется уже, вернее zfsloader это тот же loader, только он ещё умеет находить zfs пулы.
ОтветитьУдалитьПо поводу UEFI, кстати, во freebsd-hackers кто-то хотел начать писать код в рамках GSoC 2012
ОтветитьУдалитьпрошу прощение за возможный оффтоп
ОтветитьУдалитьа так должно быть?
# gpart show -r
=> 34 234492989 ada0 GPT (111G)
34 134 1 83bd6b9d-7f41-11dc-be0b-001560b84f0f (67k)
168 41943040 2 516e7cba-6ecf-11d6-8ff8-00022d09712b (20G)
41943208 41943040 3 516e7cba-6ecf-11d6-8ff8-00022d09712b (20G)
83886248 41943040 4 516e7cba-6ecf-11d6-8ff8-00022d09712b (20G)
125829288 108663735 - free - (51G)
=> 34 3907029101 ada1 GPT (1.8T)
34 6 - free - (3.0k)
40 88 1 83bd6b9d-7f41-11dc-be0b-001560b84f0f (44k)
128 209715200 2 516e7cb6-6ecf-11d6-8ff8-00022d09712b (100G)
209715328 3697313800 3 516e7cba-6ecf-11d6-8ff8-00022d09712b (1.7T)
3907029128 7 - free - (3.5k)
=> 34 3907029101 ada2 GPT (1.8T)
34 6 - free - (3.0k)
40 88 1 83bd6b9d-7f41-11dc-be0b-001560b84f0f (44k)
128 209715200 2 516e7cb6-6ecf-11d6-8ff8-00022d09712b (100G)
209715328 3697313800 3 516e7cba-6ecf-11d6-8ff8-00022d09712b (1.7T)
3907029128 7 - free - (3.5k)
одинаковые номера?
Это GUID'ы типов партиций, они и должны быть одинаковыми, если это одни и те же типы.
ОтветитьУдалить83bd6b9d-7f41-11dc-be0b-001560b84f0f = freebsd-boot
516e7cba-6ecf-11d6-8ff8-00022d09712b = freebsd-zfs
516e7cb6-6ecf-11d6-8ff8-00022d09712b = freebsd-ufs
Скорее всего, метка никуда не девается. Это uid'ы GPT, они доступны в /dev/gptid/.
УдалитьПроблема тут в том, что у всех этих провайдеров, например, ada2p2, gpt/label и gptid/uid одинаковый размер, и ZFS берёт первую попавшуюся. Сейчас нет возможность сказать ZFS использовать какую-то одну из них. Если вам не нравяся gptuid'ы, их можно отключить через kern.geom.label.gptid.enable="0" в loader.conf.
Я вас замучу )))
Удалить>sysctl kern.geom.label
kern.geom.label.debug: 0
kern.geom.label.ext2fs.enable: 1
kern.geom.label.iso9660.enable: 1
kern.geom.label.msdosfs.enable: 1
kern.geom.label.ntfs.enable: 1
kern.geom.label.reiserfs.enable: 1
kern.geom.label.ufs.enable: 1
kern.geom.label.ufsid.enable: 1
kern.geom.label.gptid.enable: 0
kern.geom.label.gpt.enable: 1
>gpart show -l
=> 34 3907029101 ada0 GPT (1.8T)
34 6 - free - (3.0k)
40 88 1 (null) (44k)
128 209715200 2 (null) (100G)
209715328 3697313800 3 beagle0 (1.7T)
3907029128 7 - free - (3.5k)
а в /dev/ нет gpt/ вообще
Так работает GEOM_LABEL, я уже неоднократно писал почему так происходит, так что предлагаю погуглить :)
Удалить