Перейти к содержанию

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


ext4

Дефолт большинства дистрибутивов (проверенная временем) + Журналируемая

  • Стабильность, отличная поддержка инструментов (e2fsck, tune2fs, resize2fs), быстрый fsck, журнал, extents, delayed allocation.
  • Нет CoW, нет нативных снапшотов, нет компрессии, нет встроенной защиты от bitrot (checksums только для метаданных; для данных — с ядра 5.4 через data_checksum, но фича experimental).
  • Фишки: до 1 EiB, до 16 TiB на файл, tune2fs -O fast_commit ускоряет fsync, chattr +C для отключения журналирования на горячих файлах.

Архитектура: block groups + журнал

ext4 — прямая эволюция ext3/ext2. Диск нарезан на block groups фиксированного размера (обычно 128 MiB), каждая содержит свой кусок bitmap свободных блоков, таблицу inode и данные. Это даёт локальность: файл и его метаданные стараются жить в одной группе — короткий seek на HDD.

Поверх — журнал (JBD2). По умолчанию режим data=ordered: в журнал пишутся только метаданные, но данные принудительно сбрасываются на диск ДО коммита метаданных. Это компромисс между скоростью (data=writeback) и надёжностью (data=journal, где журналятся и данные тоже — медленно, зато выживает любой crash).

Extents (с ext4) вместо block maps ext3: один extent описывает непрерывный диапазон блоков одной записью. Большие файлы хранятся компактно в дереве extent'ов, поиск блока — O(log n).

Delayed allocation: ext4 не выбирает физические блоки сразу при write(), а копит изменения в памяти и аллоцирует пачкой при fsync/flush. Меньше фрагментации, лучше throughput. Обратная сторона — при питании-в-розетку терялись свежие файлы (знаменитый bug 2009 года в Ubuntu); закрыто через auto_da_alloc, но осадочек остался.

Следствия

  • Журнал — это не CoW. Запись блока перезаписывает его на месте; в случае crash журнал даёт «откат к консистентному состоянию», а не «атомарную транзакцию для пользователя».
  • Никаких снапшотов: нет дерева версий, есть один актуальный набор inode.
  • fsck быстрый и предсказуемый — чинит конкретные структуры (bitmap, inode-таблицы, журнал), а не «перестраивает всё из CoW-дерева».

Хорошо

  • Зрелость. ext4 в проде с 2008, ext3 — с 2001. Самая обкатанная ФС в Linux. Поведение под любой нагрузкой задокументировано, у любого админа есть мускульная память на e2fsck/tune2fs/dumpe2fs.
  • Предсказуемая производительность. Нет CoW-фрагментации, нет «внезапного balance», нет sudden ENOSPC. На HDD + БД с random write ext4 часто обгоняет Btrfs/ZFS без тюнинга.
  • Лучший fsck в мире. e2fsck чинит почти всё, что не уничтожено физически: повреждённый суперблок (есть backup superblocks: mke2fs -n покажет offsets), сломанные inode, поломанные директории. Время fsck растёт с числом inode, но в разы быстрее xfs_repair.
  • Resize в обе стороны. resize2fs умеет и расширить (online), и сжать (offline, после umount). Редкая фича — XFS не умеет shrink, ZFS тоже.
  • Шифрование на уровне ФС. fscrypt — per-directory encryption (как в Android/ChromeOS). Не требует LUKS, можно шифровать только /home или конкретные подпапки.
  • Прогноз: будет работать всегда. ext4 не зависит от модной фичи года или конфликта мейнтейнеров. Даже когда bcachefs выпилят из ядра, ext4 останется.

