Btrfs

Z DCEwiki
Skočit na navigaci Skočit na vyhledávání

Btrfs je linuxový copy-on-write souborový systém (COW), vyvíjený od r. 2007 firmou Oracle pod GNU GPL licencí.

Copy-on-write (COW) znamená, že pokud dvě aplikace pracují se stejným datovým blokem, tak se kopie s pozměněnými daty neuloží hned, ale až ve chvíli kdy se data mají zapsat. Dokud jsou nezměněná, pracují obě aplikace se stejným datovým blokem.

Při ukládání datových bloků se využívá transakcí a průběžných kontrolních součtů. Pro optimalizaci IO operací se při ukládání využívá tzv. algoritmu B-stromu.

Stručný přehled vývoje Btrfs v datech

  • verze 0.13 - již měla podporu pro subvolume a snapshoty
  • verze 0.14 (Duben 2008) - přidala podporu pro použití více zařízení, což umožnilo implementaci raid0, raid1 a raid10
  • verze 0.15 (Květen 2008) - podpora pro zmenšování a zvětšování
  • verze 0.16 (Srpen 2008) - podpora pro ACL, změna formátu indexování
  • verze 0.17 součást jádra 2.6.29-rc1 (Leden 2009) - změněn diskový formát, zavedena komprese
  • verze 0.18 součást jádra 2.6.29-rc2 - opravovala bug verze 0.17, který se vyskytoval při mixování 32 a 64 bitových aplikací
  • verze 0.19 (Červen 2009) součást jádra 2.6.31-rc1 - zrychlení FS
  • 2.6.32 (Prosinec 2009) od verze tohoto jádra nemá Btrfs vlastní verzování, mazání snapshotů a subvolumes a parametr discard pro SSD
  • 2.6.34 (Květen 2010) - zavedení nástroje btrfs
  • 2.6.37 (Leden 2011) - asynchronní snapshoty a mazání subvolumes
  • 2.6.38 (Březen 2011) - podpora LZO komprese
  • 2.6.39 (Květen 2011) komprese per soubor a podpora pro TRIM u SSD disků
  • 3.0 (Červen 2011) - scrub souborového systému, autodefragmentace
  • 3.2 (Leden 2012) - volba recovery, mount subvolumes přes cestu
  • 3.3 (Březen 2012) - podpora pro změnu raid profilů za běhu
  • 3.4 (Květen 2012) - Povolena větší velikost metabloku, zachycení IO chyb a zrychlení při práci s metadaty
  • 3.5 (Červen 2012) - podpora pro statistiky; podpora NFS
  • 3.6 (Září 2012) - qgroups kvóty nastavitelné na subvolume; podpora změn mezi snapshoty; vypnutí volby atime u snapshotů připojených v read-only režimu; podpora klonování souboru napříč subvolume (reflink); mount s vypnutou kompresí (compress=no)
  • 3.7 (Prosinec 2012) - odstraněno omezení na počet hardlinků v jednom adresáři; podpora děravých souborů, použití NOCOW na soubor
  • 3.8 (Únor 2013) - vylepšení mechanismu výměny HW zařízení za běhu; opravy chyb a dílčí úpravy pro zrychlení souborového systému.
  • 3.9 (Duben 2013) - přidaná podpora pro Raid 5/6; přerušitelná operace defrag; změna volání ioctls přes které se zjišťuje či nastavuje návěští souborového systému; zrychlení IO přístupu; defragmentace snapshotovaných dat
  • 3.10 (Červen 2013) - redukce metadat díky využití tzv. oholených extentů (skinny extents); ukecanější výstup do syslogu; automatické vytvoření qgroups při aktivaci kvót; rozšířený formát pro send/recv, který umožňuje zpracovávat souběžně několik zdrojů dat v jednom proudu (multiplexing) a odstraněna mountovací volba subvolrootid
  • 3.11 (Září 2013) - podpora klonování extentů v rámci jednoho souboru; volání ioctl vrací výsledky až po přepočítání aktuálního stavu kvót
  • 3.12 (Listopad 2013) - zlepšení výkonu pro #send/#recieve u velkého počtu subvolume; nová mountovací volba commit, která umožňuje změnit výchozí nastavení intervalu pro ukládání změn z paměti na blokové zařízení; podpora pro dávkovou deduplikaci (přes userspace nástroj btrfs)
  • 3.13 (Leden 2014) - přes FIEMAP jsou exportovány informace o sdílených extentech
  • 3.14 (Březen 2014) -
  • 3.15 (Červen 2014) - pracovní vlákna se přesunula z userspace do jádra; opravy pro #send
  • 3.16 (Srpen 2014) - podpora pro bezpečné dočasné soubory[1]; přepracováno počítání obsazeného místa u qgroup (viz Kvóty); nový filtr limit pro sofistikovanější vyvažování extentů při balancování; ochrana snapshotů vůči změnám během operace #send
  • 3.17 (Říjen 2014) - oprava vleklé chyby, které ovlivňovala počítání volného místa u qgroups po odstranění snapshotu; vylepšení funkcionality pro df, rename, truncate a pro seeding
  • 3.18 (Prosinec 2014) -
  • 3.19 (Únor 2015) - podpora pro scrub a náhradu blokového zařízení v módu raid56
  • 4.0 (Duben 2015) - uložení časového razítka vytvoření souboru
  • 4.1 (Červen 2015) - HAFO ZMĚN
  • 4.2 (Srpen 2015) - HAFO ZMĚN
  • 4.3 (Listopad 2015) - oprava pro rebuild souborového systému v módu raid56, při ztrátě blokového zařízení
  • 4.4 (Leden 2016) - implementace bitmapy pro přehled o fragmentaci a nová volba pro mount fragment (data|metadata|all)
  • 4.5 (Březen 2016) - implementace parametru "dup" pro akci convert při vyvažování extentů
  • 4.6 (Květen 2016) - implementace dalších voleb pro mount: usebackuproot, logreplay, nologreplay, norecovery; nový výchozí limit pro datový blok 2048 (původně to byla velikost stránky paměti – 4096); oprava chyby při překrytí přes overlay
  • 4.7 (Červen 2016) - balancování dup u multi-device; odstraňování blokových zařízení přes jejich id (předtím bylo možné vyhodit zařízení jen tím, že se k němu zadala cesta), přidané další funkcionality pro selftesty
  • 4.8 (Říjen 2016) - alokace místa přes systém tiketů
  • 4.9 (Prosinec 2016) - zlepšení výkonu při detekci sdílených extentů přes FIEMAP
  • 4.10 (Únor 2015) -
  • 4.11 (Březen 2015) - implementována velká sada oprav

