Лимиты inode в xfs
XFS является очень популярной файловой системой. Она стала такой популярной после того как RedHat сделал ее фс по умолчанию для redhat 7. Среди преимуществ xfs выделяют динамическое выделение inode, поддержку дисковых квот, ну и остальные преимущества журналируемых фс. Про псевдо Copy-on-write можно почитать тут. Однако это не обычный CoW, все немного сложнее.
B-Tree
Структура xfs основывается на B-деревьях, точнее их разновидности B+Tree. Если вы хотите познакомиться с теорией B-деревьев то рекомендую замечательное видео Володи Моженкова. У него вобще довольно много интересных видео про структуры данных и аглоритмы.
А зачем B-деревья вообще используют в файловых системах? Эти структуры данных обладают характеристиками, которые делают их идеально подходящими для организации и управления большими объемами данных, особенно на дисковых устройствах. Это позволяет эффективнее использовать дисковое пространство, иметь быстрый доступ к данным, снижать количество операций ввода/вывода, удобно обновлять и удалять данные.
Среди преимуществ XFS выделяют ускорение производительности благодаря Allocation Groups, онлайн дефрагментация, расширение на лету. Конечно, есть и минусы: нельзя уменьшить xfs; медленные операции с метаданными по сравнению с фс вышедшими позднее, проблема с временными метками на пороге 2038 года (которая была решена введением 64 битных таймштампов для inode в версии ядра 5.10 в 2020 году)
Если вы хотите залезть под капот XFS, и посмотреть как в реальности выглядят эти структуры на диске, из чего состоит суперблок, как выглядят inode на диске, то рекомендую к прочтению цикл статей Hal Pomeranz либо гигантский труд Silicon Graphics на 184 страницах. Там все очень, очень подробно.
Среди файловых систем не только XFS использует B-деревья. Другие фс также основаны на них: NTFS (New Technology File System): Использует B+-tree для управления индексами файлов и метаданными. HFS+ (Hierarchical File System Plus): Файловая система, используемая в macOS, также применяет B+-tree для хранения каталогов и файлов. ReiserFS: Файловая система, использующая сбалансированные деревья для эффективного управления файловой структурой. Ну и самая свежая BTRFS, которая является фс по умолчанию для Fedora Workstation.
inode
inode, или его еще называют индексным дескриптором - важная часть файловой системы. Это структура данных, которая хранит в себе информацию о файле или директории, включая имена. Каждый inode содержит в себе атрибуты а также указания на дисковые блоки, в которых хранятся данные файла.
Тут я немного задумался, а какой род у inode в русском языке. Это он или она ? “Структура данных” - она. “Индексный дескриптор” - он. “Айнод или инод” - он. Будем считать что и так и так правильно.
Однако, меня сильно заинтересовала возможность динамического выделения inode, которые, как говорит реклама, должны выделяться по запросу, когда inode подходят к концу. У систем семейства ext, к примеру количество inode является фиксированным, и зависит от общего объема файловой системы. Хочешь получить больше inode - увеличь размер файловой системы. Но все ли так гладко и могут ли inodes выделяться бесконечно ? Конечно нет. У любой системы есть свои пределы. XFS не исключение.
inode options
При создании XFS с помощью утилиты mkfs.xfs можно указать параметр -i inode_options. Далее я приведу свой перевод официального man от mkfs.xfs с моими комментариями.
Размер inode
Тут можно указать размер переменной части inode. Поясню, inode состоит из фиксированной по размеру части, и переменной по размеру части, (размер которой можно указать) которая может содержать данные каталога для небольших каталогов; данные атрибутов для небольших наборов атрибутов; данные символических ссылок для небольших символических ссылок; список экстентов файла, для файлов с небольшим количеством экстентов; и корень дерева, описывающий расположение экстентов файла, для файлов с большим количеством экстентов.
Опции которые можно указать для inode:
size=value | log=value | perblock=value
Размер inode указывается либо при помощи size - это размер в байтах, либо как логарифм или основываясь на блоке фс. Подробней можно почитать в man mkfs.xfs.
Минимальное значение (и значение по умолчанию) составляет 256 байт без CRC(контрольной суммы), либо 512 байт с включенной CRC. Максимальное значение — 2048 байт (2 Кбайт) с учетом ограничения: размер inode не может превышать половину размера блока файловой системы.
XFS внутренне использует 64-битные номера индексных дескрипторов; однако на количество значащих битов в номере индексного дескриптора влияет геометрия файловой системы. На практике преобладающими факторами являются размер файловой системы и размер индексного дескриптора. Ядро Linux (на 32-разрядных аппаратных платформах) и большинство приложений в настоящее время не могут обрабатывать номера индексных дескрипторов, превышающие 32 значащих бита, поэтому, если в командной строке не указан размер индексных дескрипторов, mkfs.xfs попытается выбрать такой размер, чтобы номера индексных дескрипторов были < 32 бит. Если указан размер индексного дескриптора или если файловая система достаточно велика, mkfs.xfs выдаст предупреждение, если это приведет к созданию номеров индексных дескрипторов > 32 значащих битов.
maxpct
Этот параметр определяет максимальный процент пространства в файловой системе, который может быть выделен для индексных дескрипторов. Значение по умолчанию составляет 25% для файловых систем размером менее 1 ТБ, 5% для файловых систем размером от 1 Тб до 50 ТБ и 1% для файловых систем размером более 50 ТБ.
В режиме выделения индексных дескрипторов по умолчанию блоки индексных дескрипторов выбираются таким образом, чтобы номера индексных дескрипторов не превышали 32 бита, что ограничивает блоки индексных дескрипторов нижней частью файловой системы. Распределитель блоков данных будет избегать этих нижних блоков, чтобы соответствовать указанному maxpct, поэтому высокое значение может привести к тому, что файловая система будет содержать только индексные дескрипторы в значительной части нижних блоков файловой системы. (Это ограничение отсутствует, если файловая система смонтирована с опцией inode64 на 64-битных платформах).
Тут у меня есть некоторые претензии к официальному man утилиты mkfs.xfs, поскольку 64-битные системы уже повсеместно распространены, и начиная с версии ядра 3.7 опция inode64 является опцией по умолчанию для 64-битных систем. Так что можно не переживать за эти ограничения, если вы не используете старые linux системы и 32-битную архитектуру процессора. В этом можно убедиться посмотрев опции монтирования через команду mount уже подключенной xfs. пример:
root@server:~# mount |grep /dev/vdi /dev/vdi on /temp/testmount type xfs (rw,relatime,nouuid,attr2,inode64,logbufs=8,logbsize=32k,noquota)
Установка значения maxpct=0 означает, что практически вся файловая система может стать блоками индексных дескрипторов. Это значение можно изменить с помощью xfs_growfs.
Параметры maxpct и isize можно посмотреть с помощью утилит xfs_info или xfs_db, также они пишутся при создании фс с помощью mkfs.xfs. К примеру возьмем один диск размером примерно 1 Гб и создадим на нем xfs:
root@jumpbox:~# mkfs.xfs /dev/vdc
meta-data=/dev/vdc isize=512 agcount=4, agsize=65536 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1 bigtime=1 inobtcount=1 nrext64=0
data = bsize=4096 blocks=262144, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=16384, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
Discarding blocks...Done.
Как видно, создалась фс с размером inode в 512 байт (isize), и inode максимально могут занять 25% общего объема файловой системы (imaxpct). Но как же увидеть сколько сейчас выделено inode? Это можно посмотреть утилитой df:
root@jumpbox:/# df -i /test
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vdc 524288 3 524285 1% /test
Всего inode выделилось 524288, а занято из них 3. Посчитаем, какой объем от объема файловой системы займут inode если заполнить все выделенные inode. Умножаем количество inode на размер isize: 524288 * 512 = 268435456 байт что соответствует 256 Мб. Это и есть примерно 25% от всей файловой системы размером около 1 Гб:
root@jumpbox:/# df -k /dev/vdc
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/vdc 983040 39908 943132 5% /test
размер системы 983040 кб, это примерно 960 Мб.
Таким образом система сразу выделила пространство размером примерно 25% объема файловой системы для inode.
На самом деле в рассчете получилось даже больше, примерно 26,6%. Вероятно из-за того что df -k показывает размер фс в 1 Кб блоках.
Давайте посмотрим что будет если заполнить диск файлами до максимума inode. Для быстрого создания файлов используем утилиту parallel.
# Создание 500000 файлов параллельно
seq 1 500000 | parallel -j 10 'touch $directory_path/file_{}'
после того как осталось 32 свободных inode, XFS отказывается создавать новые файлы:
root@jumpbox:/test# df -i /dev/vdc
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vdc 524288 524256 32 100% /test
root@jumpbox:/test# touch 32131
touch: cannot touch '32131': No space left on device
Используя xfs_growfs увеличим параметр imaxpct, и проверим что количество inode динамически увеличилось:
root@jumpbox:/test# xfs_growfs -m 30 /dev/vdc
meta-data=/dev/vdc isize=512 agcount=4, agsize=65536 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1 bigtime=1 inobtcount=1 nrext64=0
data = bsize=4096 blocks=262144, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=16384, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
inode max percent changed from 25 to 30
root@jumpbox:/test# df -i /dev/vdc
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/vdc 629144 524256 104888 84% /test
root@jumpbox:/test# touch 321123
Как видим, количество выделеных inode действительно выросло до 629144, что составляет 30% от объема файловой системы, и теперь занято 84% от их количества. Увеличивать imaxpct можно онлайн на смонтированной файловой системе. Отдавать все пространство файловой системы под inode не очень разумно. Здесь нужен расчет исходя из объема и количество файлов предполагаемых к хранению на XFS.
P.S. единственный момент который для меня оказался неясен в этом маленьком расследовании, всегда ли XFS выделяет сразу весь объем inode который соответствует imaxpct. Возможно, на больших объемах будут выделяться не сразу все inodes, но в документации я не нашел указаний на этот счет. Если мне удастся найти возможность протестировать это на больших дисках, то я дополню эту статью.
Оставить комментарий