Файловые системы
Файловая система отображает имена файлов и каталогов на блоки диска. ext4 — надёжный выбор по умолчанию; xfs масштабируется для больших файлов; btrfs добавляет copy-on-write и снимки. Inodes хранят метаданные — и их можно исчерпать, пока диск ещё полон.
У тебя есть чистый раздел, и ты хочешь хранить на нём файлы. Раздел — это просто последовательность сырых байт: у неё нет понятия «файл» или «каталог». Файловая система — слой, который вносит эту структуру: она решает, как нарезать байты на файлы, где хранить имена файлов, как отслеживать, какие блоки принадлежат какому файлу, и как восстановиться после прерванной записи из-за отключения питания.
Выбор файловой системы имеет значение в production: неправильная для твоей нагрузки вызывает провалы производительности. А один малоизвестный сценарий отказа — исчерпание inode при том, что df показывает гигабайты свободного места — введёт тебя в глубокое замешательство, если ты не встречал его раньше.
После этого урока ты сможешь объяснить, что делает файловая система и что такое inode, создать файловую систему с помощью mkfs, описать ключевые различия между ext4, xfs и btrfs, и диагностировать ошибку «no space left on device» при исчерпании inode несмотря на свободное место на диске.
Файловая система отображает имена файлов и каталогов на блоки диска. При записи файла файловая система выбирает блоки, записывает туда данные и фиксирует отображение в структурах метаданных. При чтении файла она ищет отображение и собирает данные обратно.
Ключевые структуры:
- Суперблок — главная запись: тип ФС, общий размер, размер блока, количество inode, указатели на дескрипторы групп блоков. При повреждении суперблока ФС не монтируется. ext4 хранит резервные копии суперблока в нескольких группах блоков именно для этого.
- Группы блоков — ext4 делит раздел на группы блоков. У каждой группы своя битовая карта блоков (какие блоки свободны), битовая карта inode и таблица inode. Благодаря локальности чтение файла обычно затрагивает одну группу блоков, а не случайные места диска.
- Inode (index node) — запись фиксированного размера (256 байт в ext4), хранящая всё о файле кроме его имени: UID/GID владельца, права, метки времени (atime/mtime/ctime), размер и указатели на блоки данных.
- Запись каталога (dentry) — отображение имени файла в номер inode. Каталог — это тоже файл, данные которого представляют собой список пар
(имя_файла, номер_inode).
# Посмотреть метаданные файловой системы для смонтированного раздела
stat /etc/hostname
# File: /etc/hostname
# Size: 10 Blocks: 8 IO Block: 4096 regular file
# Device: 8,3 Inode: 2621554 Links: 1
# Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
# Access: 2024-06-20 09:12:01
# Modify: 2024-01-15 14:22:03
# Номер inode 2621554 — внутренний идентификатор файла в ФС
# Имя '/etc/hostname' — просто dentry, указывающая на этот inodeext4 — файловая система Linux по умолчанию и безопасный выбор для большинства нагрузок. Она используется по умолчанию на Debian/Ubuntu с 2010 года, имеет отличный инструментарий fsck и надёжно переживает отключения питания благодаря журналированию.
# Создать файловую систему ext4 на разделе
sudo mkfs.ext4 /dev/sda3
# mke2fs 1.47.0 (5-Feb-2023)
# Creating filesystem with 130678784 4k blocks and 32669696 inodes
# Filesystem UUID: e5f6a7b8-c9d0-1234-5678-abcdef012345
# Superblock backups stored on blocks: 32768, 98304, 163840, ...
# Allocating group tables: done
# Writing inode tables: done
# Creating journal (131072 blocks): done
# Writing superblocks and filesystem accounting information: done
# Задать количество inode вручную (для нагрузок с множеством файлов, например mail-серверов)
sudo mkfs.ext4 -N 8000000 /dev/sda3 # 8 миллионов inode вместо значения по умолчанию
# Добавить метку (удобно для fstab и идентификации)
sudo mkfs.ext4 -L data /dev/sda3
# Посмотреть метаданные ФС после создания
sudo tune2fs -l /dev/sda3 | grep -E 'Inode count|Block count|Block size|Journal'
# Inode count: 32669696
# Block count: 130678784
# Block size: 4096
# Journal inode: 8Журналирование обеспечивает надёжность ext4. Перед записью в структуры ФС она записывает запись в журнал (выделенную область на диске). При аварийном сбое fsck воспроизводит журнал для восстановления согласованности вместо сканирования всего диска.
xfs и btrfs покрывают нагрузки, где ext4 не является лучшим выбором.
# Создать xfs (большие файлы, высокая пропускная способность: базы данных, видео)
sudo mkfs.xfs /dev/sdb1
# meta-data=/dev/sdb1 isize=512 agcount=4, agsize=65536 blks
# data = bsize=4096 blocks=262144, imaxpct=25
# Создать btrfs (снимки, подтома, прозрачное сжатие, контрольные суммы)
sudo mkfs.btrfs /dev/sdc1
# btrfs-progs v6.1
# UUID: 9f8e7d6c-...
# Features: skinny-metadata, no-holesКлючевые различия:
| Характеристика | ext4 | xfs | btrfs |
|---|---|---|---|
| Журналирование | да (метаданные + опционально данные) | да (метаданные) | copy-on-write (журнал не нужен) |
| Макс. размер файла | 16 ТиБ | 8 ЭиБ | 16 ЭиБ |
| Снимки | нет (нужен LVM) | нет (нужен LVM) | да, встроенные, мгновенные |
| Сжатие онлайн | нет | нет | да (zstd, lzo, zlib) |
| Уменьшение онлайн | нет | нет | нет (только офлайн) |
| Увеличение онлайн | да | да | да |
| Лучше всего подходит для | общего назначения, загрузки, home | больших файлов, БД, высокого I/O | снимков, дедупликации, NAS |
| По умолчанию | Ubuntu (root) | RHEL | Fedora с F33 |
Производительность записи btrfs может уступать ext4/xfs на HDD при интенсивной записи из-за накладных расходов copy-on-write. На SSD разница невелика.
Inode — это фиксированный пул. Его можно исчерпать, пока на диске ещё есть место. Это одна из самых сбивающих с толку ошибок для оператора.
# Проверить использование inode — ЭТУ ПРОВЕРКУ ЧАСТО ЗАБЫВАЮТ
df -i
# Filesystem Inodes IUsed IFree IUse% Mounted on
# /dev/sda3 32669696 3100000 29569696 9% /
# /dev/sda2 131072 78000 53072 60% /boot
# /var/spool/mail 524288 524287 1 100% /var/mail <- ПОЛНО!
# Что происходит при исчерпании inode:
# touch /var/mail/newfile
# touch: cannot touch '/var/mail/newfile': No space left on device
# НО:
df -h /var/mail
# Filesystem Size Used Avail Use% Mounted on
# /dev/sdc1 20G 8.1G 11.9G 41% /var/mail <- 41% свободно! Но inode нет.
# Подсчитать файлы в подозрительном каталоге
find /var/spool/postfix/deferred -type f | wc -l
# 524281 <- mail-сервер поставил в очередь 524 281 письмо, каждое — один inode
# Сколько inode было выделено при mkfs?
sudo tune2fs -l /dev/sdc1 | grep 'Inode count'
# Inode count: 524288 <- mkfs.ext4 рассчитал по общему размеру, не по нагрузкеИсправление: либо удалить файлы, потребляющие inode, либо переформатировать с бо́льшим количеством inode (mkfs.ext4 -N <count>). Добавить inode в существующую ext4 без переформатирования нельзя. У xfs и btrfs динамическое выделение inode — у них эта проблема отсутствует.
Суперблок — главная запись файловой системы, а знание расположения резервных копий спасает данные.
# Найти расположение резервных суперблоков (полезно при повреждении основного)
sudo mke2fs -n /dev/sda3 # -n = dry run, показывает что сделал бы mkfs
# Superblock backups stored on blocks: 32768, 98304, 163840, 229376, ...
# Если основной суперблок (блок 0) повреждён:
sudo fsck.ext4 -b 32768 /dev/sda3 # использовать резервную копию в блоке 32768
# e2fsck 1.47.0 (using backup superblock at block 32768)
# /dev/sda3: recovering journal
# /dev/sda3: clean, 3100000/32669696 files, 24500000/130678784 blocks
# Проверить и восстановить ФС (должна быть размонтирована)
sudo umount /dev/sda3
sudo fsck.ext4 -f /dev/sda3 # -f = принудительная проверка, даже если помечена чистой
# Для xfs (использует воспроизведение журнала, а не сканирование как fsck)
sudo xfs_repair /dev/sdb1 # должна быть размонтирована
# Для btrfs
sudo btrfs check /dev/sdc1 # проверка только для чтения; --repair использовать с осторожностьюНикогда не запускай fsck на смонтированной файловой системе. В ext4 ядро помечает ФС «чистой» при размонтировании и «грязной» при монтировании. При загрузке systemd запускает fsck на разделах, помеченных как грязные (pass 1 или 2 в /etc/fstab).
Диагностика «no space left on device» на mail-сервере, где ещё есть свободное место на диске.
# Алерт: доставка почты падает с "no space left on device"
df -h /var/spool
# Filesystem Size Used Avail Use% Mounted on
# /dev/sdb1 50G 22G 28G 44% /var/spool <- 44% свободно, выглядит нормально
# Проверяем inode — вот что обычно забывают
df -i /var/spool
# Filesystem Inodes IUsed IFree IUse% Mounted on
# /dev/sdb1 3276800 3276800 0 100% /var/spool <- 100% inode заняты!
# Найти каталог с наибольшим количеством файлов
find /var/spool -xdev -type d | while read dir; do
echo "$(find "$dir" -maxdepth 1 -type f | wc -l) $dir"
done | sort -rn | head -5
# 3241000 /var/spool/postfix/deferred
# 35000 /var/spool/postfix/active
# В очереди deferred 3,2 млн писем — каждое отдельный файл = один inode
# Срочное исправление: сбросить очередь
sudo postsuper -d ALL deferred # Postfix: удалить все отложенные письма
# Или исследовать причину отложенности:
sudo mailq | tail -5
# Долгосрочное решение: переформатировать с бо́льшим количеством inode
# mkfs.ext4 -N 10000000 /dev/sdb1 <- 10M inode для mail-сервера
# Или использовать xfs (динамическое выделение inode, нет фиксированного пула)Вывод: при ошибке «no space left on device» всегда проверяй df -i наряду с df -h. На mail-сервере, при нагрузке с мелкими файлами или в хранилище слоёв контейнеров исчерпание inode — реальный сценарий отказа.
▸Почему это работает
Почему разработчики файловых систем использовали фиксированный пул inode вместо динамического выделения? В ext2 (предшественник ext4, разработан в 1993 году) inode необходимо было выделять заранее для обеспечения поиска inode за константное время по номеру. Схема динамического выделения потребовала бы более сложных структур на диске. xfs (также 1993, от SGI) с самого начала решил это иначе: выделение inode основано на B-дереве и полностью динамическое. Формат журнала ext4 разрабатывался с обратной совместимостью с ext2, поэтому компромисс с фиксированным пулом был сохранён. Если ты регулярно создаёшь ext4 для нагрузок, порождающих миллионы мелких файлов, задай бо́льший коэффициент inode при mkfs: mkfs.ext4 -T news /dev/sdb1 (профиль news задаёт один inode на 4 КиБ вместо стандартного одного на 16 КиБ).
▸Частая ошибка
Не запускай mkfs на устройстве, которое смонтировано, даже если данные на нём уже не нужны. Ядро кешировало inode и данные блоков для этого устройства. Запись нового заголовка ФС при смонтированной старой создаёт расщеплённое состояние: уровень VFS всё ещё читает старую ФС, а на диске уже новый суперблок. Это может повредить данные на соседних разделах через перепутанные пути записи. Всегда размонтируй (umount /dev/sdb1) и проверяй командой mount | grep sdb1 (пустой вывод = размонтировано) перед запуском mkfs.
Сервер с высоконагруженной почтовой системой сообщает 'No space left on device' при попытке создать новые файлы. df -h показывает 45% использования диска. Какова наиболее вероятная причина и как её подтвердить?
Файловая система накладывает структуру файлов и каталогов на сырой блочный раздел. Ключевые структуры: суперблок (главная запись метаданных), inode (метаданные файла: владелец, права, метки времени, указатели на блоки) и записи каталога (отображения имени в номер inode). ext4 — стандарт Debian/Ubuntu: журналируемый, стабильный, отличный инструментарий. xfs подходит для больших файлов и высокой пропускной способности (стандарт RHEL). btrfs добавляет copy-on-write, снимки и динамическое выделение inode. Создавай ФС командами mkfs.ext4, mkfs.xfs или mkfs.btrfs. Критический подводный камень: ext4 при форматировании выделяет фиксированный пул inode — его можно исчерпать до того, как закончится место на диске. df -i показывает использование inode; всегда проверяй его вместе с df -h при диагностике «no space left on device».
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.