Vytvoření Btrfs souborového systému

Naformátování blokové zařízení (v příkladu /dev/mapper/data-sklad ) na souborový systém Btrfs je triviální operací:

Poznámka
stroj:~# mkfs.btrfs -L box /dev/mapper/data-sklad
...
Upozornění Informace, které se při vytvoření souborového systému vypíšou na konzoli, i další výpisy, které jsou uvedeny v následujících příkladech se mohu lišit podle použité verze btrfs-tools!

Btrfs multidevice

Jednou z vlastností, kterými se Btrfs odlišuje od většiny běžných souborových systémů je schopnost pracovat s více než jedním blokovým zařízením. Btrfs tak může plně nahradit linuxový RAID či LVM. Oproti nim má ovšem velkou výhodu, že jako souborový systém pracuje přímo s datovými bloky, takže má (oproti zmíněným technologiím) k dispozici informace o tom, které datové bloky lze zrušit a které ponechat. Softwarový MD raid, nebo raid u LVM, nemá k dispozici informace, podle kterých by mohly určit co patří mezi datové smetí a co mezi validní data.

Extenty v single módu

Je-li souborový sytém Btrfs vytvořen pouze nad jedním blokovým zařízením, tak se všechny datové extenty tvoří pouze v single módu – pokud mu neřekneme jinak. Po přidání dalšího zařízení se tak začne souborový systém Btrfs chovat jako stripovaný RAID 0. Nové extenty se tak rovnoměrně rozkládají mezi obě zařízení. Ovšem pokud dojde k selhání jednoho z nich, budou data na něm uložená nedostupná.

Jednou z velkých výhod Btrfs je, že u něj – na rozdíl od RAID nebo LVM zařízení – nevzniká problém s rozpadlým polem. Pokud nedojde k selhání přímo na úrovni blokového zařízení, umí Btrfs poznat co k němu patří, i přesto, že je původní blokové zařízení připojené jiným způsobem.

Také pokud diskové zařízení vypadne za běhu, začne Btrfs ukládat nově přibývající data na zbylé zařízení a přístup k původním datovým blokům obnoví ihned poté co se zařízení podaří opět připojit do systému.

Extenty v DUP módu

DUP mód používá Btrfs pouze pro systémové a metadatové extenty. Nastavuje ho automaticky, pokud má na blokovém zařízení dostatek místa pro vytvoření jejich kopie.

Je to pojistka pro případ, že by se na blokovém zařízení vyskytla chyba zrovna v oblasti, kde je uložen extent s metadaty.

Extenty v raid módu

Ochranou před selháním jednoho z blokových zařízení je použití některého z raid módů. Díky tomu, že každý extent je sám o sobě nezávislou jednotkou, s vlastní konfigurací, lze nastavit při formátování souborového systému pro každý typ extentů jiný mód. Btrfs dokonce umí mód extentu změnit i dodatečně, během tzv. balancingu.

Můžeme tak mít kupříkladu extenty pro systémové informace a metadata v některém z raid módů ale vlastní data v single módu. V takovém případě se pak při selhání blokového zařízení informace o souborech z chybějícího blokového zařízení neztratí, ale skončí chybou pokus o jejich přečtení.

Z hlediska bezpečnosti je tím pádem výhodnější mít v raid módu i datové extenty. To je ovšem zase mnohem náročnějí na obsazený prostor, protože data potřebná pro rekonstrukci příslušného extentu si rovněž ukousnou své místo na blokových zařízeních.

Ovšem zde se opět projeví výhody Btrfs souborového systému, které má oproti RAID či LVM zařízení. Btrfs totiž počítá metadata potřebná k rekonstrukci datového bloku pouze pro extenty, které se skutečně používají. Nezdržuje se s počítáním kontrolních součtů extentů u kterých nedošlo ke změně, nebo jsou určeny ke smazání. Tím se rapidně zkracuje časový interval potřebný k rekonstrukci dat oproti rekonstrukci dat u RAID či LVM zařízení. Ty totiž nevědí nic o datovém obsahu svých extentů, proto při rekonstrukci dat vždy pracují s celým blokovým zařízením. Navíc se u nich může stát, že při jejich rekonstrukci dojde k obnovení extentu, který obsahuje neplatná data a tím může dojít i k nabourání souborového systému co je nad nimi. V krajním případě se dokonce může stát, že dojde k jeho fatální havárii, pokud nemá souborový systém vnitřní mechanismy, které to jsou schopny včas odhalit a opravit.
Poznámka Takovou špatnou zkušenost jsem několikrát učinil se souborovými systémy ext3 a ext4. Naopak jako poměrně robustní vůči podobnému problému se ukázal reiserfs a btrfs. Pozn. A.K.


Kontrola volného místa

Upozornění Při použití btrfs příkazy df nebo du vůbec nemusí zobrazovat validní hodnoty ze kterých by bylo možné si udělat představu, kolik volného místa nám zbývá. Proto je vždy lepší používat ke kontrole volného místa přímo administrační utilitu btrfs.

Je to dáno tím, že utilita df neví nic o tom, kolik místa zabírají extenty s metadaty, ani kolik místa zabírají datové extenty, které mohou být sdílené mezi soubory či snapshoty. Rovněž při použití příkazu du bychom se nedobrali k serióznímu výsledku, neboť by spočítal vždy plný objem dat v adresáři – bez ohledu na to jestli jsou jeho datové extenty komprimované nebo snad dokonce pouze linkované přes nějaký sdílený extent.

Následující ukázkový příklad názorně demonstruje v čem je rozdíl. Podle df zbývá 200GB volného místa, ale ve skutečnosti může být na blokovém zařízení uloženo dat více i méně – záleží totiž na mnoha fatorech: kolik souborů se uloží, jak budou velké, jaký bude jejich kompresní poměr, jestli nepřibudou snapshoty či subvolume, atd. Jediné co můžeme příkazem df s určitostí zjistit je – kolik místa z celkové kapacity je aktuálně zaplněno daty, a jak velké množství dat bude zhruba možné ještě uložit – toť vše.

