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