Dies ist ein Posting von Jörg Wunsch, seines Zeichens FreeBSD-Entwickler und Unix-Guru, in die Newsgruppe de.comp.os.unix.bsd. Seine Erklärung von Filesystemen und Softupdates hat mir so gut gefallen, daß ich sie hier ins Web stellen möchte.
From: j@ida.interface-business.de (Joerg Wunsch) Newsgroups: de.comp.os.unix.bsd Subject: Re: Journaling-Filesysteme? Date: Mon, 7 Jan 2002 11:02:41 +0000 (UTC) Message-ID: <a1bv8h$2kpk$1@innocence.interface-business.de> Reply-To: joerg_wunsch@interface-systems.de (Joerg Wunsch) sascha <SaschaSchaefer@t-online.de> schrieb: > SGI verteilt in seinem Filesystem die inode-Daten und bekommt so > Speed. Sie verkaufen Dir das als die neueste Technologie... Dabei ist das uralt. Berkeley FFS hat dies mal erfunden -- und ist just das, was Du heutzutage überall aus UFS serviert bekommst. inodes werden pro cylinder group gehalten, eben aus diesem Grunde. ext2fs ist vom Grundsatz her auch ziemlich ein (re-implementiertes) UFS, macht es also genauso. > Einen fsck im Hintergrund durchzufuehren halte ich auch fuer eine > schlechte Idee. Bei der RedHat habe ich damit auch schon ein System in > den Schlaf versetzt. Eine schlechte Implementierung heißt doch noch lange nicht, daß die Idee schlecht ist. Sie funktioniert im Gegenteil erwiesenermaßen ausgezeichnet bei UFS + Softupdates, wenn man sich an die Randbedingungen hält (im Wesentlichen das Abschalten des write caches der Festplatte, was leider aber bei billigen IDE-Platten zu heftigen Performanceeinbußen führen kann -- SCSI ist dank funktionierenden tagged command queuings von diesen Einbußen kaum geplagt). Nur wie schon geschrieben, background fsck ist leider nur in FreeBSD-current drin. > Die Sache mit den Softupdates habe ich noch nicht verstanden. > Ich mache Softupdates. Die sind aber auch mit Vorsicht zu geniessen. Nein, sie sind wirklich stabil. Die Idee der Softupdates ist (vereinfacht gesagt): es gibt zwei klassische Herangehensweisen, wie man die Metadaten des Dateisystems (also Updates in die i-node Bereiche oder in Verzeichnisse) auf die Platte zurückschreibt. Das historisch völlig normale Verhalten waren synchrone Updates der Metadaten, d. h. wenn eine Änderung an einem Verzeichnis nötig war, wurde anschließend gewartet, bis diese Änderung zurückgeschrieben worden ist. Die eigentlichen Datei/daten/ wurden natürlich sehr wohl im buffer cache zwischengespeichert und asynchron irgendwann zurückgeschrieben. Der Vorteil dieser Implementierung ist, daß sie sehr sicher funktioniert. Wenn mitten in einem Update ein Ausfall erfolgt, haben die Metadaten immer einen konsistenten Zustand. Eine Datei ist entweder komplett angelegt oder gar nicht. Wenn die Datenblöcke zur Datei den Weg aus dem buffer cache noch nicht auf die Platte gefunden haben, dann kann das fsck dies feststellen und den Zustand reparieren (Dateilänge wird dann auf 0 gesetzt). Außerdem ist die Implementierung einfach und überschaubar. Nachteil ist, daß Änderungen der Metadaten sehr langsam vor sich gehen. Ein rm -r beispielsweise faßt alle Dateien eines Verzeichnisses der Reihe nach an, aber jede dieser Änderungen am Verzeichnis (Löschen einer Datei) wird einzeln synchron auf die Platte geschrieben. Gleiches beim Auswickeln großer Hierarchien (tar -x). Zweiter Fall sind asynchrone metadata Updates. Das ist z. B. der Standard bei Linux/ext2fs oder die Variante -o async für *BSD ufs. Man schickt die Updates der Metadaten einfach auch noch über den buffer cache, sie werden also zwischen die Updates der normalen Daten mit reingeschoben. Vorteil ist, daß man nun nicht mehr auf jeden Update warten muß, geht also viel schneller. Auch hier ist die Implementierung sehr einfach und wenig anfällig für Bugs. Nachteil ist, daß keinerlei Konsistenz des Dateisystems mehr gesichert ist. Wenn mitten in einer Operation, die viele Metadaten anfaßt (rm -r oder tar -x) ein Ausfall erfolgt (Stromausfall, Reset-Taster), dann herrscht anschließend Chaos auf dem Dateisystem. Niemand kann genau sagen, was denn geschrieben worden ist und was nicht; die Datenblöcke einer Datei können schon auf der Platte stehen, obwohl es die Updates der i-node Tabelle oder des zugehörigen Verzeichnisses noch nicht geschafft haben. Man kann praktisch kein fsck mehr implementieren, das dieses Chaos wieder beräumen kann (da die dazu nötigen Informationen schlicht auf der Platte fehlen). Der historische Ausweg aus dem Chaos war ein `dirty region logging'. Man schreibt die Metadaten-Updates zwar synchron, aber nur in eine logging area. Von da aus werden sie dann asynchron auf ihre eigentlichen Bereiche verteilt. Da die logging area ein kleines zusammenhängendes Stückchen ist, hat man bei massiven Operationen auf Metadaten keine allzugroßen Wege der Schreibköpfe der Platte zurückzulegen, so daß alles ein ganzes Stück schneller geht, als bei klassischen synchronen Updates. Die Komplexität der Implementierung hält sich auch in Grenzen, damit die Anfälligkeit gegenüber Bugs. Als Nachteil ergibt sich, daß Metadaten zweimal auf die Platte geschrieben werden müssen (einmal logging region, einmal an die richtige Stelle), so daß das Filesystem im Falle regulärer Arbeit (also keine gehäuften Metadatenoperationen) eine ,,Pessimisierung'' des Falls der synchronen Updates ist, es wird alles langsamer. Dafür hat man als Vorteil, daß im Falle des Crashes der konsistente Zustand dadurch erzielbar ist, daß die angefangenen Operationen aus dem dirty region log entweder zu Ende ausgeführt werden oder komplett verworfen -- es geht schneller, als ein volles fsck. Der Ausweg von Kirk McKusick (dem Schöpfer von Berkeley FFS) nun waren Softupdates: die notwendigen Updates der Metadaten werden im Speicher gehalten und dann sortiert auf die Platte geschrieben (`ordered metadata updates'). Dadurch hat man den Effekt, daß im Falle massiver Metadaten-Operationen die nächste Operation den vorhergehenden, noch nicht auf die Platte geschriebenen Update im Speicher ,,einholt''. Alle Operationen auf einem Verzeichnis werden also in der Regel noch im Speicher abgewickelt, bevor der Update überhaupt auf die Platte geschrieben wird. (Die dazugehörigen Datenblöcke werden natürlich auch so sortiert, daß sie nicht vor ihren Metadaten auf der Platte sind.) Im Crashfall nun hat man ein implizites `log rewind': alle Operationen, die noch nicht den Weg auf die Platte gefunden haben, sehen danach so aus, als hätten sie nie stattgefunden. Man hat also den konsistenten Zustand von ,,ein wenig früher'' garantiert. Laut Kirk McKusick ist dabei vom Algorithmus her garantiert, daß alle tatsächlich benutzten Ressourcen auch in den entsprechenden Bitmaps bzw. i-node Tabellen als belegt markiert sind. Es kann lediglich vorkommen, daß Ressourcen noch als belegt markiert waren, die gar nicht mehr tatsächlich belegt sind. Nur um diesen Zustand zu bereinigen, ist jetzt noch ein fsck nötig. Dieses fsck darf man aus diesem Grunde auch ignorieren (mount -f), man hält dann eben noch Ressourcen alloziert, die eigentlich frei sind und sollte dafür später noch ein fsck nachholen. Das ist die ganze Idee dann des background fsck: am Anfang wird lediglich ein Snapshot des Filesystems gemacht um später einen Aufsetzpunkt für das fsck zu haben. Das kann dann später im Hintergrund laufen und gibt danach die ggf. nicht mehr benötigten Ressourcen frei. Der Vorteil ist, daß die Metadaten-Operationen beinahe so schnell laufen wie im asynchronen Fall (also durchaus auch schneller als beim `journalling', das ja die Metadaten immer zweimal schreiben muß; daher reagieren die Leute hier in der Gruppe immer etwas säuerlich, wenn jemand nach JFS schreit und Softupdates als ,,nicht relevant'' abtun will). Als Nachteil stehen dem die Komplexität des Codes und ein erhöhter Speicherverbrauch entgegen. Außerdem muß man sich an paar Eigenheiten gewöhnen, wie die Tatsache, daß nach einem Absturz ein etwas älterer Stand auf der Platte ist (also z. B. statt der leeren aber bereits angelegten Datei keine Spur der entsprechenden Datei mehr zu sehen ist) sowie daß der Platz nach rm -r nicht sofort als wieder verfügbar markiert werden kann sondern erst dann, wenn der Update dann auch auf die Platte vermittelt worden ist. > Mit dem tunefs gibt es da auch noch die Option auf Speed und nicht > Platz zu Optimieren. Das ist aber was ganz anderes und braucht Dich auch nicht berühren. Das bestimmt nur die Art und Weise, wann Fragmente (von Blöcken) angelegt werden. Da Du ja ext2fs gewohnt bist, das gar keine Fragmente kennt, kannst Du wohl mit dem Standard (`optimized for speed') gut und gern immer leben. ;-) Zwischen beiden Varianten wird auch automatisch umgeschaltet, wenn der Filesystemcode feststellt, daß das nötig ist. Das passiert in 99 % aller Fälle wohl nur bei klassischen Newsspool-Filesystemen mit ihren vielen kleinen Dateien. -- J"org Wunsch "Verwende Perl. Shell will man koennen, dann aber nicht verwenden." Kristian Koehntopp, de.comp.os.unix.misc