copy-on-write B-деревья вместо журнала — снапшоты почти бесплатны, но RAID5/6 всё ещё «не для прода» спустя больше десяти летcopy-on-write B-trees instead of a journal — snapshots are nearly free, but RAID5/6 is still "not for production" over a decade later

Btrfs: структуры на диске и алгоритмы работыBtrfs: on-disk structures and working algorithms

Btrfs не журналирует изменения, как ext4 — вместо этого она никогда не перезаписывает данные на месте: любое изменение блока создаёт новую копию где-то ещё, а старая остаётся нетронутой, пока на неё есть ссылки. Это устраняет целый класс проблем согласованности, которые journaling только смягчает, и делает снапшоты файловой системы операцией на несколько миллисекунд вместо полного копирования. Тот же механизм даёт сквозные чексуммы данных и метаданных — но применить его к RAID5/6 оказалось труднее, чем к обычному тому: проблема write hole в Btrfs официально не решена и сегодня.Btrfs doesn't journal changes like ext4 — instead, it never overwrites data in place: any block modification creates a new copy somewhere else, while the old one stays untouched as long as something still references it. This eliminates an entire class of consistency problems that journaling only mitigates, and turns a filesystem snapshot into a few-millisecond operation instead of a full copy. The same mechanism gives end-to-end data and metadata checksums — but applying it to RAID5/6 turned out harder than to a plain volume: the write hole problem in Btrfs is still officially unresolved today.

Что этоWhat it is

Btrfs (B-tree FS) спроектирована вокруг одной центральной идеи — copy-on-write (CoW) для всего: и данных, и метаданных. Вместо разделения на «место для данных» и «журнал транзакций», как в ext4, вся файловая система (кроме самого суперблока) представлена набором B-деревьев, и любое изменение узла дерева физически пишется в новый блок, а не поверх старого. Из этого одного решения следует почти всё остальное: дешёвые снапшоты (общий CoW между оригиналом и копией), встроенный RAID без отдельного mdadm, и сквозные чексуммы (раз блок всё равно копируется целиком при изменении, посчитать и сохранить его хэш почти бесплатно).Btrfs (B-tree FS) is designed around one central idea — copy-on-write (CoW) for everything, both data and metadata. Instead of splitting into "data area" and "transaction journal" like ext4, the entire filesystem (except the superblock itself) is represented as a set of B-trees, and any change to a tree node is physically written to a new block rather than over the old one. Almost everything else follows from this single decision: cheap snapshots (shared CoW between the original and the copy), built-in RAID with no separate mdadm, and end-to-end checksums (since a block gets copied wholesale on change anyway, computing and storing its hash is nearly free).

параметрparameterext4Btrfs
защита от сбояcrash protectionжурнал метаданных (JBD2)metadata journal (JBD2)copy-on-write — старые данные не перезаписываются, пока новые не подтвержденыcopy-on-write — old data isn't overwritten until the new data is confirmed
чексуммы данныхdata checksumsнет (только metadata_csum для метаданных)no (only metadata_csum for metadata)да, сквозные для данных и метаданныхyes, end-to-end for both data and metadata
снапшотыsnapshotsнет (нужен LVM снизу)no (needs LVM underneath)встроены, почти бесплатны за счёт CoWbuilt in, nearly free thanks to CoW
RAIDнет (нужен mdadm/LVM снизу)no (needs mdadm/LVM underneath)встроен на уровне ФС (0/1/1c3/1c4/10; 5/6 не для прода)built into the filesystem (0/1/1c3/1c4/10; 5/6 not for production)
изменение размераresizingonline только увеличение; уменьшение офлайнonline growth only; shrinking requires offlineonline в обе стороны (grow и shrink)online both ways (grow and shrink)
зрелость / стабильностьmaturity / stabilityмноголетний промышленный стандартa multi-year industry standardстабильна для одиночного тома/RAID1, но с историей нареканий на отдельные фичиstable for single-device/RAID1, but with a history of complaints about specific features

Как это устроено внутриHow it's built internally

