11.12. A lemezek finomhangolása

11.12.1. Sysctl változók

11.12.1.1. vfs.vmiodirenable

A vfs.vmiodirenable sysctl változó értéke lehet 0 (ki) vagy 1 (be, és ez az alapértelmezés is). Ez a változó vezérli a könyvtárak gyorsítótárazását a rendszerben. A könyvtárak többsége kis méretű, így az állományrendszerből csak egyetlen (általában 1 KB méretű) darabkát használnak és még ennél is kevesebbet (általában 512 byte-ot) a pufferben. A változó kikapcsolt (avagy 0) értéke mellett a puffer csak rögzített számú könyvtárat táraz be még abban az esetben is, amikor temérdek mennyiségű memória áll a rendelkezésére. Ha viszont (az 1 értékkel) engedélyezzük, akkor a rendszer a könyvtárak tárazására felhasználja a virtuális memóriában pufferelt lapokat is, amivel lényegében az összes elérhető memóriát a könyvtárak tárazására fordítja. Ilyenkor azonban az egyes könyvtárak tárazására használt legkisebb memóriaterület a fizikai lapmérettel egyezik meg (ami általában 4 KB) és nem 512 byte. Abban az esetben javasoljuk ennek a beállításnak a használatát, ha olyan szolgáltatásokkal dolgozunk, amelyek nagy számú állománnyal dolgoznak egyszerre. Ilyen szolgáltatások többek közt a webes gyorsítótárak, nagyobb levelezőrendszerek és hírrendszerek. Az opció engedélyezése alapvetően nem veti vissza a rendszer teljesítményét még akkor sem, ha ezzel memóriát pazarlunk el, de ezt igazából érdemes kikísérletezni.

11.12.1.2. vfs.write_behind

A vfs.write_behind sysctl változó alapértelmezett értéke 1 (bekapcsolt). Ez arra utasítja az állományrendszert, hogy csak akkor küldje ki az adatokat az eszközre, ha belőlük teljes fürtök gyűltek össze. Ez jellemző módon nagyobb szekvenciális állományok írása esetén kedvező. Arra szolgál, hogy segítségével el lehessen kerülni az I/O túlságosan gyakori módosítások okozta terhelését. Bizonyos körülmények közt ez azonban lassíthatja a futó programok működését, ezért ilyenkor érdemes megfontolni a kikapcsolását.

11.12.1.3. vfs.hirunningspace

A vfs.hirunningspace sysctl változó értéke azt adja meg, hogy tetszőleges számú példánynál rendszerszinten mekkora mértékű írási művelet irányítható át a lemezvezérlők soraiba. Az alapértelmezés többnyire elegendő, de olyan gépeken, ahol sok lemez dolgozik egyszerre, ez az érték négy vagy öt megabyte-ra is felszökhet! Hozzátennénk, hogy ha ezt az értéket túlságosan nagyra állítjuk (és így túllépjük a puffer írási küszöbértékét), akkor ezzel hihetetlenül gyenge fürtözési teljesítményt nyerünk. Semmiképp se állítsuk túlzottan nagy értékre! A nagyobb írási értékek a velük párhuzamos olvasások számára késleltetést is jelentenek.

Találhatunk még más egyéb pufferelési és gyorsítótárazási sysctl változókat, azonban ezek megváltoztatását egyáltalán nem javasoljuk, mivel a virtuális memória alrendszer kiválóan tudja önállóan állítani ezeket a paramétereit.

11.12.1.4. vm.swap_idle_enabled

A vm.swap_idle_enabled sysctl változó módosítása olyan nagyobb többfelhasználós rendszerekben bizonyulhat hasznosnak, ahol sok felhasználó lép be és lép ki a rendszerbe és sok az üresjáratban futó program. Az ilyen jellegű rendszerek hajlamosak nagy mennyiségű folyamatos terhelést mérni a tartalékolt szabad memóriára. A beállítás engedélyezésével, valamint a vm.swap_idle_threshold1 és a vm.swap_idle_threshold2 változókon keresztül a kilapozás “reakcióidejének” alkalmas behangolásával a megszokottnál gyorsabban lenyomhatjuk az üresjáratban dolgozó programokhoz tartozó memórialapok prioritását, amivel a kilapozásokat vezérlő démon kezére játszunk. Azonban tényleg csak akkor engedélyezzük ezt a lehetőséget, ha valóban szükségünk van rá, mivel így a memóriát jóval előbb lapozzuk ki és ezzel több lapozóállományt és lemezteljesítményt emésztünk fel. Kisebb rendszerekben jól behatárolható a hatása, azonban a nagyobb rendszerekben, ahol már eleve visszafogott mértékű lapozás történik, ez a beállítás lehetővé teszi a virtuális memóriát kezelő alrendszer számára, hogy könnyedén ki- és be rakosgasson komplett futó programokat a memóriába.

