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

В начале XXI века современной файловой системе уже недостаточно всего лишь быстро работать с файлами и защищать их от повреждений. ZFS показала нам всю мощь технологии Copy-on-Write (CoW, копирование-при-записи) в задачах сохранения данных. Для Linux была создана Btrfs — новая стандартная ФС, построенная на технологии CoW. Судя по тому, что Apple активно доделывает свою APFS, которая также использует CoW, набор возможностей ZFS/Btrfs действительно даёт новый уровень комфорта для пользователя. Чтобы ощутить его, достаточно попробовать Btrfs самим.

Цикл статей о файловых системах Linux:


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

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

  3. Файловые системы Linux. Tmpfs и Zram.

Немного теории для понимания.

Вы создаёте файл, внутри которого — строчка «Девочка Таня у клетки ходила». Сохраняете его на обычную ФС, например, на Ext4 или NTFS. Теперь, если вы откроете файл и добавите в него вторую строчку «Снова не надо кормить крокодила», файловая система при сохранении полностью перезапишет прежнюю версию файла. То есть, той версии файла, где в нём только одна строка, больше не существует.

Теперь проделаем то же самое на Btrfs. Создание файла с одной строкой проходит так же, но когда вы добавляете в файл вторую строку и сохраняете, проявляется то самое копирование-при-записи. Прежняя версия файла не перезаписывается, он остаётся нетронутой, а строка «Снова не надо кормить крокодила» дописывается в свободное место ФС.

Когда вы хотите прочитать этот файл, вы видите только последнюю версию, но с помощью утилиты btrfs можно вернуть его к прежним состояниям. Таким образом Btrfs может сохранять историю изменений каждого файла — надобность в журналировании отпадает, Btrfs просто периодически запоминает состояние ФС, и при малейшей ошибке откатывается к прежней версии.

Использование Btrfs в Ubuntu.

Установщик Ubuntu давно поддерживает Btrfs, так что никаких проблем с этим нет:

Btrfs оперирует томами или subvolumes — это как бы разделы внутри файловой системы. «Как бы» — потому что тома больше похожи на каталоги, чем на разделы. Но такой особый каталог можно монтировать как раздел. Установщик Ubuntu создаёт отдельные тома для системы и для домашнего каталога:

Так делается потому, что намного быстрее и легче сохранить состояние целого тома, чем состояние каждого из тысяч файлов в этом томе. Вторая команда показывает, что на Btrfs созданы тома @ и @home, но увидеть их в файловом менеджере не получится. Нужно сначала примонтировать корень Btrfs (не путать с корнем системы):

Что можно делать с томами Btrfs.

Экономия места на накопителе.

Для любого тома можно включить прозрачное сжатие по одному из двух алгоритмов: zlib и lzo. Первый лучше сжимает, зато второй на порядок быстрее работает. Для системы обычно используют lzo, а zlib имеет смысл на больших объёмах, которые редко читаются. Включается сжатие опцией монтирования compress=lzo в файле /etc/fstab:

После перезагрузки сжатие будет активировано. Обратите внимание, как монтируется том в указанный каталог — через опцию subvol=нужный_том.

Страховка от неудачных обновлений.

Перед каждым апдейтом системы я делаю снапшот системного тома. Вот так это может выглядеть в Ubuntu:

Так же можно сохранять и том с домашним каталогом, и вообще любой том. Снапшот Btrfs по умолчанию открыт для записи, но можно создать снапшот только для чтения:
sudo btrfs subvolume snapshot -r исходный_том снапшот

Представьте, что после обновления ваша система работает с ошибками или вообще не загружается. Тогда вам нужно будет просто указать в /etc/fstab последний снапшот в качестве системного тома через опцию subvol=нужный_том. Это можно сделать с помощью LiveCD.

Одна ФС на сколько угодно накопителей.

Для виртуальной машины с Ubuntu я создал 1 виртуальный накопитель. Представим, что на нём закончилось место. В таком случае я могу добавить ещё один виртуальный накопитель в настройках Virtualbox, а потом добавить его и к Btrfs:

Как видите, Btrfs автоматически применила модель RAID1 — отзеркалировала данные на добавленный накопитель, но уровни RAID можно менять. То же самое можно делать и на реальной машине — добавлять и удалять накопители без необходимости переразбивать их и форматировать заново.

Использование Btrfs на SSD.

