Hlavní navigace

Mazání dat uprostřed souboru

13. 9. 2014 12:07 (aktualizováno) | Tomas Matějíček
Řekněme, že máme soubor velký 2 GB a chceme někde uprostřed smazat pár bajtů. Co s tím? Ačkoli se zadání zdá jako triviální záležitost, ve skutečnosti tato akce vůbec jednoduchá není, protože žádný filesystém nenabízí pro tento úkol vhodnou operaci. Mazání dat ze souboru je a vždy bylo problematickou záležitostí.
Funkce podporované filesystémem zahrnují„otevření“ souboru (inicializace práce se souborem)skákání kurzorem v souboru (seek)čtení či zapisování dat na aktuální pozici ukazatelevynucení zapsání změn z paměti na disk (flush)řízení přístupu (lock)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), dokonce může 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). Ovšem operace pro odstranění dat z prostředka souboru chybí. Už desítky let. Co s tím?
Pokud jsou v souboru uloženy záznamy nějakého libovolného typu, je situace částečně řešitelná. Stačí když každý záznam obsahuje informaci o tom, zda je platný či smazaný. Odstranění záznamu se pak provede jednoduchým přepsáním příznaku (delete flag). Data fyzicky zůstanou na disku, jen aplikace která soubor čte je bude ignorovat. Při přidávání dalších dat do souboru se nejprve zjistí, zda se data vejdou do některého bloku označeného ke smazání, a pokud ano, dojde k jeho přepsání novými daty, a tím k recyklaci místa na disku.
Dobře řešitelná je i situace, kdy jsou záznamy konstantní délky. Pak je možné na místo „mazaných“ dat přepsat poslední záznam ze souboru, a soubor zkrátit o délku posledního bloku (truncate).
Ovšem situace, kdy soubor obsahuje stream dat, u kterého záleží na jejich pořadí (například video), není řešitelná vůbec. Představme si například úkol z videa vystříhnout nějakou sekvenci. V současné době nezbývá nic jiného, než data od místa odstraněného bloku bajtů přepsat (posunout, překopírovat). Taková operace je dost nebezpečná, protože při výpadku proudu bude soubor v nekonzistentním stavu, proto se většinou volí varianta jiná, kdy je původní soubor zachován, všechna data (bez smazaných bloků) jsou duplikována do souboru druhého, a až je vše hotovo tak se druhý soubor přejmenuje na první (a tím ho efektivně nahradí). Přejmenování je atomická operace, takže nekonzistence dat v tomto případě nehrozí.
Proč ale neexistuje operace pro smazání dat ze souboru? Tomu dost nerozumím. Přijde mi to jako velice užitečné, a navíc samotná implementace na úrovni filesystému musí být triviální. Všechny filesystémy totiž musí z principu počítat se situací, kdy je nutné interně soubor rozdělit (fragmentovat) na několik částí (fragmentů). Naše operace mazání dat uprostřed souboru by pak udělala to stejné – soubor by fyzicky na disku zůstal jak je, jen místo kde začíná mazání dat by se označilo příznakem konce fragmentu, a místo kde mají data zase pokračovat by se označilo začátkem dalšího fragmentu. Vše by se samozřejmě muselo nějak zaokrouhlit na interní velikost bloku filesystému, eventuelně někde na disku překopírovat pár základních bloků, pořád ale kopírujeme maximálně kilobajty.
Chápu, že pokud by programátor (či jeho aplikace) tohoto postupu zneužíval, docházelo by k obrovské fragmentaci dat na disku. Ovšem to už je otázka zodpovědnosti programátora, nikoli problém filesystémové operace.
Rád se nechám vyvést z omylu či poučit. Existuje filesystém který takovou operaci podporuje? Pokud ne, proč to ještě nikdo v Linuxu neimplementoval? Jsme sto let za opicemi? :)