BTRFS и свободное место

Я нахожу BTRFS довольной интересным видом ФС. Но одна из проблем, которая прямо преследует новичков в BTRFS – сложность определения свободного пространства в разделе. В простейшем случае можно воспользоваться df, как и для других ФС.

$ df -h /home/

Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme3n1p1  7,2T  6,9T  331G  96% /home

Кажется, что всё должно быть просто и у нас есть 331G свободного места. Но если спросить человека, который наработал опыт с BTRFS, он вам однозначно скажет, что не ему недостаточно вывода df для определения, есть ли здесь свободное место. Нюанс в том, как именно BTRFS распределяет свободное место и как это увидеть.

Где метрики?

У BTRFS есть команда filesystem usage для получения метрик по ФС. Флажок -T выведет данные в красивой табличной форме, удобной для чтения. Попробуем.

Пример вывода btrfs filesystem usage

Да, тут данных значительно больше. Не пугайтесь, сейчас всё разберём по-порядку.

Как считается Free (estimated)

Первая метрика – Device size, общий объём раздела. Device size состоит из Device allocated (выделенное место) и Device unallocated (не выделенное). Device unallocated – гарантированно свободное на данный момент место.

По мере заполнения раздела, BTRFS будет выделять место из Device unallocated чанками (блоками данных). Чанки делятся по видам содержимого: для данных Data, метаданных Metadata и общесистемных блоков с информацией System. Детальную информацию по выделенной (и даже не выделенной) памяти видно в таблице снизу. Строчка Total подскажет общий объём выделенного места в зависимости от типа.

Выделение чанка не значит, что он сразу будет полностью заполнен. Например, если выделен чанк на 1G для данных и туда был записан только один файл на 4K, то там будет ещё много свободного места. Если же чанк освободится полностью, то он будет де-аллоцирован, а его объём будет возвращён в пул Device unallocated. Строчка Used в таблице подскажет объём занятого пространства по типам.

Если взять чанки всех 3-х типов и сложить, сколько места там занято, то получим общее значение Used из списка сверху. При ручном сложении нужно особо уделять внимание профилям. У меня Metadata и System имеют профиль RAID1. Объём данных там нужно умножать на 2. Если профиль single, то просто складываем.

И если теперь из общего Device size вычесть сумму Used, то выведем общее значение Free (estimated). Именно поэтому эта метрика имеет estimated. Это не точная цифра, а лишь примерная. На практике нужно понимать, что значение Free (estimated) касается Data, а не Metadata. Это вводит в заблуждение.

Другими словами, эта метрика про заполнение чистыми данными, а не про увеличение метаданных. Если в разделе не останется Device unallocated, а нужно будет выделить новый чанк для Metadata, то BTRFS просто вернёт no space left.

Фрагментация и балансировка

Особенно эта проблема чувствуется при фрагментации данных, когда большое количество чанков типа DATA заполнено не полностью и поэтому не может быть деаллоцировано. Степень такой фрагментации легко понять по большой (на порядок) разнице между значением Free (estimated) и значением Device unallocated.

Пример на скриншоте выше явно относится к этому случаю. У меня 330G в Free, но всего 25G в Unallocated. Есть небольшой трюк для перепаковки данных в чанках.

$ sudo btrfs balance start -dusage=10 /home/

Done, had to relocate 9 out of 7275 chunks

После выполнения этой операции, данные из чанков, заполненных меньше, чем на 10% (-dusage=10) были перенесены в другие чанки, где ещё есть свободное место. В результате 9 чанков (9G) было очищено и деаллоцировано, а значение метрики Device unallocated, по настоящему свободного места, увеличилось до 34G.

Ну, а на этом на сегодня всё :)

Если Вы хотите обсудить содержание заметки, задать вопросы или предложить изменения, то со мной можно связаться в Telegram