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

среда, 20 ноября 2013 г.

Изменение размера зеркала GEOM_MIRROR

Недавно мне был задан вопрос о том, как можно изменить размер зеркала, созданного при помощи geom_mirror(4), после замены дисков на бОльшие? Честно говоря, самому использовать geom_mirror мне довелось немного, а после появления zfs и совсем как-то перестал. Но посмотрев в код, понял, что простого способа нет.

В итоге требуемый функционал был добавлен и сейчас он уже включён в 11.0-CURRENT. Теперь, после того как вы заменили диски и они синхронизировались, можно выполнить команду gmirror resize и изменить размер зеркала. Тут я применил подход, используемый в gpart(8). Если пользователь при выполнении команды не указывает конкретный размер, то размер расчитывается автоматически до максимально доступного. Т.е. команда:
# gmirror resize gm0

просмотрит все компоненты зеркала, определит максимально доступный размер и установит его.

Впрочем, с помощью ключа -s можно задать и конкретный размер, который может быть и меньше текущего. Но если зеркало используется, то уменьшение зеркала выдаст ошибку EBUSY.

Кроме того, я добавил реализацию метода g_resize, про который я упоминал в предыдущей заметке. Теперь, если родительский провайдер изменит свой размер, то geom_mirror автоматически запишет свои метаданные в "новый" последний сектор. Это может быть использовано, например, при зеркалировании разделов. После изменения размера раздела при помощи gpart resize метаданные gmirror будут автоматически обновлены и записаны в последний сектор. Останется только выполнить ту же процедуру для второго компонента и сделать gmirror resize.

вторник, 12 ноября 2013 г.

Автоматическое изменение размера в GEOM_PART

Некоторое время назад Edward Tomasz Napierala выполнял проект, который позволяет изменять размеры файловых систем без необходимости их размонтирования (при определённых условиях конечно). В результате выполнения этого проекта у GEOM появились новый метод класса g_resize и вспомогательная функция g_resize_provider(). Так же были сделаны соответствующие изменения для некоторых GEOM классов, чтобы задействовать новый функционал.

Теперь несколько слов о том, как это работает.  В качестве целевой аудитории пользователей этого функционала предполагались владельцы умных СХД (систем хранения данных), которые могут динамически изменять размеры своих виртуальных дисков. Администратор такой системы может подвигать ползунком в веб морде СХД (например) и увеличить размер виртуального диска. Эта информация может быть донесена до SCSI диска, а драйвер диска передаёт её geom объекту класса GEOM_DISK. Geom объект вызывает функцию g_resize_provider() и это запускает цепочку действий по информированию всех consumer'ов этого диска об изменившемся размере. Если GEOM класс consumer'а имеет реализацию метода g_resize, то этот метод будет вызван. Таким образом GEOM класс может обработать это событие и выполнить какие-то свои действия.

Как же этот новый функционал можно применить в GEOM_PART? Самое малое было реализовано Эдвардом в рамках выполняемого им проекта - он сделал так, чтобы при выполнении команды gpart resize вызывалась функция g_resize_provider().  Это позволило по аналогии с цепочкой передачи события об изменении размера диска "СХД - драйвер диска - consumer'ы диска" реализовать цепочку "пользователь - раздел в таблице - consumer'ы раздела".  Т.е. теперь, все consumer'ы подключённые к разделу, размер которого изменился, могут что-то предпринять в ответ на это событие.
Если же диск меняет размер, то очевидно, что информация в метаданных таблицы разделов может перестать соответствовать действительности.  И здесь были нужны несколько большие изменения.

В итоге в FreeBSD 11.0-CURRENT сейчас сделано следующее. Для класса GEOM_PART реализован метод g_resize и теперь, при получении события об изменении размера родительского провайдера, будет произведена корректировка метаданных. Но, чтобы уменьшить вероятность совершения тяжело поправимых ошибок со стороны пользователя, эти изменения в метаданных не записываются сразу же на диск. Вместо этого в консоль выводится сообщение "GEOM_PART: %s was automatically resized" и диск помечается как "modified". Увидев такое сообщение в консоли или в системном журнале сообщений, пользователь должен сам решить, хочет он сохранить эти изменения или нет. Для сохранения ему необходимо выполнить команду gpart commit, или сделать любые изменения в таблице разделов, которые вызывают gpart commit неявно.

