Зачем btrfs
Появилась в 2009 как ответ на ZFS. Дала Linux'у:
- Copy-on-write (COW) - запись не правит блок, пишет в новое место и обновляет указатель
- Subvolume - именованный поддиректорий, который можно отдельно монтировать, снапшотить, отправлять
- Снапшоты за O(1) - дешёвая копия subvolume через хитрый COW
- Чексуммы данных + метаданных - видим bit rot до того как он испортит файл
- Нативный RAID 0/1/10 - без mdraid сверху
- Send/receive - инкрементальная репликация
Default на openSUSE Tumbleweed, Fedora Workstation 33+. На прод-серверах встречается реже из-за исторической нестабильности RAID 5/6 и COW-фрагментации.
Copy-on-write - суть
Когда меняется блок:
- Не-COW (ext4, xfs): пишем в тот же блок
- COW (btrfs, ZFS): пишем в новый блок, обновляем указатель в дереве
Плюсы:
- Снапшот за O(1): просто новое имя, ссылающееся на те же блоки
- Crash-safe без журнала: всегда есть консистентный момент
- Чексуммы автоматически проверяются при чтении
Минусы:
- Фрагментация - частые правки одного файла раскидывают его по диску. Особенно бьёт БД (page-level правки) и VM-images.
- Места не предсказать: один файл занимает места больше при смене блока, потому что старая версия может быть удержана снапшотом.
Решение для БД/VM - chattr +C (отключить COW для конкретных файлов):
mkdir /data/postgres
chattr +C /data/postgres # для всех новых файлов внутри
cp -a /old/postgres/* /data/postgres/
chattr +C работает только при создании файла; на существующие
не накатится без перекопирования.
Subvolume
Subvolume - это отдельное дерево внутри одной ФС. Не раздел в партициях, а логическая единица btrfs:
mkfs.btrfs /dev/sdb1
mount /dev/sdb1 /mnt
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@var
btrfs subvolume list /mnt
Преимущества:
- Можно монтировать subvolume отдельно (
mount -o subvol=@home) - Свои квоты, свои снапшоты
- Изолированные ENOSPC-границы (опционально, через quotas)
Распространённый layout:
/mnt/ ← top-level
├─ @ ← root /
├─ @home ← /home
├─ @var ← /var
└─ @snapshots ← /.snapshots
В fstab:
UUID=... / btrfs defaults,subvol=@,compress=zstd:1 0 0
UUID=... /home btrfs defaults,subvol=@home,compress=zstd:1 0 0
Снапшоты
# Снапшот subvolume
btrfs subvolume snapshot /mnt/@home /mnt/@snapshots/home-$(date +%F)
# Read-only снапшот (для бэкапов через send)
btrfs subvolume snapshot -r /mnt/@home /mnt/@snapshots/home-ro
# Откат: переименовать
btrfs subvolume delete /mnt/@home_broken
btrfs subvolume snapshot /mnt/@snapshots/home-2026-05-01 /mnt/@home
Снапшот мгновенный, занимает 0 места изначально. По мере правок оригинал и снапшот расходятся - и место расходуется на различие.
Send / receive
Инкрементальная репликация на другой btrfs:
# Полный send первого снапшота
btrfs send /mnt/@snapshots/home-2026-05-01 | ssh remote 'btrfs receive /backup/'
# Инкрементальный
btrfs send -p /mnt/@snapshots/home-2026-05-01 /mnt/@snapshots/home-2026-05-02 \
| ssh remote 'btrfs receive /backup/'
Шлёт только дельту между снапшотами - бэкапы быстрые и компактные. Это лучшая альтернатива rsync для большого датасета.
RAID
btrfs умеет RAID по блокам, не по дискам:
mkfs.btrfs -d raid1 -m raid1 /dev/sdb /dev/sdc # data + metadata mirror
mkfs.btrfs -d raid10 -m raid1 /dev/sd{b,c,d,e} # data RAID10, meta mirrormkfs.btrfs -d single -m raid1 /dev/sdb /dev/sdc # данные не зеркалят, метаданные да
Уровни:
single- без избыточностиdup- две копии на одном диске (default для metadata на single-disk)raid0- страйп без избыточностиraid1- зеркало (но N-way: 2 копии на N+ дисках, не как mdraid)raid1c3,raid1c4- 3-way и 4-way mirrorraid10- страйп зеркалraid5,raid6- исторически нестабильны, write hole. До 2024 избегали. С новыми ядрами (6.x) ситуация улучшилась, но multi-disk проды всё ещё чаще на mdraid + ext4/xfs.
Добавить/убрать диск online:
btrfs device add /dev/sdd /mnt
btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt
btrfs device remove /dev/sdc /mnt
Чексуммы и scrub
btrfs хранит crc32c (или blake2/sha256/xxhash) на каждый блок. При чтении - проверка. Если нет совпадения и есть RAID - читает с другого диска и чинит на лету.
Превентивная проверка:
btrfs scrub start /mnt
btrfs scrub status /mnt
Прогон по всему диску, проверяет каждый блок. На SAS/NVMe - фоновый, на HDD заметен. Раз в неделю/месяц по cron'у - норма.
Сжатие
... compress=zstd:1 ...
Прозрачное сжатие. Алгоритмы: zlib, lzo, zstd:1..15.
zstd:1 - быстрый, ~30% экономии на типичных текстовых данных.
Уже записанные файлы можно пересжать:
btrfs filesystem defragment -r -czstd /mnt/data
Когда что-то пошло не так
No space leftпри свободных ГБ - btrfs аллоцирует chunks отдельно для data/metadata; metadata кончились.btrfs balance start -musage=50 /mntпересобирает chunks. На full-FS даже balance может не запуститься - удалить хоть что-то сначала.- БД медленная и фрагментируется - не выключили COW.
chattr +Cна директорию ДО создания файлов БД. - Снапшоты съели всё место - удалить старые:
btrfs subvolume delete /mnt/@snapshots/old-*. Полное освобождение - после балансировки. parent transid verify failed- corruption.btrfs check(только diagnostics), для починкиbtrfs check --repair(РИСК!), лучше mount-o ro,recoveryи спасать данные.- RAID 5/6 после crash'а потерял данные - известная проблема write-hole. Используй RAID 1/10 для multi-disk.
- Диск заполнен на 90% и тормозит - btrfs не любит near-full. Держи под 80%.
Когда выбирать btrfs
| Use case | Btrfs? |
|---|---|
| Workstation с автоснапшотами | ✓ - openSUSE/Snapper интеграция |
| NAS с дедупликацией нет | ✗ - бери ZFS |
| NAS с снапшотами и RAID 1/10 | ✓ |
| БД-сервер | ✗ - ext4/xfs + LVM-snapshot |
| VM-host с qcow2 | ✗ или с chattr +C |
| Контейнерный хост | ✓ - native overlayfs или snapshotting |
| Нужен RAID 5/6 в проде | ✗ - mdraid + ext4/xfs |