Ключевое отличие от ext4 видно уже на уровне одной операции записи. В ext4 изменение файла обновляет existующие блоки на месте (журнал лишь описывает это изменение для восстановления после сбоя); в Btrfs каждое изменение блока — данных или метаданных — создаёт новую физическую копию, а указатели родительских узлов дерева переписываются, чтобы указывать на неё:The key difference from ext4 is visible at the level of a single write. In ext4, modifying a file updates the existing blocks in place (the journal just describes the change for crash recovery); in Btrfs, every block change — data or metadata — creates a new physical copy, and the parent tree nodes' pointers are rewritten to point at it:

до изменения superblock → root parent node block A запись данных во время CoW-записи superblock → root (пока старый) parent node (старый) block A (нетронут) parent' (новый) block A' (новый) старый root/parent/block A остаются валидными и на диске, пока суперблок не переключат на новый root переключение root — одна атомарная операция; если система упадёт раньше — суперблок всё ещё указывает на полностью согласованное старое дерево именно поэтому Btrfs не нужен journal replay при монтировании: на диске никогда не было «наполовину записанного» состояния
CoW распространяется вверх по дереву от изменённого листа до корня: каждый затронутый узел копируется в новое место, а не правится на старом. Последний шаг — переключение указателя на корень в суперблоке — атомарен, поэтому файловая система всегда находится в одном из двух полностью согласованных состояний: «до записи» или «после записи», без промежуточных.CoW propagates up the tree from the modified leaf to the root: every affected node is copied to a new location rather than patched in place. The last step — flipping the root pointer in the superblock — is atomic, so the filesystem is always in one of two fully consistent states: "before the write" or "after the write", with nothing in between.

Btrfs хранит почти всё как набор B-деревьев, а не как жёстко зашитые структуры вроде block group ext4. Работа с реальным диском требует различать логический адрес (используется внутри всех деревьев файловой системы) и физический (реальное смещение байт на конкретном устройстве) — это разделение и делает возможным RAID на уровне самой ФС:Btrfs stores almost everything as a set of B-trees rather than hard-wired structures like ext4's block groups. Working with the real disk requires distinguishing a logical address (used inside all the filesystem's trees) from a physical one (a real byte offset on a specific device) — and this split is exactly what makes RAID possible at the filesystem level itself:

fs tree файлы/каталоги, логич. адреса extent tree занятость + refcount диапазонов логич. адрес chunk tree логич. → физич. (учитывая RAID) device 1 device 2 dev tree обратная карта: физич. → логич. RAID1: одни данные на 2 устройствах сразу
Обычный файл в fs tree адресуется логическим адресом; extent tree знает, кто и сколько раз на этот адрес ссылается (основа снапшотов и дедупликации); chunk tree превращает логический адрес в физическое расположение на конкретном устройстве или нескольких устройствах сразу — именно здесь решается, писать ли данные как RAID1 (зеркало), RAID0 (страйп) или одиночно.An ordinary file in the fs tree is addressed by a logical address; the extent tree knows who references that address and how many times (the basis for snapshots and dedup); the chunk tree turns a logical address into a physical location on one specific device or several devices at once — this is exactly where it's decided whether to write data as RAID1 (mirror), RAID0 (stripe), or single.

Снапшот подраздела (subvolume) — прямое следствие этой же архитектуры, а не отдельная реализованная поверх ФС фича. Создание снапшота — это создание нового корня fs tree, который в момент создания указывает на те же самые узлы, что и оригинал (то есть, буквально, тот же самый extent tree ниже по дереву). Никакого копирования данных не происходит:A subvolume snapshot is a direct consequence of the same architecture, not a separate feature bolted on top of the filesystem. Creating a snapshot means creating a new fs tree root that, at the moment of creation, points at the exact same nodes as the original (literally the same extent tree further down). No data copying happens:

моментmomentчто происходит с блокамиwhat happens to the blocks
btrfs subvolume snapshotсоздаётся новый корень fs tree, указывающий на всё то же дерево — общие данные ни разу не копируются; операция занимает миллисекунды независимо от размера подразделаa new fs tree root is created pointing at the exact same tree — shared data is never copied; the operation takes milliseconds regardless of the subvolume's size
файл читается из снапшотаa file is read from the snapshotчитаются те же физические блоки, что и из оригинала — оба указывают на один и тот же extentthe same physical blocks are read as from the original — both point at the same extent
файл изменяется в оригинале или в снапшотеa file is modified in the original or in the snapshotсрабатывает CoW: изменяемый блок копируется в новое место, только в этом дереве обновляется указатель — второе дерево продолжает видеть старую версию блокаCoW kicks in: the block being changed is copied to a new location, only that tree's pointer is updated — the other tree keeps seeing the old version of the block