11.12.1.5. hw.ata.wc

A FreeBSD 4.3 egyszer már kacérkodott az IDE-lemezek írási pufferének kikapcsolásával. Ez ugyan csökkentette az IDE-lemezek írási sávszélességét, azonban bizonyos merevlemezgyártók gondatlanságából eredő súlyos adatvesztések miatt szükséges volt a használata. A gond ezzel kapcsolatban ott van, hogy egyes IDE-meghajtók hazudnak az írások teljesítéséről. A lemezek írási gyorsítótárazásának bekapcsolásával az IDE-meghajtók nem csak az írások sorrendjét rendezik át, hanem nagyobb terhelés esetén egyes blokkokat jóval később is rögzítenek. Ezért a rendszer esetleges összeomlása vagy egy áramkimaradás súlyos károkat okozhat az állományrendszerben. A FreeBSD úgy döntött, hogy a megbízhatóságot választja. Sajnos ez olyan nagyságú teljesítményvesztést okozott, hogy a következő kiadásban már kénytelenek voltunk alapértelmezés szerint is visszakapcsolni ezt a lehetőséget. A hw.ata.wc nevű sysctl változó vizsgálatával ellenőrizhetjük a rendszerünkön érvényes alapértelmezett beállítást. Amennyiben az IDE írások gyorsítótárazása nem engedélyezett, akkor ezt a változó értékének 1-re állításával állíthatjuk vissza. Ezt a rendszer indításakor a rendszerbetöltőben tehetjük meg. A rendszermag indítása után ennek már nincs hatása.

A részleteket a ata(4) man oldalon tudhatjuk meg.

11.12.1.6. SCSI_DELAY (kern.cam.scsi_delay)

A rendszermag SCSI_DELAY nevű beállítása a rendszer indulásának idejét hivatott mérsékelni. Az alapértelmezett értéke viszonylag magas, innen származik a rendszer indítása során keletkező 15 másodperces csúszás. Általában az is megfelelő, ha ezt visszavesszük az 5 értékre (főleg a modernebb meghajtók számára). A FreeBSD újabb (5.0 vagy későbbi) változataiban ez az érték már a kern.cam.scsi_delay sysctl változó értékével is megadható a rendszer indításakor. Azonban ügyeljünk rá, hogy mind a finomhangoláshoz használt változó, mind pedig rendszermag beállítása ezredmásodpercben és nem másodpercben értelmezi ezt az értéket.

11.12.2. Soft Updates

A tunefs(8) nevű program használható az állományrendszerek finomhangolására. Nagyon sok opciót találhatunk benne, de itt most csak a “Soft Updates” ki- és bekapcsolásával foglalkozunk, amit a következő módon tehetünk meg:

# tunefs -n enable /allomanyrendszer
# tunefs -n disable /allomanyrendszer

Amíg egy állományrendszer csatlakoztatott állapotban van, addig nem módosítható a tunefs(8) paranccsal. A Soft Updates bekapcsolására ezért az a legalkalmasabb időpont, amikor egyfelhasználós módban vagyunk és még egyetlen partíciót sem csatlakoztattunk.

A Soft Updates beállítás engedélyezése a memóriában pufferelt gyorsítótáron keresztül jelentős mértékben fokozza a metaadatok teljesítményét, elsősorban az állományok létrehozását és törlését. A Soft Updates használatát ezért minden állományrendszer esetén ajánljuk. A Soft Updates alkalmazásának két rossz oldalára kell tekintettel lennünk. Először is a Soft Updates a rendszer összeomlása esetén ugyan garantálja az állományrendszer konzisztenciáját, de könnyen elképzelhető, hogy több másodperccel (vagy akár egy egész perccel!) hátrébb jár a fizikai lemez frissítésében. Másodszor a Soft Updates késlelteti az állományrendszer blokkjainak felszabadítását. Ha van egy olyan állományrendszerünk (mint például a rendszer indításához használt gyökér partíció), ami már majdnem betelt, akkor egy nagyobb frissítés, például a make installworld parancs kiadása, során az állományrendszer egyszerűen kifogy a helyből és így a frissítés meghiúsul.

11.12.2.1. Bővebben a Soft Updates működéséről

Két hagyományos megközelítés létezik az állományrendszerek metaadatainak visszaírására. (A metaadatok módosításakor olyan nem adatot tartalmazó blokkok változnak meg, mint például az állományokra vonatkozó információk vagy a könyvtárak.)