Poznámka
stroj:~# df -h /mnt
Souborový systém       Velikost Užito Volno Uži% Připojeno do
/dev/mapper/data-sklad     3,7T  3,4T  200G  95% /mnt
stroj:~# btrfs fi show
Label: 'box'  uuid: 8c25587e-6680-4669-b04a-b34725068564
        Total devices 1 FS bytes used 3.30TB
        devid    1 size 3.64TB used 3.64TB path /dev/dm-0

Btrfs Btrfs v0.19

Jediný způsob, jak získat přehled o skutečném obsazení disku tedy jsou dotazy přímo na připojený souborový systém. Tak lze zjistit kolik místa zabírají samotná data a kolik metadata, i to v jakém se aktuálně nalézají módu. Btrfs používá tři typy extentů:

  • systémové extenty obsahují informace o souborovém systému a příslušných blokových zařízeních
  • metadatové extenty obsahují informace o tom kde jsou uložena vlastní data
  • datové extenty obsahují vlastní data

Z následujícího výpisu tak lze tedy zjistit, že u Btrfs souborového systému namountovaného na přípojný bod /mnt je v módu single 4MB systémových extentů, 8MB metadatových a 3,49TB datových. A v duplikovaném módu 8MB systémových a 74.75GB metadatových extentů.

Poznámka
spike:~# btrfs fi df /mnt
Data: total=3.49TB, used=3.31TB
System, DUP: total=8.00MB, used=428.00KB
System: total=4.00MB, used=0.00
Metadata, DUP: total=74.75GB, used=5.00GB
Metadata: total=8.00MB, used=0.00

Velikost prostoru, který tyto extenty zabírají však nevypovídá nic o tom, kolik je volného místa. V případě, že u některého typu extentů místo pochybí totiž Btrfs operativně uvolní místo, které zabírají neobsazené extenty ve prospěch typu, kterému místo dochází.

Relevantní odpověď na otázku kolik je obsazeného místa tedy dá součet zabraných dat (parametr used).

Poznámka Pro ověření pravdivosti tohoto tvrzení doporučuji porovnat výsledný součet s hodnotou obsazeného místa, jak ji udává příkaz df v předchozím příkladu - obsazeno je zhruba 3.4TB (~ 3,31TB + 5GB + 428 KB zaokrouhleno na desetiny)

Podrobnější přehled o uložených datech v jednotlivých subvolume je možno získat, pokud souborový systém používá kvóty.

Balancing

Balancing je operace, při které se vezme obsah extentu, propasíruje přes alokační mechanismus, který rozhoduje co, kam a jak se má uložit a výsledek zapíše na jiné místo blokových zařízení které jsou součástí souborového systému.

Tato operace je primárně určena pro rovnoměrné rozložení extentů souborového systému přes více fyzických zařízení - odtud také její název, ale také lze jejím prostřednictvím změnit módy extentů. Má ale i jiné postranní efekty, které lze s výhodou využívat:

  • Je-li na zařízení alokováno hodně extentů, které jsou jinak poměrně nevyužité, lze jejich zpřeházením scelit volné místo, neboť během vyvažování dojde k efektivnějšímu uložení dat a metadat.
  • Na souborovém systému, který je nad blokovým zařízením u kterého došlo k chybě při replikaci (např. u RAID-1 kde umřel disk) to donutí souborový systém obnovit ztracenou kopii z metadat na aktuálně aktivním zařízení.
Upozornění Vyvažování nijak nepracuje s tzv. B-stromy, takže nemá žádný vliv na zrychlení přístupu k souborovému systému!

Využití balancingu pro přerovnání extentů

Po namountování blokového zařízení /dev/mapper/data-sklad naformátované příkazem z předchozího ukázkového příkladu na přípojný bod /mnt si můžeme následujícím příkazem zjistit kolik místa - u jinak prázdného souborového systému - extenty zabírají

Poznámka
stroj:~# btrfs fi df /mnt
Data, single: total=8.00MiB, used=64.00KiB
System, DUP: total=8.00MiB, used=16.00KiB
System, single: total=4.00MiB, used=0.00
Metadata, DUP: total=256.00MiB, used=112.00KiB
Metadata, single: total=8.00MiB, used=0.00

Podle toho, jak vypadá výstup příkazu, lze zpětně poznat jakým způsobem byl souborový systém vytvořen. Metadatové a systémové extenty se totiž vytvoří v módu DUP pouze pokud je k dispozici pouze jedno - dostatečně velké - blokové zařízení.

Pokud by blokové zařízení /dev/mapper/data-sklad nebylo dost velké na to, aby mohly být vytvořeny duplikované extenty, tak by vypadal výpis zhruba takto..
Poznámka
stroj:~# btrfs fi df /mnt
System, single: total=4.00MiB, used=4.00KiB
Data+Metadata, single: total=8.00MiB, used=28.00KiB
Všechny extenty by byly v single módu a navíc by se metadata ukládaly společně s daty do mixovaných extentů, které jsou úspornější z hlediska obsazeného místa.


Jak vidno i nově založený souborový systém obsahuje několik typů extentů. Pokud provedeme jeho vybalancování, tak dojde k jejich redukci..

Poznámka
stroj:~# btrfs balance start -sconvert=dup -mconvert=dup -dconvert=single -f /mnt
Done, had to relocate 2 out of 2 chunks
stroj:~# btrfs fi df /mnt
System, DUP: total=32.00MiB, used=16.00KiB
Metadata, DUP: total=128.00MiB, used=112.00KiB
Upozornění Dokud balancovaný souborový systém neobsahoval před balancováním žádná data, tak po vybalancování nebude obsahovat žádný datový extent. To není na závadu, pokud nemají být datové extenty ukládány v raid módu.

Pokud však mají být datové extenty kupř. v módu raid1, je třeba provést vybalancování po zapsání alespoň jednoho datového extentu. Jinak se datové extenty začnou zapisovat v režimu single, přes to, že při balancování byla pro datové extenty nastavena konverze na mód raid1!

Konverze extentů souborového systému do raid módu pomocí balancingu

Pokud se při formátování Btrfs souborového systému použije více než jedno zařízení, budou vytvořeny extenty systémové a metadatové v režimu RAID1 - tzn. nebudou duplikovány v rámci primárního blokového zařízení, ale jejich kopie se budou "zrcadlit" na sekundárním zařízení. Datové extenty se však kopírovat nebudou. Z hlediska fungování pak takový souborový systém bude fungovat jako pole typu RAID 0, ovšem s tím rozdílem, že v případě výpadku jednoho z blokových zařízení sice budou chybět samotná data souborů, ale informace o nich zůstane zachovaná.