Та же самая механика работает при cp --reflink: создаётся новый inode, ссылающийся на существующие extent-ы оригинала, вместо физического копирования данных — с точки зрения пользователя получается «копия файла», созданная почти мгновенно и без расхода места, пока обе версии идентичны.The same mechanics power cp --reflink: a new inode is created referencing the original's existing extents instead of physically copying the data — from the user's point of view, it looks like a "file copy" created almost instantly and using no extra space, as long as both versions stay identical.

Поскольку CoW всё равно копирует блок целиком при любом изменении, добавить к нему контрольную сумму почти ничего не стоит — Btrfs хранит чексумму (по умолчанию CRC32C, доступны более сильные алгоритмы с ядра 5.5) в отдельном checksum tree и проверяет её при каждом чтении:Since CoW copies a block wholesale on any change anyway, adding a checksum to it costs almost nothing — Btrfs stores a checksum (CRC32C by default, stronger algorithms available since kernel 5.5) in a separate checksum tree and verifies it on every read:

Как этим пользуются на практикеHow it's used in practice

командаcommandчто происходитwhat happens
btrfs subvolume create /mnt/@homeсоздаёт независимый подраздел внутри тома — можно монтировать отдельно, снапшотить отдельно от других подразделов (типичная схема: отдельные subvolume для @, @home, @snapshots)creates an independent subvolume inside the volume — can be mounted separately, snapshotted independently of other subvolumes (a common layout: separate subvolumes for @, @home, @snapshots)
btrfs subvolume snapshot /mnt/@ /mnt/@snapshots/pre-updateсоздаёт снапшот за миллисекунды — стандартная практика перед обновлением системы: если что-то сломается, откат — это смена подраздела при загрузке, а не восстановление из бэкапаcreates a snapshot in milliseconds — standard practice before a system update: if something breaks, rollback is switching the boot subvolume, not restoring from a backup
cp --reflink=always src dstсоздаёt лёгкую копию файла, разделяющую физические extent-ы с оригиналом, пока данные не разойдутся — почти мгновенно даже для больших файловcreates a lightweight copy of a file sharing physical extents with the original until the data diverges — nearly instant even for large files
btrfs scrub start /mntзапускает фоновую проверку чексумм всех данных на томе; на избыточных профилях (RAID1/DUP) автоматически чинит найденные несовпадения из второй копииstarts a background checksum verification of all data on the volume; on redundant profiles (RAID1/DUP), automatically repairs found mismatches from the second copy
btrfs filesystem resize +10G /mntувеличивает том на лету без размонтирования; тот же инструмент умеет и уменьшать размер онлайн — операция, которой у ext4 нет вовсеgrows the volume on the fly without unmounting; the same tool can also shrink it online — an operation ext4 doesn't have at all
btrfs device add /dev/sdb /mnt && btrfs balance start /mntдобавляет диск к существующему тому и перераспределяет данные по новому набору устройств — расширение массива без полного пересоздания, недоступное классическому RAID+ФС поверх негоadds a disk to an existing volume and redistributes data across the new set of devices — expanding the array without a full recreation, unavailable to classic RAID+filesystem-on-top

Грабли и мифыGotchas & myths

RAID5/6 в Btrfs официально «не для прода» — больше десяти лет спустяBtrfs RAID5/6 is officially "not for production" — over a decade later

Документация проекта прямо называет реализацию RAID5/6 содержащей «недостатки проектирования и реализации» и рекомендует использовать её только для оценки/тестирования, не в проде. Ключевая нерешённая проблема — классический write hole: при сбое питания посреди записи блока данных и его parity-блока для RAID5/6 они могут разойтись, а сама Btrfs (в отличие от, например, ZFS RAID-Z) не даёт по этому конкретному сценарию 100% гарантии восстановления. Даже официальный man рекомендует держать метаданные на RAID1/RAID1c3, даже если данные лежат на RAID5/6.the project's documentation explicitly describes the RAID5/6 implementation as having "design and implementation deficiencies" and recommends it only for evaluation/testing, not production. The key unresolved issue is the classic write hole: a power failure mid-write of a data block and its parity block for RAID5/6 can leave them out of sync, and Btrfs itself (unlike, say, ZFS RAID-Z) doesn't give a 100% recovery guarantee for this specific scenario. Even the official man page recommends keeping metadata on RAID1/RAID1c3 even when data sits on RAID5/6.

