Hlavní navigace

Mazání dat uprostřed souboru

Tomáš Matějíček

Před nějakým časem jsem si postěžoval na blogu, že linuxové jádro nenabízí dostatečnou funkčnost pro potřeby specifického okruhu úloh, jakou je například stříhání reklam z televizních nahrávek – ačkoli systém nabízí funkce pro zvětšování či zmenšování velikosti souboru, až donedávna nebylo možné mazat data uprostřed.

Dostalo se mi užitečného poučení, a jak jsem měl možnost zjistit, s novými jádry (počínaje 3.15) už je možné daný úkol optimálně vyřešit.

Malý úvod do filesystémových operací

Aplikace v Linuxu (nebo obecně v jakémkoli operačním systému) neimplementují práci se soubory na disku vlastními funkcemi. Místo toho používají funkce poskytované operačním systémem. Na jednu stranu je to ohromná výhoda, protože se nemusí každý programátor starat o to, jak správně na disk data uložit, na druhou stranu je to drobně nevýhodné v tom, že je člověk omezen předem daným rozsahem možností, které může se soubory provádět a nic víc.Běžné filesystémové operace pro práci s daty v souborech zahrnují:

  • čtení či zapisování dat na aktuální pozici ukazatele
  • skákání kurzorem v souboru (seek)
  • označení konce souboru (truncate)

Jak patrno, programátor má možnost v souboru skákat, zapisovat nová data přes stará, zapisovat nová data na konec (a tím soubor zvětšovat), může i označit určité místo jako konec souboru (a tím efektivně zahodit data uložená v souboru za pozicí ukazatele a soubor zmenšit), či dokonce skočit (seek) na místo daleko za koncem souboru (a tím soubor zvětšit, přeskočené místo se vyplní nulami, resp dírou). Ovšem operace pro odstranění dat z prostředka souboru až do nedávna chyběla.

Programátoři byli dlouhé roky nuceni tuto absenci obcházet. Například tak, že pokud potřebovali nějaká data v souboru umazat, musel se celý soubor zkopírovat někde bokem (s vynecháním dat, která jsou ke smazání) a pak se nový soubor přejmenoval na starý. Operace je to celkem bezpečná, ovšem krajně neoptimální, kopírujte kvůli umazání 10 megabajtů celých 20GB videa.

Řešení místo strašení

S jádrem 3.15 přišla ale podpora pro Collapsing file space. O co jde? Linuxové jádro přidalo do již existující interní funkce fallocate() podporu zahodit blok uprostřed souboru (zatím jen pro souborové systémy ext4 a XFS, což jsou mimochodem jediné filesystémy, které používám). Funkce se volá se dvěma parametry, offset a length, a odstraňuje ze souboru počet bajtů daný parametrem length, od pozice offset. Má to malý háček, parametry offset a length nemůžou být úplně libovolné, vždy musí jít o násobky velikosti bloku na konkrétním filesystému.

Praktické využití

První věcí, kterou je třeba udělat, je zjistit, jak velké bloky jsou na disku, na kterém chci fallocate používat:

# xfs_info /home/tom/video.ts | grep bsize   # pro XFS
# dumpe2fs /dev/sda1 | grep "Block size"     # pro ext4

Pak už jen stačí vhodně zaokrouhlit offset a length, a použít utilitu fallocate z balíku util-linux (parametr -c byl přidán ve verzi 2.25 a bude vám fungovat pouze, pokud běžíte na jádru 3.15 a novějším).

Pro mé konkrétní účely, kdy vystřihávám bloky dat z transport streamu nahraného z televize na XFS filesystému, musím zaokrouhlovat na 4096*47=192512 bajtů (což je nejmenší společný jmenovatel velikosti bloku na disku 4096 a velikosti bloku transport streamu 188 byte, a odpovídá cca 0,25 sekundám videa):

# fallocate -c -o 1078067200 -l 19251200 /home/tom/video.ts    # vyhodí cca 30 vteřin reklamy, 28 minut od začátku

Při použití nevhodně zaokrouhlených parametrů se nic nestane a fallocate pouze vrátí chybu Invalid Argument.

Hroucení (collapse) dat v souboru se nedá kvůli omezení na blokové zaokrouhlování použít pro precizní editaci, jakou by například bylo smazání pouhých deseti bajtů.

Ovšem tam, kde můžeme velikost mazaných dat přizpůsobit násobkům velikosti diskového bloku, jako je například stříhání reklam z videa pro domácí použití, jde o nejpřiměřenější metodu, která existuje, a navíc je jednoduše dostupná přes příkazovou řádku.

Našli jste v článku chybu?