Основан на B-деревьях, адаптированных к CoW и снимкам, которые используются для хранения объектов всех типов. Идентификатор объекта — 64 бита, ключ — 136 бит (идентификатор, тип — 8 бит, дополнительные данные — 64 бита). Корневое дерево (идентификатор 1) указывает на корни всех остальных деревьев (идентификаторы менее 256): дерево файловой системы (идентификатор 5) указывает на каждый подтом (идентификаторы от 256), дерево журналов (для ускорения fsync), дерево экстентов, дерево контрольных сумм, дерево устройств (отображение физических адресов в логические), дерево кусков (chunk, отображение логических адресов в физические). Для каждого файла (каталога) хранится inode (ACL и расширенные атрибуты хранятся отдельно). Файловая система, устройства и куски имеют уникальные UUID. Системные данные (корневое дерево, дерево устройств, дерево кусков, дерево экстентов) всегда дублируются. Суперблок содержит физические адреса кусков, содержащих системные данные, хранятся 4 копии суперблока со смещениями 64KiB, 64MiB, 256GiB, 1PiB (при изменениях записывается номер поколения).CoW — новые и изменённые данные записываются в свободное место, не затирая старых данных. Каждые 30 секунд (commit) автоматически формируется новый корень файловой системы в качестве точки отката при сбоях или ошибках, так что потеря данных не должна превышать 30 секунд (см. nobarrier ниже). При этом текущий номер поколения (generation) увеличивается на 1. CoW обеспечивает журналирование данных (а не только метаданных) без удвоения объёма записи (точнее говоря атомарность транзакций по изменению данных). Может быть отключено (рекомендуется для БД и образов виртуальных дисков — иначе они фрагментируются на миллионы кусочков) при монтировании (nodatacow) или пофайлово («chattr +C имя-файла»).btrfs может быть создана над несколькими блочными устройствами с отдельным заданием типа распределения метаданных и данных: single (большие куски (chunk) файла на одном устройстве, использовать в случае устройств разного размера), raid0 (экстенты распределяются между устройствами), raid1 (экстенты копируются на 2 устройства; если устройство только одно, то на нём создаются 2 копии — DUP), raid10 (сначала заполняется первое устройство), raid5 и raid6 (с ядра 3.9, недоделано в 3.19); по умолчанию, метаданные копируются на 2 устройства (raid1), данные распределяются между устройстваи (raid0). Копий делается не более 2. Копирование и распределение делается на уровне больших кусков (chunk), не файлов и не экстентов, остальные программы видят только одну логическую копию. Блочные устройства можно добавлять и удалять без размонтирования (расширение btrfs из 10 дисков ST1000528AS в raid10 до 12 raid10, FC 4Gb в режиме ptp («badblocks -n» даёт 4.4 Gbps в обе стороны против 4 Gbps в режиме кольца), занято 1ТБ — 2 часа; удаление 1 диска, освободилась сразу пара — 6 часов), имеется возможность преобразования типа RAID и балансировки используемого места. Маленькие файлы хранятся среди метаданных (в листьях, по умолчанию 8192 байта). Обещается выделенное устройство для метаданных.Свободное место выделяется для данных и метаданных большими кусками (chunk) из общего пула. Размер свободного места в btrfs — сложный вопрос: из пула свободного места при необходимости выделяются сегменты дисковых секторов (все указатели на экстенты работают с сегментными адресами вместо физических дисковых, что позволяет эффективно перемещать сегменты между дисками) для метаданных (по 256MB) и для данных (по 1GB) с учётом уровня RAID. Команда du показывает размер файла до сжатия без учёта метаданных (снимки учитываются дважды); команда df показывает общее доступное место и занятое место с учётом метаданных, свободное место для этой точки монтирования без учёта сжатия и уровня RAID; команда «btrfs filesystem df точка-монтирования» показывает с учётом уровня RAID выделенное место и использованное в выделенном для данных и метаданных и системы; команда «btrfs filesystem show устройство» показывает общее занятое место, имеющееся и занятое место на каждом блочном устройстве; команда «btrfs filesystem usage точка-монтирования» показывает более подробную информацию.Команда cp имеет ключ «—reflink[=always]», который позволяет копировать файлы без увеличения используемого дискового пространства до изменения копии.Имеется утилита дефрагментирования в фоновом режиме (ядро 3.0). Дефрагментирование файловой системы со снимками и reflink может умножить занятое место (до 3.9).Нет подсчёта количества файлов (не работает «df -i») и резервирования места под inode.Хранение данных экстентами (грануляция по умолчанию 4КиБ, максимальный размер — 128 КиБ).Встроенная возможность делать снимки (слепки, snapshot), в режиме только для чтения (используйте noatime!) и без ограничений (альтернативная версия), до ? снимков. Режим может быть изменён «на ходу». Снимки не замедляют работу. Также имеются подтома (поддеревья) с возможностью их отдельного монтирования. Тома (снимки) образуют иерархию. Подтом или снимок тома (или подтома) выглядит как обычный каталог в томе верхнего уровня (нельзя удалить пока не удалишь подтом или снимок). Можно объявить корень подтома или снимка точкой монтирования по умолчанию. При монтировании можно указать явно корень подтома или снимка корнем монтируемой файловой системы. Перемещение с одного подтома на другой — это реальное перемещение с диска на диск, но пространство выделяется из общего пула (chunk). Снимки разделяют используемое место для одинаковых файлов с исходным томом и другими его снимками. Для свободной работы со снимками рекомендуется не иметь на верхнем уровне ничего, кроме каталогов подтомов и снимков, и монтировать подтом, а не корень. Это позволит при необходимости смонтировать вместо подтома снимок, а том удалить.Создание, хранение и проверка контрольных сумм для данных (отключаемо, для экстента и блока) и метаданных (crc32c, зарезервировано 256 бит для метаданных и 4КиБ для данных). Правильное значение может браться из второй копии; неправильное значение исправляется, начиная с версии ?, ранее можно было лишь скопировать и удалить файл.Сжатие данных с помощью алгоритмов lzo и zlib (level 3), грануляция поэкстентная (ключи монтирования или «chattr +c» перед записью), с учётом сжимаемости и без. Обещаны snappy и LZ4. Отключается для прямого ввода/вывода (DirectIO, DIO) и NOCOW. Сжатие производится не постранично(4 КиБ), целым экстентом (128 КиБ), чтобы прочитать байт необходимо декомпрессировать весь экстент, а чтобы поменять байт в середине экстента, его надо переписать целиком. zlib в режиме потока с общим словарём на экстент, lzo сжимает каждую страницу (?) отдельно. Тестирование уровня сжатия на всём корпусе данных (16.2 TB):
btrfs zlib-force — 2.69gzip -1 — 2.81gzip -9 — 2.92xz -1 — 3.35xz —lzma2=preset=9,dict=200MiB,nice=273 — 3.97
Фоновый процесс поблочного сканирования (только занятые блоки) и исправления ошибок (ядро 3.1).Проверка структуры (fsck) пока в размонтированнолм состоянии (обещают в фоновом режиме).Квотирование места, занимаемого подтомом (снимком) — не пользователем или группой пользователей. Иерархия квот.Поддержка синхронизации с удалённым зеркалом (send, receive).Обещана дедупликация во время записи, сейчас имеется дедупликация после записи
duperemove: поэкстентно, ядро 3.13 (btrfs-extent-same ioctl), попробовал в RHEL 7.0: не знаю экономится ли место, но время модификации файлов покорёжено несмотря на режим «только чтение», как сочетать со снимками непонятно, собрал немного статистикиbedup: пофайлово, ядро 3.3 или 3.6 для дедупликации между томами, python 2.7 и «ещё одна» система пакетирования — не стал пробовать
/sys/fs/btrfs (ядро 3.14).Пользоваться с осторожностью — падает под большой нагрузкой (до RHEL 6.4 — совсем неживая), вывел из экспплуатации в 2015:
До ядра 3.4 при обнаружении малейшей ошибки ядро уходило в kernel panic, теперь файловая система перемонтируется в режим только чтения.Основной проблемой является необоснованное сообщение о нехватке места («__btrfs_free_extent … No space left») и аварийном завершении транзакции, при этом иногда следующий файл спокойно записывается, а иногда файловая система переводится в read-only; подобрал параметры для уменьшения вероятности явления — сборка с «skinny-metadata,^extref» и монтирование с «noatime,nodiratime,compress-force=zlib,clear_cache,nospace_cache,enospc_debug,nossd,flushoncommit,commit=15» (или наоборот 60?); не помогает при интенсивной записи во время перестроения массива или выполнении scrub (CentOS 7.2)btrfsck фактически является заглушкой (до утилит 3.18 ещё и вредной).Проблемы с multipath. btrfs путает блочные устройства с их составными частями (multipath, LVM).Проблемы с bcache.Проблемы с монтированием по метке (рекомендуют «mknod /dev/btrfs-control c 10 234; btrfs device scan» в initrd).Не может хранить swap файлы (даже с nodatacow).При обычном завершении буфера на iSCSI не успели сброситься до остановки сети (CentOS65).При удалении устройства (использовал remove-single-device) журнал заполняется сообщениями о неверныхконтрольных суммах (на каждый прочитанный экстент файла?), затем кто-то продолжает обращаться к несуществующему устройству до размонтирования. При возвращении устройства (add-single-device) оно получает новую букву, показывается в btrfs fi show, но не участвует в работе, btrfs fi sync ничего не делает, btrfs fi balance также не задействует его.mkfs.btrfs не проверяет перед созданием, что на разделе что-то уже есть (в новых версиях проверяет наличие btrfs).Лечение raid1 также в светлом будущем, сейчас надо вывести диск из эксплуатации, починить (заменить) диск, добавить новый (чиненный) диск в файловую систему.Временами (CentOS6) btrfs переход в однопоточный режим (особенно заметно, если монтировать с ключом thread_pool), после чего скорость ограничивается возможностями одного ядра по сжатию или декомпрессии, для возвращения в нормальный режим требуется размонтировать файловую систему и выгрузить модуль btrfs.Нельзя создавать снапшоты на уже существующий каталог (CentOS6), т.е. создаёт, но внутри каталога, а система падает при удалении.Обнаружились файлы различного содержания с одинаковыми inode (результат создания снимков). В частности, гарантированно создаются при попытке «rsync —inplace». При этом сервер временами перезагружается с сообщением «kernel BUG at fs/btrfs/ctree.c:2774» (CentOS 65). При экспорте такой файловой системы по NFS получается несколько разных файлов с одинаковыми fsid/inode.Куда-то пропал (CentOS64) /dev/btrfs-control («mknod /dev/btrfs-control c 10 234»)забывает блокировку? при обращении к файлам программа зависает в ожидании в/в, но никакого в/в к устройству нет
mount -o remount во время rsynccat /proc/27619/stack[] call_rwsem_down_write_failed+0x13/0x20[] do_mount+0x2fc/0xa40[] SyS_mount+0x96/0xf0[] system_call_fastpath+0x16/0x1b[] 0xffffffffffffffff
cat /proc/18025/stack[] btrfs_async_run_delayed_refs+0x11f/0x150 [btrfs][] __btrfs_end_transaction+0x1ff/0x380 [btrfs][] btrfs_end_transaction+0x10/0x20 [btrfs][] btrfs_unlink+0x6f/0xa0 [btrfs][] vfs_unlink+0xe1/0x150[] do_unlinkat+0x26e/0x2b0[] SyS_unlink+0x16/0x20[] system_call_fastpath+0x16/0x1b
[] 0xffffffffffffffff