Nebude-li v takovém případě systém chybějící data akutně potřebovat, nedojde k jeho zhroucení a bude-li zařízení znovu dostupné budou data zase normálně k dispozici.

Po namountování přes libovolné blokové zařízení které je součástí souborového systému na přípojný bod /mnt vidět výpis podobný tomuto..

Poznámka
stroj:~# btrfs fi df /mnt
Data, RAID0: total=1.05GiB, used=512.00KiB
Data, single: total=8.00MiB, used=0.00
System, RAID1: total=8.00MiB, used=16.00KiB
System, single: total=4.00MiB, used=0.00
Metadata, RAID1: total=1.00GiB, used=112.00KiB
Metadata, single: total=8.00MiB, used=0.00

Z hlediska bezpečnosti dat je ale pochopitelně lepší, nejsou-li v módu raid1 pouze metadata, ale také vlastní data. Pokud tedy víme že budeme chtít mít zrcadlená také data, můžeme rovnou vytvořit zrcadlený Btrfs souborový systém.

Poznámka
stroj:~# mkfs.btrfs -L test -draid1 -f /dev/loop1 /dev/loop2
...
stroj:~# mount /dev/loop2 /mnt
stroj:~# btrfs fi show /mnt
Label: test  uuid: 3543864f-c776-4b5b-8336-4f3ee03b478d
        Total devices 2 FS bytes used 640.00KiB
        devid    1 size 5.00GiB used 2.03GiB path /dev/loop1
        devid    2 size 5.00GiB used 2.01GiB path /dev/loop2

Btrfs v3.12
stroj:~# btrfs fi df /mnt
Data, RAID1: total=1.00GiB, used=512.00KiB
Data, single: total=8.00MiB, used=0.00
System, RAID1: total=8.00MiB, used=16.00KiB
System, single: total=4.00MiB, used=0.00
Metadata, RAID1: total=1.00GiB, used=112.00KiB
Metadata, single: total=8.00MiB, used=0.00

Zrcadlený souborový systém však můžeme vytvořit pomocí balancingu i dodatečně, poté co k již existujícímu blokovému zařízení přidáme další o minimálně stejné velikosti.

Poznámka
stroj:~# mkfs.btrfs -L test -f /dev/loop1
...
stroj:~# mount /dev/loop1 /mnt
stroj:~# btrfs fi show /mnt
Label: test  uuid: f6b45593-a09d-448b-98e3-3fac066341f0
        Total devices 1 FS bytes used 192.00KiB
        devid    1 size 5.00GiB used 548.00MiB path /dev/loop1

Btrfs v3.12
stroj:~# btrfs fi df /mnt
Data, single: total=8.00MiB, used=64.00KiB
System, DUP: total=8.00MiB, used=16.00KiB
System, single: total=4.00MiB, used=0.00
Metadata, DUP: total=256.00MiB, used=112.00KiB
Metadata, single: total=8.00MiB, used=0.00
Btrfs v3.12
stroj:~# btrfs add /dev/loop2 /mnt
...
stroj:~# btrfs fi show /mnt
Label: test  uuid: f6b45593-a09d-448b-98e3-3fac066341f0
        Total devices 2 FS bytes used 192.00KiB
        devid    1 size 5.00GiB used 548.00MiB path /dev/loop1
        devid    2 size 5.00GiB used 0.00 path /dev/loop2

Btrfs v3.12

To, že se přidá nové zařízení však neznamená, že se začnou automaticky extenty zrcadlit. Z posledního výpisu je zřejmé, že na čerstvě přidaném blokovém zařízení není obsazen ani bajt. Je tedy třeba provést vybalancování souborového systému.

Poznámka
stroj:~# btrfs fi df /mnt
Data, single: total=8.00MiB, used=64.00KiB
System, DUP: total=8.00MiB, used=16.00KiB
System, single: total=4.00MiB, used=0.00
Metadata, DUP: total=256.00MiB, used=112.00KiB
Metadata, single: total=8.00MiB, used=0.00
stroj:~# btrfs balance start -dconvert=raid1 /mnt
Done, had to relocate 1 out of 5 chunks
stroj:~# btrfs fi df /mnt
Data, RAID1: total=1.00GiB, used=320.00KiB
System, DUP: total=8.00MiB, used=16.00KiB
System, single: total=4.00MiB, used=0.00
Metadata, DUP: total=256.00MiB, used=112.00KiB
Metadata, single: total=8.00MiB, used=0.00

Z výpisu je evidentní, že pouhá konverze datových bloků nestačí a musí se překonvertovat taky extenty ve kterých jsou uloženy systémová data a metadata..

Poznámka
stroj:~# btrfs balance start -f -sconvert=raid1 -mconvert=raid1 -dconvert=raid1 /mnt
...
stroj:~# btrfs fi df /mnt
System, RAID1: total=32.00MiB, used=16.00KiB
Metadata, RAID1: total=256.00MiB, used=112.00KiB
stroj:~# echo 'pozor' > /mnt/test
stroj:~# btrfs fi df /mnt
Data, single: total=1.00GiB, used=0.00
System, RAID1: total=32.00MiB, used=16.00KiB
Metadata, RAID1: total=256.00MiB, used=112.00KiB
stroj:~# btrfs balance start -f -sconvert=raid1 -mconvert=raid1 -dconvert=raid1 /mnt
...
stroj:~# btrfs fi df /mnt
Data, single: total=1.00GiB, used=0.00
System, RAID1: total=32.00MiB, used=16.00KiB
Metadata, RAID1: total=256.00MiB, used=112.00KiB
stroj:~# btrfs fi show /mnt
Label: test  uuid: f6b45593-a09d-448b-98e3-3fac066341f0
        Total devices 2 FS bytes used 448.00KiB
        devid    1 size 5.00GiB used 1.28GiB path /dev/loop1
        devid    2 size 5.00GiB used 288.00MiB path /dev/loop2

Btrfs v3.12
stroj:~# df -h
...
/dev/loop1                   10G  576K  9,5G   1% /mnt
stroj:~#

Komprese

Používat kompresi lze u Btrfs od jádra verze 2.6.38

Aktivuje se použitím volby compress při mountu. Btrfs pak průběžně před zápisem na disk extenty komprimuje a ověřuje kompresní poměr. Není-li výhodný, tak zapíše data bez komprese.