«свободное место» в Btrfs — не то число, которое кажется"free space" in Btrfs isn't the number it looks like

Пространство выделяется chunk tree блоками ~1 ГиБ под данные и отдельно под метаданные, и переиспользование этих chunk-ов происходит не мгновенно — классическая жалоба «df показывает мало места, а реально файлов почти нет» почти всегда означает, что нужен btrfs filesystem usage вместо обычного df, и иногда явный btrfs balance для пересборки полупустых chunk-ов.space is allocated by the chunk tree in ~1 GiB blocks for data and separately for metadata, and reusing those chunks isn't instantaneous — the classic complaint "df shows little free space but there's barely any files" almost always means btrfs filesystem usage is needed instead of plain df, and sometimes an explicit btrfs balance to consolidate half-empty chunks.

снапшот — не бэкап сам по себеa snapshot isn't a backup by itself

Снапшот живёт на том же физическом томе, что и оригинал — он защищает от «случайно удалил файл» или «обновление сломало систему», но не от отказа самого диска. Полноценная защита требует либо избыточного RAID-профиля под снапшотами, либо btrfs send/receive для отправки снапшота на физически другое устройство/машину.a snapshot lives on the same physical volume as the original — it protects against "accidentally deleted a file" or "an update broke the system", but not against the disk itself failing. Real protection requires either a redundant RAID profile underneath the snapshots, or btrfs send/receive to ship the snapshot to a physically separate device/machine.

ТерминыTerms

copy-on-write (CoW)
принцип, при котором изменяемые данные никогда не перезаписываются на месте — вместо этого создаётся новая копия, а старая остаётся валидной, пока на неё есть ссылки; основа снапшотов, чексумм и устойчивости к сбоям в Btrfs.the principle that changed data is never overwritten in place — instead a new copy is created, while the old one stays valid as long as something references it; the basis of Btrfs's snapshots, checksums, and crash resilience.
subvolume
независимое поддерево внутри одного тома Btrfs со своим fs tree — можно монтировать, снапшотить и удалять отдельно от других подразделов того же физического тома.an independent subtree inside one Btrfs volume with its own fs tree — can be mounted, snapshotted, and deleted independently of other subvolumes on the same physical volume.
chunk tree
дерево, переводящее логический адрес (используемый внутри остальных деревьев ФС) в физическое расположение на конкретном устройстве или нескольких сразу — именно здесь реализован RAID на уровне файловой системы.the tree translating a logical address (used inside the rest of the filesystem's trees) into a physical location on a specific device or several at once — this is exactly where RAID is implemented at the filesystem level.
extent tree
дерево, отслеживающее занятость логических диапазонов и количество ссылок на них — основа механизма снапшотов и cp --reflink: разделяемый extent освобождается физически только когда последняя ссылка на него исчезает.the tree tracking logical range occupancy and reference counts — the basis of snapshots and cp --reflink: a shared extent is physically freed only when its last reference disappears.
checksum tree (csum tree)
дерево, хранящее контрольные суммы (CRC32C по умолчанию) для блоков данных и метаданных — проверяется при каждом чтении, обнаруживая тихое повреждение (bit rot) до того, как приложение получит испорченные данные.the tree storing checksums (CRC32C by default) for data and metadata blocks — verified on every read, catching silent corruption (bit rot) before an application receives damaged data.
write hole
классическая проблема RAID5/6: сбой питания между записью блока данных и его parity-блока может оставить их несогласованными без возможности определить, какой из них корректен; в Btrfs остаётся официально нерешённой для RAID5/6.the classic RAID5/6 problem: a power failure between writing a data block and its parity block can leave them inconsistent with no way to tell which one is correct; officially unresolved in Btrfs for RAID5/6.
scrub
фоновая проверка чексумм всех данных и метаданных на томе, а не только тех, что реально запрашиваются приложениями — на избыточных профилях автоматически чинит найденные несовпадения из исправной копии.a background checksum verification of all data and metadata on a volume, not just what applications actually request — on redundant profiles, automatically repairs found mismatches from a good copy.