a look at btrfs
Решил сегодня посмотреть на btrfs
от компании Oracle. В статье описано много плюшек, но я ее начал
читать только сейчас, когда начал писать пост :) Первое, что меня
привлекло в ней - это высокая скорость доступа к данным и относительная
простота внтурненнего устройства. Я только потом узнал, что btrfs
очень эффективно хранит маленькие файлы и старается сжимать данные с
помощью zlib и lzo. Решил я ее испробовать, когда наткнулся на
описание исправленного бага в недавно
вышедшем ядре 2.6.38.
Я держу не только системный каталог ебилдов,
но и еще cvs дерево portage (так называемый gentoo-x86
tree), чтобы вносить в него изменения.
Обновление gentoo-x86 (cvs update) у меня занимало 40 минут,
причем бОльшую часть времени занимает чтение огромного числа файлов: в
каждом каталоге находится подкаталог CVS, а в нем 3 файла:
CVS/EntriesCVS/RootCVS/Repository
Каталогов в gentoo-x86 (не включая подкаталоги CVS):
$ find -type d | grep -v CVS | wc -l
21594
Итого при cvs update нужно прочитать минимум ~60000 файлов с диска.
Самое интересное, что эти 3 файла одинаковы во всех каталогах CVS.
Если бы файловая система поддерживала
дедупликацию, то эти
3 файла прочитались бы с диска 1 раз! (поддержка дедупликации
планируется в btrfs).
btrfs поддерживает копирование-при-записи (CoW), так что я мог
бы вручную заменить все копии этих файлов на один удалением файла
CVS/Root и копированием файла с этого же раздела btrfs из
другого места (для этого нужна утилита cp из coreutils-8.10 или
выше). Это еще предстоит попробовать.
Эксперимент я начал с малого: создал блочное устройство на 2GB и
записал туда gentoo-x86:
$ dd if=/dev/zero of=btrfs.image bs=$((1024 * 1024)) count=2048
$ losetup /dev/loop0 btrfs.image
$ mkfs.btrfs -LBTRFS_TESTIE /dev/loop0
$ mount /dev/loop0 ut/
$ cp -r .../gentoo-x86 ut/
Это заняло больше 30 минут. Думаю, что бОльшаю часть времени тратилась
на чтение файлов со страшно фрагментированной ext4. Пока это дело
копировалось я изучал команды утилиты btrfs. У нее apt (или
git)-подобный интерфейс:
$ btrfs
Usage:
btrfs filesystem show [<uuid>|<label>]
Show the info of a btrfs filesystem. If no <uuid> or <label>
is passed, info of all the btrfs filesystem are shown.
btrfs filesystem df <path>
Show space usage information for a mount point
# много-много еще всего
Я попробовал такие штуки:
$ btrfs filesystem defrag ut/
$ btrfs filesystem balance ut/
Как оказалось, defrag дефрагментирует один файл (или метаданные
каталога), так что придется запускать defrag на все файлы раздела
индивидуально, если нужна полная дефрагментация.
Домашняя страница содержит много
полезной информации.
Дождавшись копирования я решил сменить владельца ut/gentoo-x86 на
себя:
$ chown -R slyfox:users ut/
Segmentation FaultНехорошо. В dmesg светился OOps ядра. Я заселился на IRC
канал #btrfs на freenode. Там Carey Underwood сказал мне, что
это неизвестный баг ядра и я его
зарепортил.
Carey также рассказал, что это отсутствие обработки нехватки места на
диске в ядре. Интересно, что gentoo-x86 весит примерно 170MB
“чистого веса” (без учета внутренней фрагментации) и 848MB на ext4
(с учетом фрагментации) (на самом деле чуть больше, так как не
учитывется место в таблице инодов - это порядка 170000 * 256 = ~44MB).
То есть в btrfs куда-то девался еще 1GB.
Carey пояснил, что в btrfs блоки под данные и метаданные выделяются
очень большие (порядка 1GB), и скорее всего у меня один из этих типов
блоков, а новый выделиться не смог. Это не чувствуется на файловых
системах размером больше 10GB, но на моей игрушке еще как. btrfs
имеет режим, когда метаданные и данные используют одни и те же блоки:
так называемый --mixed.
Он предложил мне попробовать
патч
в btrfs-progs, который позволяет создавать mixed файлухи. Заодно
я решил попробовать lzo компрессию, а не zlib (умолчальную).
$ mkfs.btrfs -LBTRFS_TESTIE --mixed /dev/loop0
$ mount -o compress=lzo image.btrfs ut/
После этого я без проблем залил туда:
gentoo-x86(177MB“чистых”)/usr/portage(199MB“чистых”)- исходник
linux-2.6.36-gentoo-r5(380MB“чистых”) - исходник и промежуточные бинарники
linux-2.6.38(1300MB“чистых”)
Это чуть-чуть больше 2GB. df и btrfs fi df ut/ говорили, что
свободно еще 300MB.
После этого я успешно сменил владельца. Обновление gentoo-x86 с
cvs заняло 16 минут. Раза в три быстрее, чем на фрагментированной
ext4.
Сконвертировал свой 4GB раздел с 300000 файлов на винчестере чтобы
попробовать btrfs на реальном железе:
$ df -h
Файловая система Разм Исп Дост Исп% смонтирована на
/dev/sda10 4,5G 752M 3,7G 17% /mnt/portage # уже btrfs
/dev/loop1 4,2G 2,1G 1,9G 52% /mnt/ut # образ ext4 (создан dd if=/dev/sda10 of=...)
Раздел btrfs больше на 300MB за счет того, что btrfs не создает
таблицы инодов, а хранит иноды как и данные в выделяемых блоках. При
создании ext4 я зарезервировал таблицу на 1.1 млн инодов. Каждый
элемент “весит” 256 байт. Это и есть наши 300MB (gentoo-x86 меньше
на btrfs).
Очень рекомендую почитать их wiki. там есть такие штуки, как создание именованных слепков файловой системы. Их можно очень прикольно использовать как бэкапы или как отдельные файловые системы.