среда, 27 октября 2010 г.

VirtualBox и NS_ERROR_FAILURE (0x80004005)

Некоторое время назад у меня перестал работать VirtualBox. При запуске виртуальной машины он выдавал сообщение:

Код ошибки: NS_ERROR_FAILURE (0x80004005)
Компонент: Machine
Интерфейс: IMachine {6d9212cb-a5c0-48b7-bbc1-3fa2ba2ee6d2}
После чего это произошло я как-то не уследил, не очень часто им пользуюсь, но бывает удобно. Ну сломался и сломался, не очень-то и нужен был. Поиск в Интернете приводил на линуксовые форумы, даже на forums.freebsd.org есть тема. Всё сводилось к тому, что что-то не так с модулем vboxdrv. С которым вроде бы всё было в порядке, он вполне соответствовал версии virtualbox-ose и загружался без ошибок.

Выходили новые версии VirtualBox'а, обновление не помогало. Решил посмотреть для начала в Makefile портов. И вот, читая emulators/virtualbox-ose-kmod/Makefile обнаружил там такие строчки:

 SRC_BASE?=      /usr/src
...
.if !exists(${SRC_BASE}/sys/kern/bus_if.m)
IGNORE=         requires kernel sources
.endif
Вот тут-то до меня и дошло в чём проблема. Я последнее время обновлял систему и ядро из другого каталога, не из /usr/src. У меня в рабочем каталоге постоянно обновлённые исходники системы, там я их и редактирую, и там же компилирую при необходимости что-то протестировать. Поэтому, /usr/src у меня оказались заброшенными. А порт-то собирался с использованием /usr/src! Сразу же попробовал переопределить SRC_BASE и всё получилось. Так что, теперь в поисковике можно будет найти ещё одно решение этой проблемы :)

вторник, 26 октября 2010 г.

Восстановление GPT при помощи gpart

Вчера, наконец-то, внёс поддержку gpart recover в head/. Через две недели планирую сделать MFC в 8-stable, если всё будет хорошо. Но хотелось бы успеть до заморозки кода перед началом подготовки к релизу, иначе в 8-ку это всё попадёт уже нескоро.

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

Запрещать любые действия было бы не логично, если не предложить что-то взамен. Взамен предлагается своего рода гарантия, что вы ничего случайно не сломаете, а так же возможность починить таблицу разделов, либо, если она вам не нужна - уничтожить её совсем. Для возможности уничтожения таблицы пришлось переделать "gpart destroy -F". Теперь форсированное уничтожение выполняется внутри ядра, а не в userspace как раньше.

Что бы знать какие типы повреждений возможно восстановить в GPT при помощи gpart, нужно иметь представление о том, как устроена GPT. Если коротко, то состоит она из заголовка и самой таблицы разделов. Всё это дублируется. Заголовок основной таблицы находится во втором секторе диска, за ним следует таблица разделов, её размер может быть различным. Заголовок резервной таблицы находится в последнем секторе, таблица располагается в предшествующих ему секторах. Содержание таблиц идентично и должно иметь одинаковую контрольную сумму. А вот заголовки отличаются, в них сохраняются номера секторов, в которых находится сам заголовок и его копия, номер начального сектора таблицы и границы пространства для использования партициями. Часть этой информации отображается в выводе команды gpart list:

> gpart list ada1
Geom name: ada1
state: OK
fwheads: 16
fwsectors: 63
last: 320173022
first: 34
entries: 128
scheme: GPT
Здесь first и last - номера секторов, ограничивающих доступное пространство для разделов GPT, entries - максимальное количество записей в таблице, другими словами максимальное количество партиций.

Так же, ещё одним обязательным условием для работы с GPT является наличие PMBR, который занимает первый сектор. Если повредить содержимое PMBR, то класс PART не будет даже искать GPT на диске. Такова особенность. Поэтому если ваша GPT не обнаруживается совсем, ядро не выдаёт никаких сообщений, связанных с GPT, первым делом стоит восстановить PMBR. Его копию можно найти в файле /boot/pmbr. Нужно всего лишь записать его в первый сектор диска. Это автоматически инициирует поиск метаданных различными GEOM классами, в том числе и GEOM_PART_GPT.

