A "megfelelő" megoldás az ext4 késleltetett allokáció "problémára"

Az elmúlt héten túlfűtött viták alakultak ki internet szerte arról, hogy az ext4-ben 2008 közepén bemutatkozott delayed allocation (késleltett allokáció) kód fokozottan veszélyes-e az adatbiztonságra, vagy sem. Noha Ted Ts'o szerint a késleltetett allokációval kapcsolatban megreklamált "0 hosszúságú file" probléma leginkább alkalmazás-tervezési probléma, a fejlesztő már a probléma felbukkanásakor workaround-okat készített rá. Most azonban egy nemrég elkészített patch nyomán talán megnyugszanak a kedélyek.

Ted nemrég egy olyan patch-et készített az ext4-hez, amely bevezeti a "data=alloc_on_commit" mount opciót az ext4 fájlrendszerhez. Ahogy azt a fejlesztő írja, a "data=alloc_on_commit" nem más, mint az ext3 fájlrendszer esetén használható "data=ordered" mount opció "bug-for-bug" kompatibilis vagy bug kompatibilis hasonmása.

Mit jelent ez? Azt, hogy az ext4 fájlrendszert "data=alloc_on_commit" opcióval felcsatolók gyakorlatilag azt az eredményt érik el, mintha az ext3 fájlrendszert a "data=ordered" módban csatolták volna fel (ami egyébként ext3 esetén az alapértelmezett felcsatolási opció).

Az még nem világos, hogy a "data=alloc_on_commit" alapértelmezett csatolási opció lesz-e az ext4-hez.

A mount opció legelőször a 2.6.30-as kernelben található ext4 kódban bukkanhat fel.

A Heise cikke részletesen foglalkozik a problémával.

Hozzászólások

erdkes olvastam olyan erveket Ted Ts'o tol hogy mas filerendszerek is erintettek, mint pl btrfs, szerintem csak "magyarazom a bizonyitvanyom" volt...

btrfs faq:

"Does Btrfs have data=ordered mode like Ext3?

Yes. In v0.16, Btrfs waits until data extents are on disk before updating metadata. This ensures that stale data isn't exposed after a crash, and that file data is consistent with the checksums stored in the btree after a crash.

Btrfs does not force all dirty data to disk on every fsync or O_SYNC operation.
Can the data=ordered mode be turned off in Btrfs?

No, it is an important part of keeping data and checksums consistent. The Btrfs data=ordered mode is very fast and turning it off is not required for good performance."

wow. tehát 3 év után kaptunk egy kiszuperált ext3-at, ha jól értem

Mire alapozod ezt? Nekem az jött le, hogy az ext4 alapértelmezetten marad úgy ahogy eredetileg eltervezték, csak a sipárgóknak lett egy opció, amivel vissza tudják butítani. A Heise cikke szerint ez a normális működés. Az, hogy az ext3 "biztonságosabban" működik egy nem szándékos mellékhatás:

"the "safer" behaviour of Ext3 is only an unintended side effect"

--
trey @ gépház

Buta kérdés: reiserfs-ben hogy van ez megoldva? Mert az is nagyon gyors, és bármikor megy ki alóla az áram egy bit nem veszik el...

"A fejlesztot azert fizetik, hogy oldja meg a problemat. Ez egy kemeny szakma." - Chain-Q

Csak szerencséd volt. (Mondom ezt úgy, hogy hirtelenjében nem tudnék olyan szitut hozni, mikor ReiserFS-ről vesztettem adatot, ellentétben ext3-mmal, amiből már lényegesen többet láttam szétomlani és még csak nem is áramszünet vagy vinyó hiba miatt. Felüdülés volt a legutolsó ext3-s linuxom halála, amikor a disk döglött meg alatta ;)

XFS még egy eléggé mázli rendszer, ha kirántod a kakaót a gép alól (esetleg borítod a gépbe ;), de azt nem is ezért szeretjük.

FAT32 ugye vicc ilyen szempontból, NTFS mondjuk - szerintem - beton stabil. Igaz, nem feltétlen a leggyorsabb.

----------------
Lvl86 Troll

Mitől haláloztak el? Komolyan érdekelne, hátha csak én nem találkoztam hasonló szituval. (Eddig két esetben láttam NTFS-t megborulni, egyik, mikor én csesztem el magát a particiót, másik, mikor az egyik vinyónak megdöglött a particiókat leíró szektora.)

----------------
Lvl86 Troll