Это реализовано практически для всех поддерживаемых таблиц разделов, за исключением LDM и GPT. GPT имеет возможность быть помеченной CORRUPT, и для неё может быть использована команды recover, так что не особенно актуально. А LDM поддерживается в режиме только для чтения.

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

gpart resize - лёд тронулся.

Ну вот, переодическое "капанье на мозг" :-) дало первые результаты. Marcel закоммитил мой патч, добавляющий поддержку изменения размера провайдеров внутри схемы. Константин Белоусов (kib@) посоветовал не забыть через некоторое время напомнить ему сделать MFC. Думаю недельки через 3-4 можно будет начинать "напоминать" :-)

А пока, отправил ему письмо с благодарностью и ссылками на следующие два патча :-)

понедельник, 22 марта 2010 г.

gpart: изменение размера раздела

Доделал поддержку изменения размера разделов для GEOM класса PART. На данный момент идеи "что бы туда ещё добавить" закончились, поэтому решил выложить патчи.

Немного о цели патчей. Были у меня несколько машин, на которые я уже давно для тестов ставил FreeBSD с ZFS. Они полностью установлены на ZFS, но было оставлено свободное пространство "на всякий случай". Там используется GPT "схема" со "стандартной" разбивкой на три партиции: freebsd-boot, freebsd-swap и freebsd-zfs. Свободное место было оставлено в конце диска. И вот, в один прекрасный момент захотелось использовать свободное место. Но создавать отдельную партицию не хотелось после успешных экспериментов по расширению пула ZFS.

После постановки задачи "как это сделать" очевидных решений найдено не было. Первое, что пришло на ум - поправить в таблице GPT размер партиции. Решил попробовать, подампил таблицу в файлы, поизучал формат... Решил посмотреть, что там в коде реализации. Оказалось, что "заготовка" базового метода resize уже имелась в коде класса. Только она ничего не делала, а возвращала ошибку ENOSYS.

Я связался с автором класса PART - Marcel Moolenaar. Обсудил с ним что и как лучше реализовать. После чего взялся за эксперименты. Что в итоге получилось, можно увидеть здесь. Ход работы можно проследить в perforce.

Если в кратце, то в начале пришлось заново вспомнить изучить для чего в дереве кода ядра используются файлы с расширением "*.m". Они применяются для создания подобия ООП в коде ядра. Как я уже упоминал ранее, структура класса PART интересна своей модульностью. Сам класс имеет базовые методы работы с партициями, а все детали реализации описываются в отдельных модулях схем. Так вот, в .m файлах описан программный "интерфейс" подобных модулей. Эти файлы обрабатываются awk скриптом во время компиляции ядра и генерируются файлы .c и .h.

Грубо говоря, благодаря им и создаётся иллюзия ООП. Хотя на мой взгляд всё довольно условно :) Итак, реализовав базовый алгоритм изменения размера в ядре и добавив новую команду в утилиту управления gpart, я добавил поддержку в GPT схему. Потестировал на md(4) дисках - вроде работает и даже не паникует :)
Решил попробовать на рабочей системе, попробовал - размер изменился, перезагрузился - пул "подхватил" свободное пространство и я счастлив :)

После этого добавил поддержку в оставшиеся схемы, немного потестировал на том же md(4) и вроде всё. Да, только в EBR не стал добавлять, там как-то не всё гладко в реализации.

Пример использования:
# gpart show md0
=>    34  409533  md0  GPT  (200M)
      34  204800    1  freebsd-zfs  (100M)
  204834  204733       - free -  (100M)

# gpart resize -s 150m -i 1 md0
md0p1 resized
# gpart show md0
=>    34  409533  md0  GPT  (200M)
      34  307200    1  freebsd-zfs  (150M)
  307234  102333       - free -  (50M)

# gpart resize -i 1 md0
md0p1 resized
# gpart show md0
=>    34  409533  md0  GPT  (200M)
      34  409533    1  freebsd-zfs  (200M)

У команды resize есть два параметра "-i index" и "-s size". Указание индекса обязательно, а вот размер может быть вычислен автоматически. Изменяться может только смещение конца партиции, смещение начала всегда остаётся неизменным.

И ещё важное замечание - изменяются только метаданные таблицы разделов, изменение размеров файловой системы нужно производить сторонними методами, например growfs для UFS. ZFS сама видит увеличение. Уменьшение разделов не запрещено и работает, но что на это скажет файловая система раздела - мне, честно говоря, не очень хочется узнавать :)