Теперь о возможных повреждениях. Первое - это повреждение основного заголовка или таблицы GPT. При обнаружении такого повреждения ядро выдаст сообщение:
GEOM: provider: the primary GPT table is corrupt or invalid.
GEOM: provider: using the secondary instead -- recovery strongly advised.
Здесь provider - это имя диска, например ad0. Кроме этого сообщения, которое обычно можно увидеть только во время загрузки системы, о том что ваша GPT повреждена могут расказать команды gpart show, list и status.
> gpart show
=>        34  1250263661  ada0  GPT  (596G) [CORRUPT]
          34         256     1  freebsd-boot  (128K)
         290     8388608     2  freebsd-swap  (4.0G)
     8388898  1241874797     3  freebsd-zfs  (592G)

> gpart list ada0 | grep state
state: CORRUPT
Следующий тип - повреждение резервной копии заголовка или таблицы GPT. Как частный случай сюда же относится вариант несоответствия резервной и основной копий (например, когда в основной копии заголовок и таблица с одними данными, а в резервной - с другими, но сами по себе они являются вполне корректными). В это случае GPART просто воспользуется данными из основной копии. Сообщение от ядра в этом случае будет таким:
GEOM: provider: the secondary GPT table is corrupt or invalid.
GEOM: provider: using the primary only -- recovery suggested.
Третий случай, когда таблица GPT будет помечена как повреждённая - это неверное расположение заголовка резервной копии GPT. Такое может случится, например если у вас GPT создана на каком-то виртуальном носителе, который умеет расширяться путём добавления новых дисков. Либо, просто, например, вы создали GPT на gmirror устройстве, но забыли загрузить класс geom_mirror. В этом случае размер провайдера увеличится, так как gmirror резервирует пространство под свои метаданные.

Теперь, собственно про восстановление. Всё что нужно сделать - правильно выбрать носитель, на котором восстанавливать GPT и выполнить команду:
# gpart recover ada0
В моём примере это ada0. Почему я выделил слово "правильно"? Вернёмся к примеру, в котором GPT создана поверх gmirror. Так вот, если забыть загрузить gmirror, то GPT будет найдена на том диске, на котором создан gmirror. И соответсвенно, если выполнить gpart recover для этого диска, то все параметры заголовка GPT будут перерасчитаны, а значит изменится и значение last - границы последнего доступного сектора, а так же, в последний сектор диска будет записан заголовок резервной копии GPT, который уничтожит метаданные gmirror. Хорошо, если это именно то, чего вы хотели :)

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

понедельник, 27 сентября 2010 г.

Новая опция для "gpart destroy"

Давненько я ничего сюда не писал. Почти месяц был без доступа к сети. Тяжело :)

За это время pjd@ успел наломать дров - пользуясь отсутствием Марселя он внес кучу изменений в geom(8) и в gpart(8). В частности, он изменил интерфейс взаимодействия между утилитой geom(8) и ядром. В связи с этим мне предстоит значительно повозится, исправляя sade, когда дойдут до неё руки...

А на данный момент, я добавил поддержку опции "-F" для команды "gpart destroy". Опция эта позволяет уничтожить таблицу разделов без необходимости удаления каждой её партиции. На мой взгляд - давно востребованная функция. Я даже где-то в списках рассылки видел шелл скрипт, выполняющий эту задачу.

Немного подробностей. Патч с реализацией этого функционала был готов ещё в конце июля, но тогда он ожидал одобрения от marcel@, затем от моих менторов. Так время тянулось в ожидании, а потом я попал в дтп и на месяц ушёл в оффлайн. Вернувшись, пришлось исправлять и патч (спасибо pjd :).

Марсель одобрил идею, которая заключалась в реализации всего функционала внутри gpart(8), без изменений внутри ядра. А именно, если пользователь указывает ключ "-F", то внутри gpart(8) в цикле удаляются все разделы таблицы, а затем уже уничтожается таблица.

С MFC этого функционала возникнут некоторые трудности, благодаря всё тем же изменения от pjd@, но проблема вроде бы решаемая. Так что через недельки полторы этот функционал появится и в 8-STABLE,

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

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

Отчёт за июнь

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

Июнь прошёл. Прогрессом в разработке sade похвастаться не могу. Его нет, т.к. нет времени.
Выложил исходный код в SVN. Из разработчиков написали двое - один спросил "что нужно для сборки?", второй - "узнал что есть такой редактор, где посмотреть?" :)
Первый собрал, понравилось, пожелал удачи :) Второй больше ничего не ответил.