Data se komprimují automaticky na pozadí, ovšem pouze pokud stíhá CPU!.

Komprimovaná data zabírají fyzicky méně místa. Proto je komprese na úrovni souborového systému výhodná kupř. tam, kde se ukládají především textová data.

Naopak svou režií zbytečně zatěžuje CPU tam, kde se ukládají multimediální soubory, či data pakovaná do malých komprimovaných archívů (typicky např. rozdílové objekty u gitu!).

Poznámka Komprimace se provádí před uložením extentu z vyrovnávací paměti (cache) na disk. Nelze ji tudíž používat, je-li diskový oddíl s Btrfs namountován v režimu COW, kdy se ukládají pouze rozdílová data, nebo direct IO, při kterém se nepoužívá vyrovnávací paměť a data zapisuje rovnou na disk.
Poznámka
root@stroj:~# mount -t btrfs /dev/data/btrfs /mnt -o compress
root@stroj:~# mount | grep btrfs
 /dev/mapper/data-btrfs on /mnt type btrfs (rw,relatime,compress=zlib,space_cache)

Výchozí kompresní algoritmus, který se použije není-li určeno jinak je ZLIB. Ten sice dosahuje oproti alternativnímu LZO lepšího kompresního poměru, je však pomalejší a víc zatěžuje procesor.

Algoritmus LZO, který je navržen pro kompresi v reálném čase, zatěžuje procesor mnohem méně, ovšem jeho výsledky mají horší kompresní poměr a tak jsou data zapisována ve větší míře bez komprese.

Poznámka
root@stroj:~# mount -t btrfs /dev/data/btrfs /mnt -o compress=lzo
root@stroj:~# mount | grep btrfs
 /dev/mapper/data-btrfs on /mnt type btrfs (rw,relatime,compress=lzo,space_cache)
Poznámka Od linuxového jádra verze 4.11 by mělo dojít k výraznému zlepšení výkonu u kompresního algoritmu LZ4, který nabízí mnohem rychlejší kompresi i dekompresi než LZO při zachování stejného kompresního poměru. Ovšem vývojáři Btrfs o jeho implementaci neuvažují, protože mají poněkud jinou představu.

Spíše by chtěli umožnit, aby bylo možné nastavit silnější kompresi, která by poskytla lepší kompresní poměr, byť i za cenu pomalejšího zápisu. Rychlost čtení dekomprimovaných dat by tak zůstala stejná, ale vedlo by to k efektivnějšímu využití místa na blokovém zařízení.

Faktem je, že použití algoritmu LZ4, který získává na výkonu především tím, že si umí rozložit práci do více vláken (a tím i využít více procesorových jader současně) u Btrfs, které pracuje s poměrně malými bloky dat nedává smysl.

Vynucená komprese

Upozornění Špatný kompresní poměr může vznikat mimo jiné když CPU nestíhá data komprimovat v reálném čase. Btrfs bez vynucené komprese v takovém případě začne data ukládat nekomprimovaná. V takovém případě tedy může být aplikace vynucené komprese silně kontraproduktivní!
Poznámka Při vynucené kompresi nelze použít volby nodatacow a nodatasum.

Rozhodovací mechanismus Btrfs, který určuje zda-li se mají uložit data s kompresí či bez, lze ovlivnit použitím volby compress-force. Tím si lze natvrdo vynutit kompresi data a případně i kompresní algoritmus, bez ohledu na to, je-li kompresní poměr výhodný či nikoliv.

Poznámka
root@stroj:~# mount -t btrfs /dev/data/btrfs /mnt -o compress-force=zlib
root@stroj:~# mount | grep btrfs
 /dev/mapper/data-btrfs on /mnt type btrfs (rw,relatime,compress-force=zlib,space_cache)

Vynucené vyloučení komprese

Stejně tak jako si lze vynutit kompresi a kompresní algoritmus, je možné také kompresi zcela vypnout. A to tak, že se předá jako parametr volby compress či compress-force místo jména komprimačního algoritmu no.

Poznámka
root@stroj:~# mount -t btrfs /dev/data/btrfs /mnt -o compress=no
root@stroj:~# mount | grep btrfs
 /dev/mapper/data-btrfs on /mnt type btrfs (rw,relatime,compress=no,space_cache)

Vypnutí (nebo zapnutí) komprese pro jeden souboru

Vypnutí komprese se hodí u velkých souborů s jejichž obsahem se často pracuje a které už mnohdy komprimuje aplikace, která s nimi pracuje – typicky jde třeba o velké obrázky, nebo videa. V takovém případě komprese na úrovni souborového systému vůbec nedává smysl.

Poznámka
root@stroj:~# btrfs property set /cesta/k/nekomprimovanemu_souboru compression ""

Po aplikaci tohoto příkazu bude vypnuta komprese, ovšem pouze pro nově vytvářené extenty(!), a to jen dokud nedojde nějakým způsobem opět k její aktivaci (např. příkazem pro nastavení atributů chattr +c)

Podobným způsobem si lze také u souboru vynutit jiný než výchozí kompresní algoritmus…

Poznámka
root@stroj:~# btrfs property set /cesta/k/souboru_komprimovanemu_lzo compression lzo

Jakým způsobem Btrfs aplikuje kompresi?

Jak už padla zmínka, Btrfs neaplikuje kompresi přímo na uložené soubory, ale na jednotlivé extenty souborového systému. V rámci jednoho svazku se tak mohou vyskytovat jak extenty nekomprimované, tak extenty komprimované přes ZLIB, či LZO.

Upozornění Komprese (a to platí i pro zvolený algoritmus), se aplikuje po namountování až na nově zapsané extenty. Extenty, které byly uloženy dříve, zůstávají beze změny.

Dodatečná komprimace extentů

Dodatečně lze extenty komprimovat (i dekomprimovat) během defragmentace. Pouze je třeba si uvědomit, že Btrfs nepracuje se stromovou strukturou, ale s objekty. Mají-li se tedy komprimovat datové extenty jednoho souboru, je třeba aplikovat příkaz pouze na tento objekt (soubor)

Starších verze btrfs-progs (<4.9) neuměly zpracovávat soubory a podadresáře rekurzivně, tudíž bylo nutné příkaz k defragmentaci aplikovat na každý objekt zvlášť pomocí utility find.