Eredetileg alapértelmezés szerint a metaadatok változásait szinkron módon írták ki. Amikor egy könyvtár megváltozott, a rendszer egészen addig várt, amíg ez a változás a lemezre nem íródott. Ugyanekkor az állományok adatait tartalmazó pufferek (az állományok tartalma) átkerültek a pufferelt gyorsítótárba, hogy majd később, aszinkron módon kerüljenek kiírásra. Ennek az implementációnak a biztonságos működés volt az előnye, mivel így a metaadatok még akkor is konzisztens állapotban maradtak, amikor valamilyen hiba következett be. Tehát egy állomány vagy teljesen létrejött vagy egyáltalán nem. Ha az állományhoz tartozó blokkok már nem tudtak kijutni a gyorsítótárból az összeomlás ideje előtt, akkor az fsck(8) felismerte ezt a helyzetet és az állományrendszer ilyen jellegű hibáját úgy orvosolta, hogy az adott állomány méretét nullára állította. Ezenkívül még az implementációs részletek is tiszták és egyszerűek maradtak. Ennek viszont hátránya, hogy a metaadatok kezelése lassú. Ha például kiadunk egy rm -r parancsot, akkor az a könyvtárban levő állományokat szekvenciálisan dolgozza fel, de minden egyes változtatást (az állományok törlését) csak szinkron módon rögzíti a lemezre. Ezek a frissítések érintik magát a könyvtárat, az állományokkal kapcsolatos információkat tároló táblázatot (az ún. inode táblát) és minden valószínűség szerint az állományok által lefoglalt blokkokat is közvetve. Hasonló megfontolások élnek a nagyobb könyvtárszerkezetek kibontása esetén is (tar -x).

A második lehetőség a metaadatok aszinkron frissítése. Ez az alapértelmezés a Linux ext2fs és BSD-k mount -o async opcióval csatlakoztatott UFS állományrendszerei esetén. Ilyenkor minden metaadattal kapcsolatos aktualizálás egyszerűen bekerült a pufferelt gyorsítótárba, tehát az állományok adatai és ezek a típusú frissítések keverednek. Ennek a megvalósításnak az az előnye, hogy nem kell megvárni, amíg a metaadatok is kiíródnak a lemezre, ezért a metaadatok óriási mennyiségű változásával járó műveletek sokkal gyorsabban hajtódnak végre, mint a szinkron esetben. Sőt, maga az implementáció is tiszta és egyszerű marad, ezért a kódban megjelenő hibák beszivárgásának kockázata alacsony. A módszer hátránya, hogy egyáltalán semmilyen garanciát nem kapunk az állományrendszer konzisztenciájára. Ha tehát egy rengeteg metaadat megváltozásával együttjáró művelet közben történik valamilyen probléma (áramkimaradás, vagy valaki egyszerűen megnyomja a reset gombot), akkor az állományrendszer előre kiszámíthatatlan állapotba kerül. A rendszer újbóli indításakor ezért nincs lehetőségünk megvizsgálni az állományrendszer állapotát. Elképzelhető, hogy az állományokhoz tartozó adatok már kikerültek a lemezre, miközben a rá vonatkozó inode- vagy könyvtári bejegyzések még nem. Így lényegében lehetetlen olyan fsck implementációt készíteni, ami képes lenne eltüntetni ezt a káoszt (hiszen az ehhez szükséges adatok nem állnak rendelkezésre). Ha az állományrendszer helyrehozhatatlanul károsodott, akkor csak a newfs(8) és a biztonsági mentés visszaállítása segíthet rajta.

Ezt általában úgy küszöbölik ki, hogy az egészhez hozzáteszik még a módosított területek feljegyzését, amit gyakran csak naplózásnak (journaling) neveznek, habár ezt az elnevezést nem mindenhol ilyen értelemben használják, ezért a tranzakciók naplózásának más formáira is utalhat. A metaadatok frissítése ebben az esetben is csak szinkron módon történik, de csak a lemez egy kisebb területére. Később ez a megfelelő helyére kerül. Mivel a lemez naplózásra fordított része egy viszonylag kis méretű, folytonos terület, a lemez fejének még a megterhelőbb műveletek esetén sem kell sokat mozognia, ezért valójában ez a megoldás gyorsabb, mint a mezei szinkron frissítések. Az implementáció bonyolultsága továbbra is jól behatárolható, a velejáró hibalehetőségek kockázata alacsony. Hátránya, hogy minden metaadat kétszer íródik ki (egyszer a naplózási területre, aztán a megfelelő helyre), ezért a hétköznapi használat során “visszaesés” tapasztalható a teljesítményben. Másrészről azonban egy összeomlás esetén a naplózási terület segítségével minden függőben levő metaadattal kapcsolatos művelet könnyen visszafordítható vagy lezárható a rendszer következő indításakor, így ezzel egy gyors helyreállítást nyerünk.

