open atlas
↑ К треку
Linux: операционная система LIN · 06 · 02

Файловые системы

Файловая система отображает имена файлов и каталогов на блоки диска. ext4 — надёжный выбор по умолчанию; xfs масштабируется для больших файлов; btrfs добавляет copy-on-write и снимки. Inodes хранят метаданные — и их можно исчерпать, пока диск ещё полон.

LIN Middle ◷ 22 min
Уровень
ОсновыJuniorMiddleSenior

У тебя есть чистый раздел, и ты хочешь хранить на нём файлы. Раздел — это просто последовательность сырых байт: у неё нет понятия «файл» или «каталог». Файловая система — слой, который вносит эту структуру: она решает, как нарезать байты на файлы, где хранить имена файлов, как отслеживать, какие блоки принадлежат какому файлу, и как восстановиться после прерванной записи из-за отключения питания.

Выбор файловой системы имеет значение в production: неправильная для твоей нагрузки вызывает провалы производительности. А один малоизвестный сценарий отказа — исчерпание inode при том, что df показывает гигабайты свободного места — введёт тебя в глубокое замешательство, если ты не встречал его раньше.

Цель

После этого урока ты сможешь объяснить, что делает файловая система и что такое inode, создать файловую систему с помощью mkfs, описать ключевые различия между ext4, xfs и btrfs, и диагностировать ошибку «no space left on device» при исчерпании inode несмотря на свободное место на диске.

1

Файловая система отображает имена файлов и каталогов на блоки диска. При записи файла файловая система выбирает блоки, записывает туда данные и фиксирует отображение в структурах метаданных. При чтении файла она ищет отображение и собирает данные обратно.

Ключевые структуры:

  • Суперблок — главная запись: тип ФС, общий размер, размер блока, количество 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, указывающая на этот inode
2

ext4 — файловая система 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 воспроизводит журнал для восстановления согласованности вместо сканирования всего диска.

3

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

Ключевые различия:

Характеристикаext4xfsbtrfs
Журналированиеда (метаданные + опционально данные)да (метаданные)copy-on-write (журнал не нужен)
Макс. размер файла16 ТиБ8 ЭиБ16 ЭиБ
Снимкинет (нужен LVM)нет (нужен LVM)да, встроенные, мгновенные
Сжатие онлайннетнетда (zstd, lzo, zlib)
Уменьшение онлайннетнетнет (только офлайн)
Увеличение онлайндадада
Лучше всего подходит дляобщего назначения, загрузки, homeбольших файлов, БД, высокого I/Oснимков, дедупликации, NAS
По умолчаниюUbuntu (root)RHELFedora с F33

Производительность записи btrfs может уступать ext4/xfs на HDD при интенсивной записи из-за накладных расходов copy-on-write. На SSD разница невелика.

4

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 — у них эта проблема отсутствует.

5

Суперблок — главная запись файловой системы, а знание расположения резервных копий спасает данные.

# Найти расположение резервных суперблоков (полезно при повреждении основного)
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-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 4 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.