Van sokszor véletlenszerű borulás. Egyik nap megy a gép, kikapcsolják, reggel már nem megy, mert az NTFS megborult. Nem tudom ennek mi lehet az oka, de tényleg legalább havi 1 ilyen van.
Áramszünetek esetén is szokott borulni a rendszer.
A leggyakoribb eset viszont amikor valami féreg szarrá fertőzi a rendszert és véletlenszerűen újraindítja a gépet, ekkor általában mindig NTFS kócolódás van.

Számtech szervízben dolgozom, sok a külső partnerünk és a behozott gépek alapján tudom ezt mondani.

--
Elméletileg nincs különbség elmélet és gyakorlat között. Gyakorlatilag van.

A K&R könyvben szó van az open(), write(), close() függvényekről, de nincs szó az fsync()-ről. Jó, azóta sok idő eltelt (30 év), a dolgok változnak. Úgy tudom, az fsync csak 2001-től POSIX, és azelőtt is volt élet.

Egy Jáva FileOutputStreamből elő lehet szedni a FileDescriptort, annak meg lehet hívni a sync metódusát, és le lehet kezelni a belőle jövő SyncFailedException-t. Olyan Jáva tananyagot viszont még nem láttam, ami ezt tárgyalta volna.

Ez azt sejteti, hogy sok program van/lesz még, ami nem törődik az fsync-kel. Márpedig az ext4 teljesítménye/minősége azon az _összhatáson_ lesz lemérve, amit a felette működő programokkal együtt produkál. Ezért nem okos dolog direkt szivatni a környezetet.

Nem tetszenek a mount opciók. Az alkalmazásokat nem érdekli, hogy alul milyen fs van. És addig jó, amíg nem érdekli, másképp az volna, hogy az egyik csak ilyen, a másik csak olyan paraméterekkel felmountolt fs-sel futna.

Teljesen rendben van, hogy a hatékonyság<->biztonság/kényelem követelmények szemben állnak egymással. Ami nem tetszik az ext4 hozzáállásában, hogy úgy akar hatékonyságot növelni, hogy másra hárítja át a feladatokat.

Nyilvánvaló, hogy úgy a leghatékonyabb a lemezreírás, ha egyáltalán nem írunk lemezre. Találja ki más, hogy mikor legyen az írás. Ez plusz feladatokat ad az alkalmazásfejlesztőknek, amiből plusz hibák lesznek. Teszteszözök is kellenének, amikkel ki lehet mutatni az fsync hiányát. Resetelgetni a gépet, és nézni, hogy mi romlott el, az nem túl bíztató lehetőség.

Na de honnan hiányzik az fsync véletlenül és honnan szándékosan? Nem egyszerű dolog kitalálni, hova kellenek az fsyncek. Együgyű elképzelés, hogy a "fontos" adatok kiírása után.

Még egy dolog a sipárgókról és "hobbikoderekrol". Kernighan és Ritchie a fentiek szerint hobbikoder. Az egyik legismertebb hobbikoder L.T., aki ráérő idejében kifejlesztett egy kernelt. Ezzel szemben a hivatásos kóder egy meglehetősen alacsony presztízsű foglalkozás, aki napi munkalap alapján dolgozik.

--
CCC3

"A K&R könyvben szó van az open(), write(), close() függvényekről, de nincs szó az fsync()-ről."

K&R csak a standard C-ről beszél, aminek az fsync() tényleg nem része. De különféle rendszerekre más standardok is vonatkoznak, amit egy nem hobbikódernek ismernie kellene.

"Úgy tudom, az fsync csak 2001-től POSIX, és azelőtt is volt élet."

Rosszul tudod.

En hobbikoder vagyok.

A konkrét eset nem túl érdekes. Általában az fsync nélküli programok is jól fognak működni. Az olyan programokban, mint a postgres a készítő az éppen aktuális trendnek és fs-nek megfelelően majd kiveszi meg berakja az fsyncet, mint ahogy az valóban meg is történt a postgresnél. (Mivel nem könnyű kitalálni, hogy mikor kell fsync, mikor nem, minthogy ez nem "bug", hanem koncepció.)

Az informatikában az az alapvető trend, hogy a szoftverek kényelmesebbé és biztonságosabbá válnak. Ezért programozunk Jávában assembler helyett, noha az utóbbi (primitív nézőpontból) hatékonyabbnak tűnhet. A Jáva pl. mindent elkövet azért, hogy a hulye koder a típusokat ne tudja összekeverni. Ugyanez a hulye koder viszont gondoljon az fsync-re, aminek a használatára nincs is megtanítva.

Ebben a szellemben szerintem egy fs-nek fel kell vállalnia a feladatot, hogy alkalmas időben szinkronizál. Ha másért nem, hogy hulye/hobbikoder-biztos legyen.