Poznámka
root@stroj:~# find /mnt -exec btrfs filesystem defrag -czlib '{}' \;
root@stroj:~# btrfs filesystem df /mnt
 System: total=4.00MB, used=4.00KB
 Data+Metadata: total=996.00MB, used=183.27MB
root@stroj:~# sync
root@stroj:~# btrfs filesystem df /mnt
 System: total=4.00MB, used=4.00KB
 Data+Metadata: total=996.00MB, used=165.39MB

V současné době to již není třeba. Stačí uvést cestu k adresáři. Pro defragmentaci celého namountovaného kořenového systému tedy stačí zadat parametr -r a jako cestu kořen / viz:

Poznámka
root@stroj:~# btrfs filesystem defrag -v -r -czlib -l 32768 /
…
Poznámka Pomocí volby -l lze nastavit, minimální velikost objektu pro defragmentaci. U souborů, které se vejdou do minimální velikosti jednoho datového extentu totiž defragmentace moc nedává smysl, takže by se takto měly při rekurzivním zpracování ignorovat.

Lze zjistit aktuální kompresní poměr?

Bohužel v současné době nelze zjišťovat, s jakým kompresním poměrem jsou data uložená, neboť do nástroje btrfs prozatím není integrován patch, který umožňuje zjistit kolik fyzického místa na disku zabírají komprimovaná data uloženého souboru.

Více k tématu viz odkazy[2]

Vliv komprese na výkon

Komprese má pochopitelně vliv na výkon. Maximální velikost komprimovaného datového rozsahu je 128 KiB, kdy se zvlášť komprimuje každý blok o velikosti 4KiB (odpovídající velikosti stránky v paměti). Pro načtení libovolného bajtu z tohoto rozsahu se tak musí vždy rozbalit do paměti celý rozsah, tj. všech 128 KiB dat.

Subvolume

Btrfs-subvolume-scheme.svg

Btrfs je souborový systém, který však má některé aspekty LVM. Mimo jiné umožňuje vytvářet tzv. subvolume a jejich snapshoty, které z hlediska souborového systému sice vypadají jako adresáře, ale fungují jako logické diskové oddíly a jejich snapshoty.

  • Subvolume lze namountovat na jiný přípojný bod, stejně jako logický diskový oddíl.
  • Na subvolume lze aplikovat nastavení kvót.
  • Z aktuálního obsahu subvolume lze vytvářet snapshoty, stejně jako v LVM, které lze namountovat, i exportovat a zpětně importovat do jiného subvolume stejného, ale i jiného Btrfs souborového systému.
Poznámka Z hlediska Btrfs je snapshot subvolume, které spravuje pouze rozdílová data jimiž se snapshot od původního subvolume liší. Pokud je původní subvolume odstraněno, zahodí jen data, která s nimiž snapshot už nemá nic společného a ta zbylá se do něj zaintegrují. Ze snapshotu se tím stane regulérní subvolume.

Vytvoření subvolume

Vytvoření subvolume se provádí pomocí utility btrfs s parametrem subvolume a příkazem create, kterému se přidá cesta do přípojného bodu, kam máme připojen svazek s Btrfs, doplněná o jeho unikátní název, který nesmí být v kolizi s jiným existujícím souborem na přílušné úrovni. Bez ohledu na to, bylo-li by to jiné subvolume, snapshot, soubor či adresář.

Poznámka
stroj:~# btrfs subvolume create /mnt/Subvolume\ B
Create subvolume '/mnt/Subvolume B'

Na ilustračním obrázku adresářové Btrfs struktury vpravo, jsou subvolume podbarveny červeně. Ačkoliv z pohledu souborového systému nově vytvořené subvolume s názvem "Subvolume B" vypadá jako prázdný adresář, skončí pokus o jeho odstranění příkazem rmdir chybou

Poznámka
stroj:~# ls -al /mnt/Subvolume\ B
celkem 4
drwxr-xr-x 1 root root   0 srp 12 15:10 .
drwxr-xr-x 1 root root 282 srp 12 12:42 ..
stroj:~# rmdir /mnt/Subvolume\ B
rmdir: odstranění „/mnt/Subvolume B“ selhalo: Operace není povolena

Pro nedestruktivní zjištění zda-li jde o adresář nebo subvolume či snapshot lze použít utilitu btrfs s parametrem subvolume a příkaz show

Poznámka
stroj:~# btrfs subvolume show /mnt/Subvolume\ B
/mnt/Subvolume B
        Name:                   Subvolume B
        uuid:                   eb730a78-2ec5-d045-9526-2ad6bd10ef46
        Parent uuid:            -
        Creation time:          2013-08-12 15:10:41
        Object ID:              3514
        Generation (Gen):       679887
        Gen at creation:        679887
        Parent:                 5
        Top Level:              5
        Flags:                  -
        Snapshot(s):

Pokud by nešlo o subvolume či snapshot, skončil by příkaz chybou

Poznámka
stroj:~# btrfs subvolume show /mnt/Directory\ A
ERROR: '/mnt/Directory A' is not a subvolume

Vytvoření snapshotu

Snapshoty jsou na ilustračním obrázku adresářové Btrfs struktury vpravo podbarveny zeleně. Lze si je představit jako snímek určitého stavu subvolume, se kterým lze dále pracovat, nemá-li příznak "readonly".

Poznámka
stroj:~# btrfs subvolume snapshot -r /mnt/Subvolume\ B /mnt/Snapshot\ B
Create a readonly snapshot of '/mnt/Subvolume B' in '/mnt/Snapshot B'

Výchozím zdrojem snapshotu nemusí být pouze subvolume, ale může jím být klidně jiný snapshot, nebo subvolume, které je součástí jiného snapshotu, jako kupř. subvolume "Subvolume d", které je součástí snapshotu s názvem "Snapshot B". Pokud bychom si vytvořili rozdílový soubor mezi "Subvolume d first" a "Subvolume d second", pak bychom zjistili, která data přibyla v "Subvolume d" od doby vytvoření snapshotu "Snapshot B" (který nelze modifikovat, jelikož má příznak readonly) do okamžiku vytvoření snapshotu "Snapshot d second".

Připojení subvolume ( snapshotu )

Pokud chceme namountovat pouze subvolume, nebo jeho snapshot, tak se přidá jako doplňková volba jeho relativní cesta coby parametr atributu subvol

Poznámka
stroj:~# mount /dev/mapper/btrfs-volume /mnt -o subvol="/Subvolume B"