Плохо

  • Нет CoW — нет снапшотов, нет атомарных переключений версий конфига/контейнера. Хочешь снапшот — лезь в LVM thin снизу.
  • Нет checksums данных. Если диск молча испортит блок (bitrot), ext4 этого не заметит — отдаст битый блок приложению. На enterprise SSD/HDD с end-to-end protection это менее остро, на consumer-железе с большими объёмами — реальный риск.
  • Нет компрессии. Логи, дампы, текстовые данные занимают полный размер. Лечится только на уровне приложения (gzip/zstd на pipeline'е).
  • Нет нативного multi-device. ext4 живёт на одном блочном устройстве. Нужен RAID — mdraid снизу, нужен пул дисков — LVM. Стек получается многоэтажный.
  • Фрагментация на долгоживущих директориях с миллионами мелких файлов. Не катастрофа, но e4defrag существует не просто так.
  • Inode-таблица фиксирована при mkfs. mkfs.ext4 -N или -i задают число inode. Если упёрся — единственный путь mkfs заново. На FS с миллионами мелких файлов (mail spool) это реальная проблема. XFS и Btrfs аллоцируют inode динамически.

Грабли

  1. Inode exhaustion при свободном месте. df -i показывает 100% used, df — 30%. Лечения «на лету» нет, только mkfs.
  2. data=writeback теряет данные при crash, но включают «для скорости» — потом удивляются.
  3. fsck требует umount: для корня — single-user или fsck.mode=force через initramfs.
  4. resize2fs shrink требует e2fsck сначала, сжимать можно только до объёма используемых данных.
  5. Discard/TRIM: монтировать с discard замедляет delete на SSD; правильнее fstrim по cron/таймеру systemd.

XFS

Дефолт в RHEL/Rocky/Alma. Заточена под крупные файлы и параллелизм.

  • Отличный throughput на больших файлах и многопоточной нагрузке (allocation groups), online defrag (xfs_fsr), reflinks (CoW-копии файлов), DAX, real-time subvolume.
  • Раньше нельзя было уменьшать (shrink) — до сих пор нельзя. Тяжелее ext4 на мелких файлах. fsck требует много памяти.
  • Фишки: xfs_io -c "reflink" — мгновенные CoW-копии, идеально для контейнерных образов и снапшотов БД.

Архитектура: allocation groups + B+ деревья + журнал

XFS родилась в Silicon Graphics (IRIX, 1993) для видеомонтажа и научных вычислений — то есть для очень больших файлов и многотерабайтных томов на multi-CPU машинах. Это вся ДНК ФС.

Диск делится на Allocation Groups (AG) — обычно 4 и более, каждая со своими структурами учёта (free space btree по offset и по size, inode btree, reverse-mapping btree с v5). AG — это не block group ext4: каждая AG работает почти независимо, со своим локом, поэтому параллельные write'ы в разные файлы идут параллельно в разные AG без contention. Отсюда легендарный scalability на NUMA-машинах.

Inode аллоцируются динамически — нет глобальной таблицы как в ext4. Сколько надо мелких файлов — столько inode. Лимит — свободное место.

Всё внутри — B+ деревья. Свободные блоки, экстенты файлов, inode, директории, ACL, reverse-map. Поэтому XFS отлично масштабируется на 100M+ файлов в директории, на терабайтные файлы, на тысячи параллельных потоков. ext4 на таком захлёбывается.

Журнал — metadata-only (как ext4 data=ordered, своего data=journal-режима нет). По умолчанию internal (на том же AG-0), можно вынести на отдельное устройство (-l logdev=) — пишут на NVRAM или быстрый SSD в HPC-конфигурациях.

Delayed allocation, speculative preallocation (XFS заранее резервирует чуть больше места при росте файла, чтобы избежать фрагментации), extent hint'ы.

Версия v5 on-disk format (с 2014, дефолт с RHEL 7.3): CRC32 на ВСЕ метаданные, reverse-mapping (rmapbt) для self-healing, reflinks. Старые v4 в RHEL 9 deprecated.

Следствия

  • На больших файлах и параллельной нагрузке (БД, Kafka, MinIO, видеостриминг, HPC) XFS почти всегда быстрее ext4 и предсказуемее Btrfs.
  • На массе мелких файлов (mail, мелкие конфиги, исходники) ext4 чуть шустрее из-за более компактных директорий и меньшего overhead AG.
  • Журнал не защищает данные, только метаданные. После crash файл может быть «частично записан» с дырой нулей. fsync делает то, что должен; mount option sync — для параноиков.
  • Shrink невозможен в принципе. AG-структуры аллоцированы по всему тому, переехать не могут. Это by design, не «не успели реализовать».

Хорошо

  • Производительность на больших и параллельных нагрузках. Confluent рекомендует XFS для Kafka. MinIO — официально XFS only для прода (на других ФС работает, но не саппортится). EDB/AWS RDS советуют XFS для Postgres. Рекомендации не из вежливости.
  • Reflinks (с v5). cp --reflink, xfs_io -c "reflink" — мгновенное CoW-копирование файла. Поверх Postgres даёт pg_basebackup --reflink (PG16+), поверх контейнеров — overlayfs-style сборка образов. Это «полу-снапшоты»: не subvolume, но отдельные файлы делить блоки умеют.
  • Online grow. xfs_growfs расширяет ФС без размонтирования. Стандартный сценарий «lvextend + xfs_growfs» отработан до автоматизма.
  • Online defrag. xfs_fsr перебирает файлы по фрагментации и переписывает их компактно, не останавливая нагрузку. У ext4 e4defrag тоже есть, но xfs_fsr старше и стабильнее.
  • Reverse-mapping (rmapbt) с v5. Когда диск сообщает «бэд-сектор LBA X», rmapbt мгновенно отвечает «это файл /var/log/foo, offset 4 MiB» — без обхода всей ФС.
  • Quotas — нормальные, без btrfs-style тормозов. Project quotas (по дереву директорий, не только по uid/gid) — фича XFS, которой нет в ext4.
  • DAX. На persistent memory (Optane и подобные) XFS умеет direct access без page cache — read/write идут прямо в NVDIMM. Очень узкая ниша, но единственная нормально работающая.

Плохо

  • Shrink невозможен. Захотел уменьшить ФС — только бэкап + mkfs + restore. Главная причина, по которой ext4 всё ещё используют для root.
  • Не любит memory pressure при fsck. xfs_repair загружает в RAM структуры всей ФС; на больших томах (десятки TiB) может потребоваться 16–64 GiB RAM. Можно -m maxmem или -o bhash=N, но если памяти физически нет — fsck не сделать.
  • Удаление миллионов мелких файлов медленнее ext4. Транзакции в журнале XFS «тяжелее» из-за B+ деревьев и rmapbt.
  • Метаданные журналируются, данные — нет. После crash без fsync файл может оказаться обнулённым (zero-length). Это известно и стандартно (POSIX так и говорит), но первый раз пугает. Лечение — приложение должно делать fsync перед rename().
  • Нет нативного multi-device, нет нативного RAID. Снизу всегда LVM/mdraid. Свои снапшоты XFS не делает, только reflinks по файлам.
  • Дефолтные mount options консервативные. Для прода обычно крутят: noatime, logbsize=256k, allocsize=64k (под БД — наоборот, allocsize=1m и больше), inode64 (давно дефолт, но проверь на legacy).

Грабли

  1. xfs_growfs работает только в сторону роста. Никаких xfs_shrink не существует и не будет.
  2. xfs_repair вне initramfs не запустится для root — нужно single-user/rescue или rebuild.
  3. v4 → v5 апгрейда нет. Только mkfs.xfs и restore.
  4. xfs_quota -x требует mount с -o uquota/gquota/pquota; включить на смонтированной ФС нельзя — нужен remount/umount.
  5. allocsize слишком большой = «дыры» на маленьких файлах и потеря места до flush. Слишком маленький = фрагментация на растущих логах.

Btrfs

Дефолт в openSUSE, Fedora Workstation. Современная CoW ФС.

  • Снапшоты, subvolumes, встроенная компрессия (zstd/lzo/zlib), checksums данных и метаданных, send/receive для инкрементальной репликации, online balance, RAID 0/1/10, dedupe (offline), chattr +C для nodatacow на БД-файлах.
  • RAID 5/6 до сих пор помечен как unstable (write hole). Производительность падает на сильно фрагментированных workloads (БД, VM-образы) без nodatacow. Историческая репутация хрупкости (хотя за последние годы — заметно стабильнее).
  • Фишки: btrfs subvolume snapshot за миллисекунды, compress=zstd:3 бесплатно режет I/O на текстовых данных, Snapper/Timeshift из коробки.

Архитектура: B-tree + CoW

Copy-on-Write (CoW) — фундамент. При изменении блока:

  1. Новый блок пишется в свободное место.
  2. Указатель в дереве обновляется (тоже через CoW — родительский узел перезаписывается на новом месте).
  3. Так вверх до корня дерева.
  4. Корень дерева коммитится атомарно (через superblock update).

Следствия

  • Никаких partial writes. Либо транзакция целиком, либо её нет. Журнал в классическом смысле (как ext4) не нужен.
  • Снапшоты бесплатны — это просто новая ссылка на корень subvolume.
  • Фрагментация — обратная сторона. Случайные записи в большой файл разлетаются по диску.

Хорошо

  • Снапшоты + send/receive. btrfs send -p prev current | ssh backup btrfs receive /backup — инкрементальная репликация на уровне ФС, без rsync-сканирования. Убийственная фича для бэкапов.
  • Прозрачная компрессия. compress=zstd:3 в mount options. zstd:1 почти бесплатен по CPU, на текстах/логах/исходниках экономит 50–70%. Для бинарей/уже сжатых данных Btrfs сам понимает, что жать бесполезно (heuristic), и пропускает.
  • Reflinks. cp --reflink=always — мгновенная CoW-копия. Полезно для VM-образов (golden image → клон за миллисекунды), бэкапов, dev-окружений.
  • Checksums данных и метаданных (crc32c по умолчанию, можно xxhash/sha256/blake2). На multi-device при scrub автоматически чинятся через копию-зеркало. Защита от bitrot — то, чего нет в ext4/XFS.
  • Online всё. Resize (вверх и вниз!), balance (перераспределение чанков), defrag, добавление/удаление устройств — без размонтирования. XFS shrink, кстати, до сих пор невозможен.
  • Гибкие RAID-профили на уровне чанков, меняются на ходу: btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt.
  • Quotas через qgroups, по subvolume. Но: исторически глючные и тормозящие при больших объёмах. С simple quotas (kernel 6.7+) стало лучше.

Плохо

  • RAID 5/6 — broken by design до сих пор. Write hole не закрыта. На вики Btrfs прямым текстом: «unstable, do not use for valuable data». Для parity-RAID — ZFS или mdraid под Btrfs.
  • Производительность на БД-workload. Без nodatacow (+C) фрагментация съедает throughput. С +C — нет checksums, нет компрессии. Так себе trade-off для prod-БД. ZFS на таком же сценарии ведёт себя лучше (recordsize tuning).
  • Quota groups + большие FS = тормоза. Включённые qgroups могут заметно замедлять btrfs balance и удаление снапшотов.
  • ENOSPC-сюрпризы. Btrfs может сказать «нет места» при свободных гигабайтах, потому что чанки уже выделены под data, а metadata некуда. Лечится btrfs balance start -dusage=50. Современные ядра справляются лучше, но артефакт остался.
  • Восстановление после катастрофы. btrfs check --repair — last resort, может сделать хуже. Best practice — бэкапы и btrfs restore для вытаскивания данных. У ext4 e2fsck в этом плане куда дружелюбнее.
  • Metadata-heavy операции (rm -rf огромного дерева, find /) медленнее ext4/XFS. CoW + множественные деревья дают оверхед.

Грабли

  1. ENOSPC при свободном месте. Btrfs аллоцирует диск чанками (1 GiB для data, 256 MiB для metadata). Если все чанки расписаны под data, а metadata-чанк заполнился — записать новый файл некуда: для него нужна запись в metadata-tree.
  2. df врёт, и это by design. Используй btrfs filesystem usage / btrfs filesystem df.
  3. Снапшоты — не бесплатны в долгую. Старые снапшоты держат старые блоки, free space постепенно тает.
  4. Quota groups (qgroups) — исторический ад. До simple quotas (6.7+) — best effort стратегия «не включать».
  5. Восстановление после повреждения — стресс. План — бэкапы + btrfs restore, не btrfs check --repair.
  6. Поведение под нехваткой памяти. На тесных по RAM системах CoW + B-tree commit'ы могут вести себя непредсказуемо.

ZFS

Порт из Solaris, лицензия CDDL (поэтому не в mainline kernel).

  • Всё что у Btrfs + рабочий RAID-Z1/2/3, ARC/L2ARC (кэш в RAM + SSD), ZIL/SLOG, native encryption, send/receive, дедупликация (но прожорливая по RAM), снапшоты с zero overhead.
  • Лицензионная несовместимость с GPL — ставится через DKMS, ломается при обновлении ядра. Прожорлив по RAM (~1 GiB на 1 TiB при включённой dedupe — больше). Vdev нельзя расширить добавлением одного диска (хотя RAID-Z expansion появился в 2.3, 2024).
  • Фишки: «правильный» enterprise-grade, считается золотым стандартом для NAS/storage. TrueNAS, Proxmox, Ubuntu offer root-on-ZFS.

Архитектура: pool → vdev → dataset, CoW + Merkle-tree

ZFS — это не «ФС», а интегрированный stack: volume manager (как LVM) + RAID (как mdraid) + filesystem в одном. Layering нет принципиально: пул знает про диски, ФС знает про блоки, всё видит друг друга и принимает решения вместе.

Структура снизу вверх:

  • Физические диски объединяются в vdev (virtual device): mirror, raidz1/2/3, draid, single. Vdev — это unit of redundancy.
  • Несколько vdev объединяются в zpool. Запись страйпится по всем vdev пула (как RAID-0 поверх RAID-Z). Добавление vdev в пул расширяет ёмкость без перестройки.
  • Внутри пула создаются datasets — либо файловые системы (ZFS-FS, монтируются как любая ФС), либо zvol (блочные устройства для iSCSI/VM-дисков).
  • Снапшоты и клоны — на уровне dataset. send/receive — между dataset'ами.

Запись — CoW + transaction groups (TXG). Изменения копятся в RAM (open TXG), раз в несколько секунд (txg_timeout, по умолчанию 5s) коммитятся атомарно: новые блоки записаны, uberblock (корень) обновлён в одном из 128 ring-slot'ов. До коммита sync write'ы идут в ZIL (ZFS Intent Log) — отдельный лог для durability fsync().

Merkle-tree: каждый блок ссылается на дочерние через указатель + checksum. Поэтому ZFS обнаруживает silent corruption на любом уровне — от данных до метаданных до uberblock.

ARC (Adaptive Replacement Cache) — кэш в RAM, умнее Linux page cache: учитывает и recency, и frequency, не вымывается одним sequential scan'ом. L2ARC — расширение ARC на SSD. SLOG — отдельное устройство для ZIL (NVMe/Optane), ускоряет fsync-нагрузки.

Следствия

  • Storage stack единый, без зазоров. mdraid не знает что выше ФС, ФС не знает что снизу RAID — отсюда write hole в RAID-5. ZFS знает всё. Поэтому RAID-Z не имеет write hole: parity и data пишутся в одной транзакции, либо обе, либо ни одной.
  • Снапшоты бесплатны и мгновенны. Это просто ссылка на старый uberblock; пока новые блоки CoW-копируются, старые не удаляются.
  • send/receive передаёт diff между двумя снапшотами потоком. Инкрементальный бэкап на удалённый pool — одна команда, без rsync-сканирования.
  • Память — лекарство и яд. ARC по умолчанию забирает до 50% RAM (на FreeBSD — больше). На сервере с 8 GiB и нагруженным Postgres это конкуренция между ARC и shared_buffers; нужно крутить zfs_arc_max.

Хорошо

  • Надёжный parity-RAID. RAID-Z1/2/3 (1/2/3 диска под parity), draid (для очень больших массивов с distributed spare), mirror. В отличие от Btrfs RAID-5/6, write hole закрыта by design. Причина, по которой ZFS — стандарт для NAS/архивных хранилищ.
  • Send/receive с шифрованием. zfs send -w отправляет уже зашифрованные блоки без расшифровки на отправляющей стороне — приёмник не видит ключи. Идеальный off-site backup на untrusted машину.
  • Native encryption per-dataset. zfs create -o encryption=on -o keyformat=passphrase. Ключи можно хранить в файле/KMS, загружать lazy при первом доступе.
  • ARC. На read-heavy нагрузке ARC бьёт Linux page cache: за счёт adaptive replacement не вымывается sequential I/O (одного find / достаточно, чтобы page cache забыл всё нужное; ARC — нет).
  • Recordsize per-dataset. Для Postgres ставят 8K (= размер страницы), для Kafka сегментов — 1M, для логов/архивов — 1M с компрессией. Редкий уровень контроля.
  • Compression by default. lz4 включают почти всегда — почти бесплатен по CPU, на текстах сильно экономит I/O. zstd-3/9 — для архивных dataset'ов.
  • Scrub. Раз в неделю/месяц обходит весь пул, проверяет checksums, чинит из mirror/parity. Bitrot обнаруживается ДО того, как ты захочешь прочитать файл.
  • Снапшоты + холды. zfs hold предотвращает удаление снапшота, пока он удерживается (например, идёт send). Никаких «удалил снапшот пока шёл бэкап».
  • Self-healing. Прочитал блок с диска — checksum не сошёлся — взял с зеркала/parity, отдал приложению, переписал плохой блок. Прозрачно для приложения.
  • zvol для VM-дисков. Снапшот, клон, send/receive — поверх обычного блочного устройства. Альтернатива qcow2 + LVM thin.

Плохо

  • Лицензия CDDL. Несовместима с GPL2 ядра Linux — поэтому ZFS не может попасть в mainline. Распространяется как out-of-tree модуль (OpenZFS) через DKMS. При апгрейде ядра модуль пересобирается; если новое ядро ломает API (а это случается раз в 2–3 релиза мажоров) — апгрейд откладывается на 2–8 недель, пока выйдет новый OpenZFS.
  • Прожорлив по RAM. ARC на 50% RAM по умолчанию — не баг, by design. На 4–8 GiB машинах ZFS уже неуютно. С dedup совсем плохо: dedup-таблица сидит в ARC, ~5 GiB RAM на 1 TiB уникальных данных. Поэтому dedup в ZFS выключают чаще, чем включают.
  • Vdev неэластичный. Долго (до 2024) единственный способ расширить пул — добавить новый vdev (то есть ещё одну группу дисков). RAID-Z expansion (добавление одного диска в существующий vdev) появилось в OpenZFS 2.3 в 2024 — фича сырая, восстанавливается медленно, не убирает старый stripe-pattern.
  • Нельзя удалить vdev. Mirror убрать можно, top-level vdev — только если пул mirror-only (zpool remove). Для raidz remove не поддерживается. Ошибся на mkfs — пересоздавать пул.
  • Поведение под memory pressure хуже, чем у нативных ФС ядра. ARC долго отдаёт память обратно kernel'у, OOM-killer может пристрелить процесс, который мог бы и пожить.
  • Setup сложнее. Установить ZFS на root в Ubuntu — отдельный квест с initramfs и zfs-mount.service. Любая Linux-распределённость, кроме TrueNAS/Proxmox/Ubuntu, — это «соберите сами».
  • Не любит overcommit. zvol с volsize больше, чем свободно в пуле, можно создать через sparse — но при заполнении гость отвалится без warning. У ext4/XFS поверх LVM thin — то же самое, просто там это привычнее.
  • fsync дорогой без SLOG. Sync write идёт в ZIL (фактически — двойная запись), пока не закоммитится TXG. На обычных SSD терпимо, на HDD без SLOG — катастрофа для Postgres.

Грабли

  1. zpool import после reboot может потребовать -f, если pool был «not cleanly exported». Стандартная история на нештатном shutdown.
  2. Снапшот zvol съедает место — даже без записей, потому что любая запись в активную копию начинает плодить CoW-копии старых блоков.
  3. dedup включил → выключить нельзя. Только пересоздание пула. zfs set dedup=off отключает ТОЛЬКО для НОВЫХ записей; старые dedup-blocks остаются и сидят в DDT.
  4. ashift задаётся при создании vdev и не меняется. Поставил 9 (512b) на диск с 4K-сектором — потерял производительность навсегда. Стандарт сегодня — ashift=12.
  5. ARC на сервере с БД — крутить zfs_arc_max (/etc/modprobe.d/zfs.conf: options zfs zfs_arc_max=8589934592 для 8 GiB).
  6. send/receive обрывается → recv state остаётся, надо zfs receive -A для abort.
  7. Перевод pool на новую версию OpenZFS — односторонний. zpool upgrade сделал → на старой версии этот pool уже не импортируешь.

bcachefs

В mainline с ядра 6.7 (2024). Молодая, но амбициозная.

  • CoW, checksums, компрессия, шифрование, многоуровневое хранилище (tiered storage: NVMe + HDD в одном пуле с автоматической миграцией), erasure coding, replicas.
  • Сырая, в проде использовать рано. Конфликты автора (Kent Overstreet) с Линусом — будущее в mainline под вопросом.
  • Фишка: настоящий tiered storage без сторонних инструментов (типа bcache+LVM).

Архитектура: эволюция из bcache, B-tree + CoW

bcachefs выросла из bcache — block-level кэша SSD-перед-HDD, который Kent Overstreet вёл с 2010. К 2015 стало ясно, что инфраструктура bcache (CoW B-tree, журнал, allocator) достаточно мощная, чтобы стать полноценной ФС — так появилась bcachefs. В mainline принята с 6.7 (январь 2024), статус experimental.

Цель — собрать в одной ФС всё лучшее: надёжность ZFS, фичи Btrfs, скорость ext4/XFS. И tiered storage из bcache как killer feature.

Внутри — CoW B-tree (как Btrfs), но дерево одно глобальное (а не лес как у Btrfs), что упрощает целостность и снижает overhead на mount. Журнал отдельный (а не сам B-tree как у ZFS) — для durability fsync без write amplification CoW-коммита.

Multi-device встроено. Каждое устройство имеет target label (foreground, background, promote, metadata). При записи блок попадает на foreground (быстрый NVMe), фоном мигрирует на background (медленный HDD). При чтении промоутится обратно. Это и есть tiered storage — то, что в Linux раньше делали bcache + LVM + ручной хореографией.

Replication и erasure coding — на уровне ФС, не блочного устройства. replicas=2 = «храни 2 копии», как ZFS mirror. erasure_code= на больших write'ах — RAID-5-подобная избыточность с N data + M parity. По заявлениям автора, write hole закрыта (в отличие от Btrfs RAID-5/6); в проде это пока никто массово не проверял.

Snapshots и subvolumes — есть, но реализация моложе чем у Btrfs/ZFS.

Следствия

  • Tiered storage без слоёв. Один формат данных от NVMe до HDD, без перекладывания через bcache/LVM/dm-cache. Это уникально для Linux.
  • Молодость = баги. На 2024–2025 регулярно фиксят корректность, не производительность. Никто из вендоров (RHEL, SUSE, Ubuntu) bcachefs официально не саппортит.
  • Toolchain тонкий. bcachefs-tools есть, но возможностей repair заметно меньше, чем у e2fsck/xfs_repair/btrfs check.

Хорошо

  • Tiered storage из коробки. bcachefs format --label=ssd.ssd1 /dev/nvme0n1 --label=hdd.hdd1 /dev/sda --foreground_target=ssd --background_target=hdd --promote_target=ssd создаёт ФС, где горячие данные сами едут на NVMe, холодные — на HDD, прозрачно для приложения. В одной команде то, на что в bcache+LVM уходит полдня.
  • Erasure coding с надеждой на отсутствие write hole. Если выстрелит — первая нативно-Linux'овая parity-ФС без проблем Btrfs RAID-5/6 и без out-of-tree статуса ZFS.
  • Чистая архитектура. Один B-tree, явный журнал, понятные структуры. Внутренности проще читать, чем Btrfs/ZFS.
  • Per-file/per-directory параметры. Компрессия, checksum-алгоритм, replicas, target можно задать на конкретный файл/подкаталог (xattr), а не только на весь mount.
  • Активная разработка. Фичи добавляются регулярно, фидбек с продакшен-пилотов учитывается.

Плохо

  • Будущее в mainline под вопросом. Конфликт Kent Overstreet с Линусом и другими мейнтейнерами обострился в 2024–2025 (Kent присылал крупные изменения вне merge window и не соглашался с процессом). Обсуждалось удаление из ядра. На 2026 формально ещё в дереве, но статус нестабильный. Если выпилят — придётся жить на out-of-tree модуле, а это уже ZFS-уровень головной боли без enterprise-поддержки.
  • Сырой repair. bcachefs fsck умеет основные сценарии, но на углах ловит баги; единый advice от мейнтейнеров — «делайте бэкапы», а не «чините». Нормально для experimental, но в проде неприемлемо.
  • Нет официальной поддержки от дистрибутивов. RHEL — нет и не планируется. Ubuntu — есть пакет bcachefs-tools, но без commercial support. SUSE — экспериментально.
  • Производительность ещё не настроена. На синтетике bcachefs местами сравним с XFS/ext4, местами — заметно медленнее. Авторские бенчмарки красивые, независимые — разброс.
  • Документация ниже среднего. Большая часть знаний в mailing list, commit messages, и личных постах Kent'а.
  • Совместимость on-disk формата ломалась несколько раз за 2023–2025. Документировано (experimental), но при апгрейде ядра — readme + tools нужно читать.

Грабли

  1. Не ставить на root, не ставить на критичные данные. До stable-статуса в апстриме — это playground.
  2. Бэкап на ext4/XFS + restore — план B по умолчанию.
  3. Версия bcachefs-tools должна соответствовать версии ядра. Стащил tools поновее — на старом ядре mount может отказать с unknown features.
  4. На multi-device пуле потеря «фонового» (HDD) устройства = потеря холодных данных, если replicas=1. По умолчанию replicas=1. Сюрприз для тех, кто ждал ZFS-семантики.
  5. Compression-эвристики моложе Btrfs/ZFS — на mixed-content томах иногда жмёт уже сжатое.

Когда брать

  • Домашний NAS с NVMe-кэшем и HDD-массивом, и не страшно потерять данные. Лучшее, что есть в Linux для этого сценария.
  • Эксперименты, разработка, тесты — feedback автору всегда полезен.
  • Под прод — не сейчас. Минимум — дождаться, пока статус сменится с experimental и появится хотя бы один дистрибутив с коммерческим саппортом.

Сводная таблица

Требование ext4 XFS Btrfs ZFS mdraid+LVM+XFS
Resize ↑ online online online autoexpand online
Resize ↓ offline никогда online только через destroy для ext4 LV
Добавить диск нужен LVM/RAID снизу нужен LVM/RAID снизу btrfs device add zpool add mdadm --add
RAID нативно нет нет только 0/1/10 (5/6 broken) RAID-Z1/2/3, mirrors всё через mdraid
Бэкап БД (Postgres и др.) только внешние тулзы reflinks + pgBackRest нужен +C, теряет фичи snapshots/send thin snapshots + pgBackRest
Скорость PG/Kafka/MinIO хорошо отлично (офиц. реком.) плохо: фрагментация требует тюнинга отлично
Snapshots нет нет (только reflinks) native native через LVM thin
Checksums данных нет нет да да нет
Компрессия нет нет zstd lz4/zstd нет
Mainline kernel да да да нет, DKMS да
RAM требования низкие низкие средние высокие (≥8 GB) низкие
MinIO supported warn официально нет нет да
Kafka рекомендация ок официально (Confluent) нет warn да
Postgres рекомендация ок официально (EDB/AWS) нет без +C warn, с тюнингом да
Сложность setup низкая низкая средняя средняя средняя
Сложность восстановления e2fsck xfs_repair часто = restore from backup ZFS-специфика стандартные тулзы

Главное правило: ставь то, что умеешь восстанавливать. Для root — ext4. Для БД и Kafka — XFS поверх LVM. Для NAS — ZFS. Для домашнего файлопомойничного NAS с NVMe-кэшем — bcachefs, если не жалко. Btrfs — только если CoW-фичи реально нужны и nodatacow на горячих файлах не пугает.