De a hatékonyságot is előmozdítja. Pl. egy lezárt fd-ről tudható, hogy a program többet nem akar foglalkozni vele. Az fs ezt látva alkalmas/ráérő idejében szinkronizálhat. Ha viszont az alkalmazás a close előtt explicite szinkronizál (megvárja az fsync visszatérését), akkor az fs szempontjából az fsync nem a legalkalmasabb időben jön, amivel a hatékonyság csökken.

--
CCC3

hogy alkalmas időben szinkronizál

- No igen, de kinek mi az alkalmas idő?
Nekem az is megfelelne (ha lenne elég bufferem), ha menet közben egyáltalán nem történne lemezre írás, hanem shutdown-kor szinkronizálna mindent! :>

Az én szememet ez a timeout-megközelítés bántja (x másodpercenként forced sync). Azzal kiegyeznék, ha a kernel beiktatna egy-egy sync-et azokban az időszakokban, amikor éppen kicsi a load.
Amikor viszont látja, hogy alszik a lemez, akkor mindent elkövet, hogy ne kelljen egy sync miatt felébreszteni.
Nekem fontosabb, hogy gyors legyen. Amikor meg altatom a lemezt, akkor azt azért csinálom, hogy tényleg aludjon (amikor úgysincs load, de zavarna a hangja :) ).

A rendszer stabil, a vas előtt ups van, ha mégis beütne a mennykő, ott van az előző napi backup (/etc és /home). Ez utóbbi (ti. rendszeres backup) az adatok legjobb barátja. Nem hiszem, hogy a fájlrendszert rendkívüli helyzetek kezelésére kellene kihegyezni. Legyen jó abban, amire való. IMHO.

Oke, gondolj abba a szituba bele, amikor egy kisebb alkalmazas irkalja a filesystemet. Mondjuk SAP vagy hasonlo, mogotte valamilyen adatbazis rendszer (oracle, maxdb, db2), ahol az SAP sajat kernel reteget irt a kulonbozo oprendszerek es adatbasis kezelok kozotti kulonbsegek elfedesehez. A konzisztenciat alkalmazas szinten kell biztositanod. Nem csak adatbazis szinten. Ja tobb ezer user log a rendzseren 7x24x365 uzemben. A storage diszkek nem szeretnek aludni, adatkozpont. Ez a masik veglet, mint otthon a hobbi desktop.

nagyon off:

> Egy Jáva FileOutputStreamből elő lehet szedni a FileDescriptort,

Ha Jáva, akkor FájlKimenetiFolyam. Más a kiejtés és más az írás. Ugyanis a nevéről van szó, és anyja/apja a Java nevet adta neki.
És assembler-ben nem szoktak programozni, mert az a fordító. Legfeljebb assembly-ben, mert az a nyelv.

nagon off vége

Ami pedig a tartalmat illeti, kénytelen vagyok azokkal egyetérteni, akik szerint egy alkalmazás írójától egy bizonyos szint felett elvárható, hogy ismerje azt a rendszert, amelyre fejleszt, és annak működését. Persze ez gyakorlatban hiú ábránd.

Az "off" nem magyar szó. Ha neked jogod van külföldiül írni, akkor nekem jogom van a külfödi Java (ejtsd dzsává) szó helyett a magyar Jáva (sziget) szót használni. Egyébként is úgy írok, ahogy akarok.

A tartalmat illetően. A mondanivalóm egyik eleme, hogy a szinkroniázálást nem kéne az alkalmazásokra hárítani, hanem az fs-nek kéne felvállalnia. Ez nem attól függ, hogy valaki egy szint felett van, és ismeri az fsyncet, hanem ez egy _koncepció_.

Az ext4 esete azért váltott ki felzúdulást, mert meglepő módon (és szerintem is tévesen) visszalépni készül ettől a koncepciótól a 10 vagy 20 éves POSIX-ra hivatkozva.

--
CCC3

en teljesen egyet ertek veled. amugy sem ertem, hogy a nem hobbikoder hogy csinalja, rak a programba egy bazi nagy matrixot, tarolva benne, hogy melyik filesystemnel kell mindenkepp fsync, melyiknel tul lassu stb., detektalja a filerendszert es a matrixbol kinezi, hogy akkor mi legyen?

szerk: lehet, hogy inkabb ezen hozzaszolasod ala kellett volna irni a valaszom, de mindegy

- Use the Source Luke ! -

Nekem is hasonló a problémám. Nevezetesen, hogy a C++ STL-jében _nincs_ fsync. 6-7 sorral el lehet ugyan jutni a C file descriptoráig, de ez azért mégsem elvárható.