Zrušení snapshotu či subvolume

Poznámka
stroj:~# btrfs subvolume delete /mnt/Subvolume\ B
Delete subvolume '/mnt/Subvolume B'
Upozornění Při zrušení se odstraní pouze extenty, které nejsou použity nikde jinde. To je třeba brát v úvahu, pokud chceme uvolnit místo na disku. Extenty, které patřily do subvolume "Subvolume d", by se nyní staly součástí snapshotu "Snapshot d first" a zůstanou i nadále na disku.
Poznámka Od verze 3.9 má btrfs podporu pro defragmentaci extentů, které patří ke snapshotům.
U novějších verzí Btrfs dojde k definitivnímu zrušení subvolume až po zapsání změn na disk. Pokud by došlo k restartu stroje ještě předtím, než se změny skutečně zapíší, tak se rušený subvolume znovu objeví.
Poznámka
stroj:~# btrfs subvolume delete -C /mnt/Subvolume\ B
Transaction commit: after each
Delete subvolume '/mnt/Subvolume B'
Aplikací volby -C lze vynutit zápis na disk ihned po zrušení subvolume. Má-li být jedním příkazem zrušen větší počet subvolume lze tento zápis na disk vynutit až na závěr celé operace volbou -c.


Kvóty

Kvótování umožňuje nastavit limity, omezující objem dat, uložitelný do subvolume. Aktivace kvót a nastavení limitu je základní krok u Btrfs subvolume, u kterého reálně hrozí, že se na něj budou ukládat data o jejichž budoucím objemu nemáme nejmenší potuchy.

Upozornění Ačkoliv Btrfs pracuje s kvótami od vanilla jádra verze 3.6, byl nástroj btrfs (u Debianu součást instalačního balíku btrfs-tools) rozšířen o kód umožňující sofistikovanou práci s kvótami až v říjnu 2013 - po vydání vanilla jádra 3.14

Protože btrfs-tools, které jsou součástí stabilní distribuce Debianu nekopírují aktuální verze jádra, nemusí mít nástroj btrfs na vašem stroji některé volby potřebné pro práci s kvótami k dispozici!

Nač kvóty?

Pokud si někdo myslí, že v případě nutnosti postačí pro uvolnění místa smáznout několik adresářů s postradatelnými daty - jako je tomu zvykem u souborových systémů které nepoužívají COW (Reiserfs, Ext4, apod.) - bude u Btrfs nemile překvapen.

Pokud totiž byl vytvořen snapshot subvolume, tak po smazání adresáře a jeho obsahu nedojde k odstranění datových bloků, ale pouze deskriptorů, které na ně vedou. Datové bloky se uvolňují až poté, co přestanou existovat všechny deskriptory na ně odkazující, tedy i ty ze snapshotů.

Co se stane když je souborový systém Btrfs plný?

Je-li souborový systém s Brfs plný, tak se automaticky remountuje do read-only režimu.

Poznámka Remountem do read-only stavu se Btrfs brání tomu, aby došlo místo úplně[3]. Při každé diskové operaci - včetně mazání souborů se totiž pracuje s metadaty a pokud by Btrfs nemělo na disku k dispozici alespoň minimum prostoru, tak by už nebylo možné soubory ani smazat.

Remount do stavu read-write - bez toho aniž by bylo nutné zasahovat do běžících procesů - se podaří pouze v tom případě, že se zaplněný souborový systém Btrfs rozšíří o další blokové zařízení.

Není-li k dispozici, nezbývá než povraždit všechny procesy, které si na připojeném Btrfs drží otevřené deskriptory - jinak ho nebude možné korektně odpojit. A teprve pak ho odpojit a znovu připojit.

Poznámka Btrfs se úplnému zaplácnutí disku brání tím, že si v rámci blokového zařízení udržuje tzv. "globání rezervu", kterou využije při read-write mountu.

To je okamžik, kdy btrfs-cleaner odstraní bezprizorné datové bloky a uvolní místo. Místo lze u zaplněného Btrfs získat také rekompresí datových bloků, ale i pro tuto operaci musí být k dispozici alespoň minimum místa.

Jakým způsobem jsou aplikovány kvóty

Btrfs umožňuje nastavit dva typy kvót:

rfer
Není-li řečeno jinak, je nastavením kvóty limitován celkový objem dat, které se vztahují k subvolume - tedy včetně těch dat, na které už neodkazuje přímo subvolume, ale jeho snapshoty. Proto se nazývá tento limit referenční kvóta Aktuální hodnotu najdete ve výpisu v sloupci rfer. Velikost nastaveného limitu zobrazuje pouze při rozšířeném výpisu, ve sloupci max_rfer.
excl
Limitovat lze ale také maximální 'objem dat k jednomu subvolume - ten se zobrazuje ve sloupci excl - exkluzívní kvóta.

Jak uvolnit místo při dosažení kvóty

Jsou-li na připojený souborový systém aplikovány kvóty, tak by nemělo dojít k situaci, že by došlo k remountu do read-only stavu. Protože v případě, že k dokončení souborové operace nebude dost volného místa, oznámí tuto skutečnost souborový systém Btrfs dřív, než k tomu - v rámci blokového zařízení - skutečně dojde.

V případě, že je nastaven limit na celkový objem dat (max_rfer), lze situaci operativně řešit:

  • rekompresí datových extentů
  • navýšením kvóty
  • nebo uvolněním místa zmenšením některého z uložených souborů na nulovou velikost[4]

Je-li nastavena kvóta na celkový objem dat jednoho subvolume, tak je nutné u tohoto subvolume kvótu navýšit, nebo z něj něco umazat.

quota - aktivace nastavení kvót

Ve výchozím stavu má Btrfs použití kvót vypnuto. Aby s nimi bylo možné pracovat, musí se nejprve aktivovat příkazem quota.

root@stroj~# btrfs quota enable /mnt/subvolume
root@stroj~# btrfs qgroup show /mnt
0/5 4096 4096
0/257 4096 4096
0/258 4096 4096
0/259 4096 4096

Po aktivaci kvót je limit u všech subvolume bez omezení!

Kvóty lze kdykoliv deaktivovat..