По поводу того, что бы использовать sade в инсталляторе - в связи с последними событиями по импорту инсталлятора PC-BSD, думаю эта тема уже не актуальна. Так что будет просто удобная утилита для работы. В принципе, мне так даже проще :)

По просьбе двух товарищей с IRC канала #FreeBSD@RusNet закоммитил код новой netgraph ноды ng_patch и уже сделал MFC в 8-ку. Так же смержил почти все изменения в gpart из CURRENT в 8-STABLE. Включая и поддержку "gpart resize", MFC которой столкнулось с вопросом от Константина kib@ - "А не ломает ли оно KBI?". Другими словами, не повлияет ли изменение интерфейса в ядре на уже скомпилированные модули ядра. В результате пришлось вновь ковыряться в исходниках интерфейса KOBJ :) Ну и простой эксперимент показал, что подобные изменения не влияют на KBI. Новое ядро с расширенным интерфейсом g_part (там добавился новый метод resize) успешно подгружает старые модули g_part_xxx и они работают.

На очереди к MFC исправление для упомянутой мной ранее "особенности" реализации в определении размера сектора утилитой gpart. Теперь она научилась правильно определять размер сектора и больше подобные проблемы возникать не должны.

Так же, успел пообщаться с Марселем на тему реализации функции "gpart recover". Он дал несколько советов и попросил не останавливаться только на том, что уже сдалал, а подойти к проблеме более широко. Так что, появился простор для творчества, но времени всёравно нет :)

понедельник, 7 июня 2010 г.

Преступление и наказание.

Давненько я ничего сюда не писал. В связи с ремонтом в квартире всё никак не могу найти времени..

Итак, к чему такой subj? Май прошёл для меня плодотворно. Не только в связи с ремонтом в квартире, который проходит, на мой взгляд, ударными темпами, но и из-за событий связанных со мной и FreeBSD. 3-го июня меня "наказали" коммит битом в дерево src. Теперь я официально стал src-коммитером FreeBSD. :-)

Длилась эта процедура чуть больше месяца. Всё началось с предложения Константина (kib@) стать коммитером, на которое я дал согласие. Затем он написал обращение в FreeBSD Core Team с предложением "наказать" меня за мои деяния. На что core@ дало согласие. Моими менторами стали Константин Белоусов (kib@) и Александр Мотин (mav@). Далее последовали создание аккаунта на кластере freebsd.org и первые, традиционные коммиты.

Менторы курируют начинающих разработчиков. Советуясь с ними я должен освоить основные правила, которые применяются в проекте. Ну и главное, я должен согласовывать с ними все изменения, которые я собираюсь вносить в дерево исходных кодов FreeBSD. У меня два ментора. Причина в том, что сфера моих интересов слабо пересекается с интересами моих менторов. В качестве своих интересов я обозначил: подсистемы ядра GEOM, ATA, IPFW и файловые системы. Вот этим и буду заниматься в ближайшем будущем. Так же, я планирую перевести разработку sade в svn репозиторий FreeBSD. Так будет и мне проще, да и вдруг, кто-то решит помощь оказать?

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

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

Немного новостей о ходе работы. Марсель закоммитил два исправления, о которых я упоминал ранее. Теперь, вроде бы нет препятствующих разработке багов.

Я же выделил код и объявления структур и функций для работы с устройствами, партициями и файловыми системами в отдельную группу файлов. Позже оформлю их в виде библиотеки. Написал код для получения информации о файловых системах и сохранения его в список, которой используется внутри редактора файловых систем. Сделал базовую реализацию редактора, пока что он отображает список партиций имеющих тип freebsd-swap и freebsd-ufs:
На список команд не обращайте внимание, это copy-paste из редактора партиций. В принципе, кроме того что видно в списке сейчас, информационная структура хранит ещё данные о том смонтирована ли файловая система и опции монтирования из /etc/fstab.
Сделал так же проверку на наличие меток glabel, под которыми данное устройство может быть смонтировано или записано в fstab. Правда пока эта проверка достаточно формальная, потому как перебрать все возможные метки какие могут быть - достаточно нетривиальная задача.

Дальше буду думать, какие команды добавить в этот редактор и потихоньку их реализовывать.
Ещё надо что-то придумать с механизмом commit/undo для этого редактора. Небольшой набросок механизма ведения истории действий с возможностью отката и сохранения я сделал, но ясной картины как я буду его использовать пока нет.