Kirk McKusick, a Berkeley FFS fejlesztője ezt a problémát a Soft Updates segítségével hidalta át: a metaadatokkal kapcsolatos minden függőben levő frissítést a memóriában tart, majd ezeket rendezett sorrendben írja ki a lemezre (“a metaadatok rendezett frissítése”). Ennek következményeképpen a metaadatok komolyabb frissítése során a később érkező módosításoknak lehetőségük van “elkapni” a memóriában levő korábbi változataikat, ha azok még nem kerültek ki a lemezre. Így az összes, például könyvtárakon végzett, művelet a lemezre írás előtt általában először a memóriában játszódik le (az adatblokkok a pozíciójuknak megfelelően kerülnek rendezésre, ezért a rájuk vonatkozó metaadatok előtt nem jutnak ki a lemezre). Ha eközben a rendszer összeomlik, akkor így implicit módon a “napló visszalapozását” eredményezi: minden olyan művelet, ami már nem tudott kijutni a lemezre, meg nem történtnek számít. Ezen a módon az állományrendszernek egy 30 és 60 másodperc közti korábbi állapota marad fenn. Az algoritmus garantálja, hogy az összes használt erőforrás a nekik megfelelő bittérképekben helyesen jelölődik, a blokkokban és az inode-okban. Az összeomlás után az erőforrások kiosztásával kapcsolatban csak egyetlen hiba léphet fel: amikor olyan erőforrások jelölődnek “használtnak”, amelyek igazából “szabadok”. Az fsck(8) azonban képes felismerni ezeket a helyzeteket és felszabadítani a nem használt erőforrásokat. A mount -f parancs kiadásával minden további következmény nélkül figyelmen kívül hagyhatjuk az állományrendszer félkész állapotát és csatlakoztathatjuk az állományrendszereket. A használatban már nem levő erőforrások felszabadításához az fsck(8) parancsot később kell futtatni. Ez az alapötlet húzódik meg a háttérben végzett lemezellenőrzés mögött. A rendszer indításakor az állományrendszernek csupán egy pillanatképét rögzítjük, és az fsck tényleges lefuttatását későbbre toljuk. Mivel mindegyik állományrendszer csatlakoztatható “félkész” állapotban, ezért a rendszer képes elindulni többfelhasználós módban. Eközben a háttérben az fsck beütemezhető minden olyan állományrendszer számára, ahol arra szükség van, hogy szabadítsa fel az esetlegesen már nem használt erőforrásokat. (Így a Soft Updates opciót nem alkalmazó állományrendszerek esetén továbbra is szükség van az előtérben elvégzett fsck parancsra.)

A módszer előnye, hogy így a metaadatokkal kapcsolatos műveletek közel olyan gyorsak, mint az aszinkron módon végzett frissítések (tehát gyorsabb, mintha naplóznánk, ami ugye minden metaadatot kétszer ír ki). A hátránya a bonyolultabb kód (ami miatt növekszik az olyan hibák lehetősége, amelyek érzékenyen befolyásolhatják a felhasználói adatok elvesztését) és a nagyobb memóriaigény. Ezenkívül még van néhány olyan egyéni jellemzője, amelyet meg kell szokni. A rendszer összeomlása után az állományrendszer valamivel “régebbi” lesz. Amikor pedig megszokott szinkron megközelítés szerint az fsck lefutása után nulla méretű állományok jönnének létre, ezek az állományok a Soft Updates esetén egyáltalán meg sem jelennek, mivel sem a rájuk vonatkozó metaadatok, sem pedig a tartalmuk nem került ki a lemezre. Egy rm lefuttatása után a lemezterület addig nem kerül felszabadításra, amíg a frissítések teljesen rá nem kerülnek a lemezre. Ez nagyobb mennyiségű adat telepítésekor gondokat okozhat egy olyan állományrendszeren, ahol nincs elegendő hely az állományok kétszeri tárolására.

Ha kérdése van a FreeBSD-vel kapcsolatban, a következő címre írhat (angolul): <freebsd-questions@FreeBSD.org>.
Ha ezzel a dokumentummal kapcsolatban van kérdése, kérjük erre a címre írjon: <gabor@FreeBSD.org>.