Использование журналирования во FreeBSD


Во FreeBSD появилась возможность задействовать журналирование.

Об этом вы могли узнать из нашей новости Журналирование UFS с помощью gjournal
Для тех у кого совсем туго с английским перевожу письмо автора патча Pawel Jakub Dawidek.

Привет.

В течение последних нескольких месяцев я работал над проектом gjournal. Чтобы исключить недопонимание, хочу заметить, этот проект не связан с проектом gjournal над которым работал Ivan Voras в рамках SoC (2005).

Нехватка журналируемой файловой системы во FreeBSD была ахиллесовой пятой многие годы. Мы имеем множество файловых систем, но ни одной с журналированием:
ext2fs (журналирование в ext3fs),
XFS (только чтение),
ReiserFS (только чтение),
HFS+ (чтение и запись, но без журналирования),
NTFS (только чтение).

GJournal работает через провайдеров журнала GEOM, поэтому фактически он работает ниже уровня файловой системы, но имеет методы доступа для работы с файловой системой. Другими словами, gjournal не зависит от файловой системы, она может работать вероятно с любой файловой системой с минимальными знаниями о ней. Я осуществил только поддержку UFS.

Патчи лежат здесь:

http://people.freebsd.org/~pjd/patches/gjournal.patch (для HEAD)
http://people.freebsd.org/~pjd/patches/gjournal6.patch (для RELENG_6)

Для исправления ваших исходников необходимо сделать следующее:
# cd /usr/src
# mkdir sbin/geom/class/journal sys/geom/journal sys/modules/geom/geom_journal
# patch < /path/to/gjournal.patch

Добавить options UFS_GJOURNAL в ваш конфигурационный файл ядра и пересобрать ядро и мир.

Как это работает (коротко). Вы можете определить один или два поставщика которых будет использовать gjournal. Если дан один поставщик, он будет использоваться и для данных и для журнала. Если даны два поставщика, один будет использоваться для данных а другой для журнала. Каждые несколько секунд (вы можете определить как часто) журнал прерывается и помечается как согласованный(непротиворечивый, совместимый) и gjournal начинает копировать данные из его в поставщика данных. В то же самое время новые данные сохраняются в новом журнале. Давайте называть момент, в который прерывается журнал - "переключением журнала".

Во время переключения журнала происходит следующее:
Начинаем переключение журнала, если пришло время или заканчивается кеш. Не выполняем переключение журнала, если не было запросов на запись.
Если имеем файловую систему, синхронизируем ее.
Помечаем файловую систему как "чистую"(clean).
Блокируем все запросы к файловой системе на запись.
Прерываем журнал.
В конечном счете - ждем, если копирование предыдущего журнала еще не закончено.
Посылаем запрос BIO_FLUSH (если данный провайдер поддерживает это).
Отмечаем новую позицию журнала в провайдере журнала.
Разблокируем запросы на запись.
Начинаем копировать данные из прерванного журнала в поставщика данных.

Было несколько дел, которые я должен был сделать вне gjournal, чтобы его работа была надежнее:
Запрос BIO_FLUSH. В настоящее время мы имеем три запроса ввода/вывода: BIO_READ, BIO_WRITE и BIO_DELETE. Я добавил BIO_FLUSH, что означает "записать кеш на диск". Запрос посылается всегда с установленным в наибольшее значение bio_offset (mediasize of the destination provider), так что это должно нормально работать с bioq_disksort(). Вызывающему необходимо остановить дальнейшие запросы ввода/вывода перед вызовом BIO_FLUSH, so we don't have starvation effect.
Железная часть: должна быть осуществлена поддержка этого в каждом драйвере дисков, потому что операция сброса кеша на диск зависит от драйвера. Я осуществил это для ata(4) дисков и amr(4). Хорошая новость - это просто. GJournal может также работать с провайдерами не поддерживающими BIO_FLUSH и в моих power-failure тестах все работает хорошо (без проблем), но есть факт, что кеш gjournal больше кеша контроллера, это трудно назвать надежным.

Вы можете прочитать в документации ко многим журналируемым файловым системам, что вы должны выключить кеширование записи, если хотите использовать журналирование. Это не так в случае с gjournal (особенно, если ваш драйвер диска поддерживает BIO_FLUSH).