Az egész probléma nem a delayed allocation miatt van. A probléma gyökere az, hogy a "rename" eredménye (vagy annak egy része) hamarabb kerül mentésre mint a fájl tartalma. Mint fentebb olvasható, a brtfs nem így működik. Azaz enélkül a meglehetősen furcsa viselkedés nélkül is lehet gyors fájlrendszert írni.
(Eleve kétlem, hogy az ilyen típusú, ritkán előforduló use-case nagymértékben befolyásolná a fájlrendszer hatékonyságát.)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Éppen szünet van az Amber versenyen.

Ez egy copy-paste-tel (!) átvett idézet a Postgres 8.3.6 doksi FAQ_hungarian filéből (2005-ös szöveg)

Számos teljesítmény javíto lehetõség van. Kikapcsolhatod az fsync() mûveletet a postmaster -o -F opciokval valo indításakor. Így nem fog az amugy lassú fsync() függvény meghívodni minden tranzakcio végén.

Ez meg egy friss szöveg a HISTORY filéből

Asynchronous commit delays writes to WAL during transaction commit (Simon) This feature dramatically increases performance for short data-modifying transactions. The disadvantage is that because disk writes are delayed, if the database or operating system crashes before data is written to the disk, committed data will be lost. This feature is useful for applications that can accept some data loss. Unlike turning off fsync, using asynchronous commit does not put database consistency at risk; the worst case is that after a crash the last few reportedly-committed transactions might not be
committed after all. This feature is enabled by turning off synchronous_commit (which can be done per-session or per-transaction, if some transactions are critical and others are not). wal_writer_delay can be adjusted to control the maximum delay before transactions actually reach disk.

Az első idézet azt mutatja, hogy a postgresben benne van az fsync, de néha szükségét érzik kikapcsolni. Valóban, ha egyszerűen minden tranzakciót azonnal fsyncelünk, akkor mennyivel vagyunk beljebb a DOS-hoz képest? Ugyanúgy kattog a diszk mint 20 éve.

Elfogadható kompromisszum volna, ha az os/fs valami nem túl hosszú várakozás után automatikusan szinkronizálna. Ext3-nál ez úgy tudom 5 sec. 5 percet is elfogadhatónak tartok, de 5 órát már nem (ez persze szubjektív).

Második idézet. Ha az automatikus szinkronizálásra nem lehet számítani, akkor muszáj fsyncelni. Hogy mégse legyünk ugyanott, ahol a DOS korszakban voltunk, az alkalmazás (postgres) maga oldja meg a tranzakciók bufferelését, viszont a flush után egyúttal fsyncel is. Vagyis kénytelen olyan funkciót megduplázni, ami az os/fs-ben is benne van, vagy benne lehetne.

Azt is mondhatanám, ha valaki fsyncel, akkor annak bufferelni is kell.

Az ext4 átdefiniálja a feladatot (alább adja), majd jelenti, hogy hatékonyságnövelést ért el. Ennek következtében az alkalmazási programok kénytelenek bufferelést+fsyncet alkalmazni. Szerintem jobb volna az automatikus szinkronizálás irányába menni. Nem csak a "hulye hobbi koderek" (bocs, ezek nem az én szavaim) kedvéért, hanem a postgres meg effélék kedvéért.

Lékó-Morozevics: 1-0:)
--
CCC3

Nekem ezzel az időzített szinkronizálással elvi problémám van. Mennyinek válasszuk ezt az időtartamot? Ahogy Te is írtad: 5 másodperc? 5 perc? 5 óra? Attól függ. Feladatkörönként más és más érték lenne megfelelő.
Nulladik közelítésben szerintem arra kellene elindulni, hogy a sync-ek olyankor történjenek, amikor kicsi a load. Tehát a kernel a lehetőségekhez képest ,,intelligens'' módon válassza meg az időpontokat, minimalizálva ezzel a teljesítménybeli veszteséget. Generálisabban megközelítve a dolgot ez egy ütemezési feladat.

Nekem ezzel az egésszel csak annyi a bajom, hogy az alapvető UNIX filozófiát és az operációs rendszer mibenlétét borítja. Ugyanis:
1) operációs rendszer feladata elrejteni a részleteket, és egy egységes, könnyen kezelhető felületet adni a programozó kezébe
2) UNIX alaptétel, hogy mindent fileokon keresztül kell kezelni.

Namármost, ha egy programnak tudnia kell, hogy hogyan tárolja a rendszer a filejait, és más kód kell, ha ext4, akkor nekem az a véleményem az ext4 sz@r (mindentől függetlenül, a fenti 2 pont alapján). Az nem lehet kifogás, hogy a programok rosszak, ha azok tökéletesen működnek más filerendszerekkel, annélkül, hogy tudnák, mit használ a kernel a file absztrakció alatt. Uff.