root@stroj~# btrfs quota disable /mnt/subvolume
root@stroj~# btrfs qgroup show /mnt
ERROR: can't list qgroups: No such file or directory
Upozornění Je třeba mít na paměti, že při deaktivaci kvót veškeré nastavení limitů nenávratně zmizí.
Upozornění Kvóty lze kdykoliv stejným příkazem zase deaktivovat, je ovšem třeba mít na paměti, že Btrfs při deaktivaci kvót veškeré nastavení zahodí.

To zda má váš Btrfs FS kvóty aktivovány lze zjistit triviálním dotazem:

root@stroj~# btrfs qgroup show /

Jsou-li kvóty aktivovány, vyjede tabulka se seznam subvolume, ze které lze vyčíst, kolik každé z nich obsahuje dat. Pokud kvóty aktivovány nejsou, skončí příkaz chybou.

Aktivace kvót je jednoduchá, navíc sebou pak nese jako bonus možnost zjistit skutečný objem dat v subvolume:

root@stroj~# btrfs quota enable

Každé subvolume je v seznamu identifikováno přes svůj qgroupid, což je kombinace čísla úrovně skupiny kvót a čísla "Object ID" příslušného subvolume.

Poznámka Ve výchozím stavu má každé subvolume nastaven neomezený limit.

Nastavení, popř. rušení limitu se provádí příkazem quota. Takže...

quota
příkaz pro aktivaci či deaktivaci kvót
qgroup
příkaz pro práci s kvótami

Reflink

Defragmentace

Defragmentace je proces, kdy se data jednoho souboru, rozdělená na více objektů rozházených po celém disku scelí do jednoho nového objektu.

Btrfs pracuje s on-line defragmentací. To znamená, že lze objekty defragmentovat za normálního provozu. Defragmentace se totiž v btrfs provádí de fakto automaticky, při každém kopírování či přesouvání souboru, neboť cílový objekt se vytváří z těch stávajících jako zbrusu nový, scelením objektů původních. Díky tomu jsou takové operace v btrfs bezpečnější než u jiných FS, protože původní objekty se odstraňují až poté co úspěšně vytvořen objekt nový.

I tak se ale může stát, že se vyskytnou defragmentované soubory. Obzvláště tehdy, je-li disk poměrně plný, protože k jednou vytvořeným objektům se už btrfs automaticky nevrací. Proto lze objekty deframentovat i dodatečně.

Každá položka souborového systému je samostatný objekt. Defragmentace adresáře v případě btrfs se tedy v žádném případě neaplikuje rekurzivně na objekty, které jsou jinak jeho součástí. Defragmentují se pouze metadata, která se týkají objektu který je defragmentován (adresář).

Rekurzivní defragmentaci lze provést s využitím utility find

Upozornění Přitom je třeba mít na vědomí, že při defragmentaci objektu, pro který v rámci btrfs existuje nějaká přírůstková kopie (COW) - typicky objekt, který je součástí snapshotu, dojde k jejich vzájemnému oddělení a vytvoření vzájemně nezávislých objektů. Tzn. že si data ukousnou další místo na disku!

Scrub

Export/Import Btrfs subvolume

Btrfs-subvolume-export.svg

Vlastnosti Btrfs z principu vylučují, aby bylo možné zkopírovat obsah subvolume, včetně případných snapshotů prostým příkazem cp, aniž by došlo k duplikaci dat. Pro takové případy, kdy chceme vytvořit kopii (nebo zálohu) subvolume, má utilita btrfs příkazy send, kterým se provede export do proudu dat a receive, kterým se ze vstupního proudu dat vytvoří kopie subvolume na jiném místě či stroji.

Ilustrační schéma popisuje situaci, kdy se exportuje snapshot "Readonly snapshot c" ze stroje "stroj-A" na "stroj-B".

  • Nejprve se vytvoří na stroji stroj-A "readonly" snapshot subvolume "Subvolume c"
Poznámka Btrfs je stále ve vývoji, proto lze vyexportovat pouze snapshot subvolume, který je ve stavu "readonly". Nikoliv subvolume jako takové, nebo některý z jeho podadresářů.
  • Na stroji stroj-B se připraví subvolume "Subvolume B", do kterého se bude importovat exportovaný stream
  • Pak se ze stroje stroj-A snapshot "Readonly snapshot c" odešle na stroj-B kde v "Subvolume B" vytvoří jeho kopiie
Poznámka
stroj:~# btrfs send -v /mnt/Readonly\ snapshot\ c | ssh root@stroj-B 'btrfs receive /mnt/Subvolume\ B'
send
V exportovaném proudu dat, který se posílá na standardní výstup a který se může prohnat rourou nebo také přesměrovat do souboru, jsou obsaženy veškeré data, které patřily k "Subvolume B" v okamžiku, kdy byl vytvořen "Readonly snapshot c"
receive
Po naimportování vznikne z přijatý dat snapshot, který je opět ve stavu "readonly". Ale pokud se vůči němu vytvoří zapisovatelný snapshot a původní naimportovaný "Snapshot subvolume c" je zrušen, tak se "Readwrite subvolume C from snapshot" změní na normální subvolume s nímž lze dále pracovat.

Obnova btrfs

Pro obnovu btrfs existuje utilita btrfs-restore, která umožňuje nedestruktivním způsobem obnovit data ze souborového systému, který nejde namontovat.

Odkazy

  1. Do těchto dočasných souborů se zapisuje přes otevřený deskriptor, takže v rámci souborového systému nejsou nikde vidět. Jejich obsah a příslušná metadata se po uzavření deskriptoru zahodí.
  2. Btrfs - komprese(angl.)
  3. Stejný problém se týká i staršího ZFS, které však na rozdíl od Btrfs žádnou globální rezervu nemá - tudíž nastavení výchozí kvóty je u ZFS, které nelze operativně zvětšit o další blokové zařízení prvořadá záležitost.
  4. Soubor lze na nulovou velikost zmenšit buď utilitou truncate (u Debianu součást instalačního balíku coreutils), nebo zkrácením ke kterému dojde, když do souboru zapíšete 0 znaků.
https://btrfs.wiki.kernel.org/index.php/Problem_FAQ Oficiální FAQ
https://wiki.archlinux.org/index.php/Installing_on_Btrfs_root Btrfs jako kořenosý souborový systém
https://wiki.archlinux.org/index.php/Maximizing_Performance Maximalizace výkonu u Btrfs
http://www.ckernel.org/news/uploadfile/2012/ppt/04.pdf Příspěvek z China Linux Kernel Developer Conference 2012 o defragmentaci Btrfs snapshotů