И вот у меня первый раз произошёл сбой на файловой системе XFS (eXtended File System).
XFS — высокомасштабируемая высокопроизводительная файловая система, изначально разработанная в Silicon Graphics.
XFS поддерживает журналирование метаданных, что ускоряет восстановление после сбоев. Файловую систему XFS можно дефрагментировать и увеличивать в размерах, пока она смонтирована и активна.
Сбой случился, как говорится, на ровном месте. Расширяли файловую систему на виртуально машине, и БД, которая писала на диск данные, вдруг упала. В консоль посыпалось:
Free Inode BTree record corruption in AG 20 detected!
Ошибка однозначно указывает на проблему с файловой системой XFS. Это сообщение сигнализирует о том, что ядро Linux обнаружило повреждение структуры B-Tree, отвечающей за отслеживание свободных инодов (индексов дескрипторов файлов) в одной из групп агрегации (AG — Allocation Group) диска.
Одна из возможных причин
Если вы видите ошибку Free Inode BTree record corruption, но не можете создать файл (ошибка Structure needs cleaning), это может быть следствием известного бага в старых версиях ядра. Ошибка возникает в последней, урезанной группе AG. Решением часто является обновление ядра до исправленной версии, после чего может потребоваться принудительная починка (xfs_repair -L, что удаляет журнал).
Файловая система XFS разбивает блоки на группы распределения (AG). Максимальный размер каждой группы фиксирован. Утилита mkfs.xfs по умолчанию старается распределить блоки равномерно между четырьмя AG, а для файловых систем больше 4 ТиБ создаёт больше групп. При расширении файловой системы количество AG при необходимости тоже увеличивается.
Однако количество блоков файловой системы далеко не всегда делится на AG без остатка. К тому же расширение файловых систем редко происходит ровно на величину, кратную размеру AG. В результате последняя AG почти всегда оказывается меньше всех остальных.
Иноды для новых файлов и каталогов выделяются группами по 64 штуки. При стандартных 512-байтных инодах и 4-кибибайтных блоках такая группа занимает 32 КиБ, то есть 8 блоков файловой системы.
Ядро применяет дополнительную хитрость, когда группа инодов упирается в конец AG и целиком там не помещается: оно выделяет столько, сколько влезает, и группа инодов получается короче обычной. Таким образом, ядро ограничивает выделение инодов пределами текущей AG.
Когда ядро выделяет инод в укороченной группе, которая находится в последней, меньшей по размеру AG, оно ошибочно ограничивает выделение не реальным размером этой AG, а размером нормальной, полной AG. Иными словами, ядро пытается писать за пределы файловой системы. Оно обнаруживает выход за границы и возвращает ошибку EUCLEAN (структура требует очистки).
Исправляющий эту ошибку патч принят в основную ветку ядра.
Но есть загвоздка: файловые системы, которые уже затронуты ошибкой, не позволят установить обновлённое ядро. В проблемных каталогах невозможно создать ни файл, ни каталог, поэтому пакетный менеджер (например, rpm) аварийно завершится, как только ядро попытается выделить инод в последней AG.
Понятно, что нужно обновиться. Однако, у меня ядро, в которой вышеописанный баг исправлен.
Восстановление файловой системы
Файловую систему не плохо бы пофиксить. Остановим все процессы, которые пишут на диск с проблемной XFS, у меня /dev/sda1. Я уже ранее писал, что не рекомендую XFS использовать на системном диске.
Запустим проверку:
xfs_repair -n /dev/sda1
И видим:
Inode allocation btrees are too corruptedПробуем исправить:
xfs_repair /dev/sda1
И всё починилось.
Ошибка оказалась как-то связана с расширением файловой системы. Данные уцелели.