Как было сказано выше, технология CoW приводит к высокой фрагментации файлов — все изменения в них записываются кусочками в разные места ФС. Именно поэтому Btrfs (а также ZFS) рекомендуется использовать на SSD, на которых фрагментация совершенно не ощущается.

Btrfs — достаточно современная и продвинутая файловая система, она поддерживает SSD, что называется, «из коробки». В журнале ядра можно увидеть такие строки:

По последней строчке видно, что Btrfs сама определила, что находится на SSD, и автоматически включила режим поддержки твердотельных накопителей. Этот режим также можно включить одноимённой опцией монтирования. Благодаря этому режиму Btrfs показывает высокую скорость на многопоточных операциях.

Но следует иметь в виду, что SSD-режим не включает в себя поддержку TRIM! Поэтому его нужно либо включать опцией монтирования discard, либо же регулярно запускать программу fstrim. В Ubuntu есть отдельный юнит systemd для периодической отработки этой программы, активировать его можно такой командой:
sudo systemctl enable fstrim.timer

Предотвращение деградации скорости.

У Btrfs есть одна неприятная архитектурная особенность: она упаковывает мелкие файлы прямо в дерево метаданных. Дерево метаданных это что-то вроде содержания в книге или поисковой системы в Интернете — в общем, очень важная вещь.

По умолчанию в дерево сохраняются файлы размером до 4 Кб, и вот здесь таится опасность. Из-за того, что размер файла заранее неизвестен, а диапазон размеров широк, дерево метаданных Btrfs сильно разрастается, что негативно отражается на скорости работы ФС.

Чтобы избежать этого, можно сильно ограничить максимальный размер файла, который будет упакован в дерево. Делается это опцией монтирования max_inline с указанием размера файла в байтах — конечно, в файле /etc/fstab:
Теперь в дерево будут сохраняться только файлы размером до 256 байтов. Можно вообще отключить упаковку, указав 0 после знака «равно».

Кстати, нелишним будет отключить обновление временных меток при каждом обращении к файлу. Это делается опцией noatime. Это немного прибавляет скорости работы ФС, а на SSD ещё имеет смысл и потому, что сокращает количество записей на него.

Отключение CoW для томов и файлов.

Одно из выгодных отличий Btrfs от ZFS — возможность полностью отключить Copy-on-Write. Это может быть нелишним на HDD, чтобы снизить фрагментацию и повысить скорость. Но даже на SSD большие файлы, которые часто перезаписываются, могут из-за CoW замедлять работу всей файловой системы. К таким файлам можно отнести образы виртуальных машин и базы данных.

Отключить CoW можно на уровне тома, с помощью опции монтирования nodatacow:

Но этот вариант может не сработать из-за запутанной системы зависимостей опций монтирования между томами. В этом случае можно отключить CoW на уровне атрибутов файла, с помощью команды:
chattr -R +C нужный_каталог
Казалось бы, ключ «+C» должен, по логике, включать CoW, но нет, всё наоборот. Чтобы включить CoW, нужно применить ту же команду, но уже с ключом «-C».

Анализ состояния Btrfs.

Часто люди не понимают, как правильно узнавать количество свободного и занятого места на Btrfs. Дело в том, что из-за снапшотов и сжатия обычные утилиты «сходят с ума» и показывают неправильные данные. Поэтому нужно использовать утилиту btrfs:

Её вывод тоже не очень понятен, так что разберём по строкам.

В первой строке пишутся совокупные объёмы выделенного и занятого места. Слово «single» означает, что Btrfs используется на одиночном накопителе. «Total» показывает, сколько места доступно, причём оно может быть намного меньше общего количества места на накопителе. Паниковать не стоит, просто Btrfs выделяет место порциями. Закончится одна порция — будет выделена ещё одна. Ну, а «used» показывает, сколько места на файловой системе реально занято.

Вторая строка отображает, сколько места занято под системный резерв. Нечто подобное есть и в Ext4.

Третья строка интереснее — в ней можно увидеть, сколько занимает то самое дерево метаданных. На скриншоте видно, что под дерево выделено 2 Гб, из которых заняты около 600 Мб. Эти показатели учитываются в первой строке.

Наконец, в четвёртой строчке показана информация о резервной области, но уже относящейся к самой Btrfs. Она нужна для того, чтобы даже на полностью забитой ФС можно было удалять и создавать тома и снапшоты.

Таким образом, чтобы узнать, сколько места реально занято на Btrfs, нужно смотреть на показатель «used» в первой строчке вывода команды:
sudo btrfs filesystem df нужный_путь