Опция монтирования gjournal. Для осуществления поддержки gjournal в UFS Я должен изменить способ удаления, еще открытых объектов. В настоящее время, когда файл или директория открыты, а мы удаляем последнее ссылающееся на них имя, они все еще будут доступны для использования теми, кто оставил их открытыми. Когда последний потребитель закроет их, inode и блоки будут освобождены. При включенном журналировании я не могу оставлять такие объекты, так как после аварии для проверки файловой системы не используется fsck(8), то inode и блоки недолжны освобождаться. Когда файловая система примонтирована с опцией gjournal, объекты не удаляются, если они открыты. Когда последнее имя удалено, файл/директория перемещаются в директорию .deleted/ и удаляются оттуда при закрытии последнего. В этом случае, Я просто очищаю директорию .deleted/ после аварии во время монтирования.

Быстрый старт:
# gjournal label /dev/ad0
# gjournal load
# newfs /dev/ad0.journal
# mount -o async,gjournal /dev/ad0.journal /mnt
(да, с gjournal 'async' безопасен)

Теперь, после отключения питания или краха системы не нужен fsck (опа!).

Есть два недостатка в данной реализации, которые я хотел бы исправить. Первый, когда монтирование осуществлено с опцией 'gjournal'. Сборщик мусора, который отвечает за удаление объектов из директории .deleted/ использует для этого полный путь. Из-за этого, когда ваша точка монтирования /foo/bar/baz и вы переименуете 'bar' во что-то другое, зачистка работать не будет. Это не так часто делается, но должно быть устранено, и Я работаю над этим. Второй недостаток связан со связью между gjournal и файловой системой. GJournal делает выбор, когда делает "переключение" и должен найти файловую систему, котороая примонтирована. Поиск этой файловой системы не очень хорош - его надо переделать.

Есть дополнительные полезности, которые пришли с gjournal. Например, если gjournal сконфигурирован на gmirror или graid3, при сбое питания или крахе системы, не нужно юудет синхронизировать устройства mirror/raid3, потому что структура данных не будет повреждена.

Я трачу много времени на работу по оптимизации gjournal. поскольку я имею несколько секунд перед тем как данные попадут провайдеру данных, Я могу выполнить такие вещи, как объеденить несколько маленьких запросов на запись в одну большую, игнорировать данные записываемые дважды в одно и тоже место, и т.п.. Из-за этого, операции с маленькими файлами весьма быстры. С другой стороны, операции с большими файлами медленее, потому что я должен записывать данные дважды и места для оптимизации. Вот некоторые цифры.
gjournal(1) - провайдер данных и журнала на одном диске
gjournal(2) - провайдер данных и журнала на разных дисках

Копирование одного большого файла:
UFS: 8s
UFS+SU: 8s
gjournal(1): 16s
gjournal(2): 14s

Копирование восьми больших файлов одновременно:
UFS: 120s
UFS+SU: 120s
gjournal(1): 184s
gjournal(2): 165s

Растаривание восьми src.tgz одновременно:
UFS: 791s
UFS+SU: 650s
gjournal(1): 333s
gjournal(2): 309s

Чтение. grep -r на двух src/ даректориях параллельно:
UFS: 84s
UFS+SU: 138s
gjournal(1): 102s
gjournal(2): 89s

Вы можете видеть, даже на одном диске, растаривание восми src.tgz в два раза быстрее чем на UFS+SU. Я понятия не имеею, почему gjournal быстрее читает.

Есть возможность тюнинга gjournal через sysctl (ветка kern.geom.journal).

Когда используется только один провайдер и для данных и для журнала, журнал дописывается в конец провайдера, что дает возмозможность использовать файловую систему без журналирования. Если вы используете такую конфигурацию (с одним диском), для улучшения производительности поместите журнал перед данными, для этого вы можете создать две партиции (например. 2GB для ad0a и остальное для ad0d) и создайте gjournal слудующим путем:
# gjournal label ad0d ad0a

Пробуйте!

Спонсор работы home.pl (http://home.pl).
Работа была сделана Wheel LTD (http://www.wheel.pl).
Работа была проверена в кластере netperf.

Я хочу поблагодарить Александра Кабаева (kan@) за помощь с VFS и Mike Tancsa за тест железа.
Pawel Jakub Dawidek http://www.wheel.pl
pjd at FreeBSD.org http://www.FreeBSD.org
FreeBSD committer Am I Evil? Yes, I Am!

Вольный перевод произвел Андрей Н. Грошев aka GreenX

http://wiki.bsdportal.ru/doc:gr_gjournal

Обновлено: 12.03.2015