|
Bog BOS: Файловая система btrfs |
Последние изменения: |
Последнее изменение файла: 2019.04.29
Скопировано с www.bog.pp.ru: 2024.11.23
Файловая система btrfs типа CoW (Copy on Write, новая версия данных записывается в свободное место) была инициирована Oracle под GPL (после покупки Sun Microsystems у Oracle есть ZFS под CDDL). Дано обещание не ломать (обеспечивать совместимость снизу вверх) формат хранения после ядра 2.6.31. Основные цели - устойчивость к сбоям, выявление ошибок на диске и восстановление данных. Максимальный размер файловой системы - 16 EiB, файла - 8 EiB (ограничивается ядром Linux), максимальное количество файлов - 2^64, максимальная длина имени файла - 255 байт. Времена с точностью до наносекунды. Расширенные атрибуты POSIX и ACL.
Основан на 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):
Фоновый процесс поблочного сканирования (только занятые блоки) и исправления ошибок (ядро 3.1).
Проверка структуры (fsck) пока в размонтированнолм состоянии (обещают в фоновом режиме).
Квотирование места, занимаемого подтомом (снимком) - не пользователем или группой пользователей. Иерархия квот.
Поддержка синхронизации с удалённым зеркалом (send, receive).
Обещана дедупликация во время записи, сейчас имеется дедупликация после записи
/sys/fs/btrfs (ядро 3.14).
Пользоваться с осторожностью - падает под большой нагрузкой (до RHEL 6.4 - совсем неживая), вывел из экспплуатации в 2015:
cat /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
Ключи mkfs.btrfs (создаётся мгновенно, до RHEL 7 не проверяет, что место занято):
Опции монтирования (в качестве устройства указать одно из блочных устройств, парные опции с/без no- в ядре 3.14):
Не надо провоцировать запуск fsck в /etc/fstab, поставьте в конце строки "0 0".
Утилита btrfs позволяет манипулировать файловыми системами ("btrfs help --full")
OLD_TRANSID=`btrfs subvolume find-new "$SNAPSHOT_OLD" 9999999` OLD_TRANSID=${OLD_TRANSID#transid marker was } btrfs subvolume find-new "$SNAPSHOT_NEW" $OLD_TRANSID | sed '$d' | cut -f17- -d' ' | sort | uniq
/usr/local/bin/btrfsck --repair --check-data-csum /dev/mapper/good-x136full enabling repair mode Checking filesystem on /dev/mapper/good-x136full UUID: e984c6f1-431d-47cf-9da2-9c4d36335837 checking extents # читая по 7 МБ/сек до 10 ГБ, затем чтение пошло по 70 МБ/сек Fixed 0 roots. checking free space cache cache and super generation don't match, space cache will be invalidated checking fs roots # полчаса без чтения, ЦП - 100%, чтение 7 МБ/сек до 30 ГБ ОП checking csums # чтение 300 ГБ/сек, молча 12 часов checking root refs found 1380129128119 bytes used err is 0 total csum bytes: 13207991564 total tree bytes: 116377309184 total fs tree bytes: 79296180224 total extent tree bytes: 22198173696 btree space waste bytes: 13680619315 file data blocks allocated: 13633639153664 referenced 33725318455296 Btrfs v3.18.1
Сборка и установка утилит btrfs 3.18.1 из исходных пакетов в CentOS 7.0:
install -m755 -d /usr/local/bin install mkfs.btrfs btrfs-debug-tree btrfsck btrfs btrfs-map-logical btrfs-image btrfs-zero-log btrfs-convert btrfs-find-root btrfstune btrfs-show-super /usr/local/bin install fsck.btrfs /usr/local/bin # btrfsck is a link to btrfs in the src tree, make it so for installed file as well ln -f /usr/local/bin/btrfs /usr/local/bin/btrfsck install -m755 -d /usr/local/lib install libbtrfs.so.0.1 libbtrfs.a /usr/local/lib cp -a libbtrfs.so.0 libbtrfs.so /usr/local/lib install -m755 -d /usr/local/include/btrfs install -m644 send-stream.h send-utils.h send.h rbtree.h btrfs-list.h crc32c.h list.h kerncompat.h radix-tree.h extent-cache.h extent_io.h ioctl.h ctree.h btrfsck.h version.h /usr/local/include/btrfs
Btrfs v3.18.1
Сборка утилит btrfs из git:
btrfs-convert - преобразоватие файловой системы ext2/ext3/ext4 в btrfs на месте.
btrfs-debug-tree - вывод дерева метаданных на stdout ("-r" выдаёт список подтомов, снимков и т.д.).
btrfs-find-root - поиск (медленно) и вывод корней деревьев (фильтр по уровню, поколению).
btrfs-image - сделать образ файловой системы с обнулёнными данными (сжать и отправить разработчикам для отладки).
btrfs-map-logical - физический адрес по логическому (для отладки).
btrfs-show-super - вывести информацию из суперблока (метка, поколение, корень, флаги, размеры блоков и т.д.).
btrfstune - поменять некоторые параметры файловой системы, опрометчиво заданные при создании.
btrfs-zero-log - очистить попорченное дерево журналов, если не получается смонтировать файловую систему (актуальность утеряна).
Тестирование btrfs с помощью bonnie++ (настольная машина, 2 диска ST1000528AS):
bonnie++ 1.03 Sequential Output Sequential Input Random -Per Chr- -Block- -Rewrite- -Per Chr- -Block- -Seeks- Machine Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP /sec %CP 20000M 107510 7 52049 6 127602 10 410.9 1 ext4 над md RAID1 20000M 107218 6 51888 6 131864 11 403.7 1 ext4 над md RAID1 без битовой карты 20000M 120283 7 51758 8 125788 11 384.4 1 btrfs -d/m single над md RAID1 20000M 227244 13 83197 11 215481 12 383.0 1 btrfs -d/m raid0 над дисками 20000M 117174 7 46594 6 121916 7 374.8 1 btrfs -d/m raid1 над дисками 20000M 846256 78 222862 33 325088 19 539.8 3 btrfs -d/m raid1 над дисками, compress=lzo,space_cache
Тестирование на резервное копирование и восстановление (на настольный комптьютер с 2 дисками ST1000528AS и сервер Intel SR2625URLX, дисковая полка из 12 дисков ST31000340NS через FC 4Gb, большой корпус данных местного производства)
Чтение полной фаловой системы (noatime,nobarrier,compress-force=zlib,space_cache; дисковая полка MSA 2000g2 с RAID6 из 12 дисков ST32000640NS через FC 4Gb; 16.3TB, 30 миллионов файлов):
Сервер архива должен содержать данные разработчиков за значительный срок с возможностью самостоятельного извлечения файлов по состоянию на произвольный день в прошлом. Данные разработчиков хранятся на файловых серверах с доступом по NFS. Общий объём - 50 ТБ (более 100 миллионов файлов), ежедневные изменения - до 2ТБ.
# обновить прошивку контроллера и CV /opt/MegaRAID/storcli/storcli64 /c0 download file=/tmp/mr2208fw.rom /opt/MegaRAID/storcli/storcli64 /c0 download file=/tmp/TFM_70-25849-04.rom fwtype=2 # параметры контроллера /opt/MegaRAID/storcli/storcli64 /c0 set coercion=0 /opt/MegaRAID/storcli/storcli64 /c0 set patrolread=off /opt/MegaRAID/storcli/storcli64 /c0 set perfmode=1 # настройка smartd для извещения о проблемах с диском и zabbix о проблемах с массивами /opt/MegaRAID/storcli/storcli64 /c0 add vd type=raid6 size=all name=first drives=8:0-17 pdcache=off wb nora direct Strip=64 /opt/MegaRAID/storcli/storcli64 /c0 add vd type=raid6 size=all name=second drives=8:18-23,9:0-11 pdcache=off wb nora direct Strip=64
pvcreate /dev/sdc pvcreate /dev/sdd vgcreate x134all36 /dev/sdc /dev/sdd lvcreate --stripes 2 --stripesize 64K --name full --extents +100%FREE x134all36
Параллельное копирование с зеркала по rsync (ssh), каждый каталог второго уровня - отдельный поток:
mkdir .ssh chmod 700 .ssh vim .ssh/id_rsa # и сконфигурировать на той стороне /root/.ssh/id_rsa.pub chmod 600 .ssh/id_rsa
if [ -z "$SSH_CLIENT" -a -z "$SSH_AUTH_SOCK" ] then eval `ssh-agent` # ssh-add ~/.ssh/id_rsa # лучше добавлять вручную только тогда когда надо fi
#!/bin/bash if [ -z "$1" ] then echo empty exit else DATE=`echo $1|awk -F/ '{print $1}'` DIR=`echo $1|awk -F/ '{print $2 "/" $3}'` rsync -e ssh -vas [--compress --compress-level=1] --whole-file --numeric-ids --ignore-errors --delete зеркало:/time_machine/old/$DATE/$DIR/ /time_machine/current/$DIR/ >> /root/rsync/rsync.$DATE.log 2>&1 fi
#!/bin/bash DATE=$1 ssh зеркало ls -d /time_machine/old/$DATE/*/*|awk -F/ '{print $4 "/" $5 "/" $6}' | xargs --verbose --max-args=1 --max-procs=40 getdir_snapshot.sh 2>&1 | tee -a /root/rsync/rsync.$DATE.log /sbin/btrfs subvolume snapshot /time_machine/current /time_machine/old/$DATE chmod go+rx /time_machine/old/$DATE
mkdir /time_machine/current/... ...
Копирование очередного дня с зеркала по send/receive (вдвое быстрее, данные пересылаются по сети несжатые):
btrfs property set /time_machine/old/20140801 ro true btrfs property set /time_machine/old/20140802 ro true btrfs send -v -p /time_machine/old/20140801 /time_machine/old/20140802|...
Итоги с 1 августа 2014 по 16 января 2017 + current (rsync в режиме --whole-file, иначе btrfs разваливается очень быстро):
Тестирование чтения привычным tarnull_all_common.sh самого старого снимка (20150121) после 2.5 лет эксплуатации архива (с диска читается до 450 МБ/сек, т.е. после декомпрессии ожидается более 1 ГБ/сек; манипуляции с настройкой контроллера и read_ahead_kb не помогают; в начале всплеск в 1.3 GB/s; встроенный readahead насыщает систему хранения?):
Тестирование чтения привычным tarnull_all_common.sh лизкого к текущему состоянию снимка (20170318) после 2.5 лет эксплуатации архива (с диска читается 350 МБ/сек, т.е. после декомпрессии ожидается более 1 ГБ/сек; манипуляции с настройкой контроллера и read_ahead_kb не помогают):
|
Bog BOS: Файловая система btrfs |
Последние изменения: |