Frage zu ZFS snapshots "in die Vergangenheit"

thorsten

Member
Moin zusammen,

ich beschäftige mich gerade mit dem ZFS:

Wenn ich das richtig verstanden habe, werden durch die copy-on-write Methode (CoW) Dateien niemals überschrieben, sondern die Änderungen in einen neuen Block geschrieben.
Ist die Datei kleiner als der Block (4k) dann wird sie eben komplett neu geschrieben - bei jeder Änderung!
Mache ich jetzt einen Snapshot "merkt" sich ZFS einfach den aktuellen Block in dem die Datei steht und macht ja nicht wirklich noch eine Kopie davon.
Ich kann via /dataset/.zfs/snapshot auf die Snapshot zugreifen, kann ja auch in die Datei hineinschauen, weil es ist ja nur eine Referenz auf einen alten Block.
Mache ich einen Rollback von diesem Snapshot wird einfach nur der "alte" Block aus dem Snapshot als aktueller Block markiert, ohne die Datei wirklich irgendwo hinzukopieren.

Richtig soweit?

Jetzt zu meiner "kruden" Frage:
Mal angenommen ich habe eine 2 TB Platte, auf der nur eine (1) Datei mit 4 kb (also 1 Block) geschrieben ist.
Auch wenn ich keine Snapshot mache, existieren ja trotz täglicher Änderung dieser Datei alle Versionen dieser Datei, da die ZFS Blöcke durch CoW ja "nie" über schrieben werden.
(In diesem Fall erst bei der 500 Mrd 'sten Kopie)
Ich kann nur nicht darauf referenzieren, weil ich keine Snapshot gemacht habe, aber ZFS weis ja selbst welche Blöcke es beschrieben hat.

Jetzt müsste es ja rein theoretisch möglich sein, einen Snapshot in die Vergangenheit zu machen, also ZFS anweisen eine Referenz auf alle Blöcke zu erstellen, die vorgestern geändert wurden (In diesem einfachen Fall wäre es ja nur einer).

Mache ich einen Denkfehler? Oder geht das am Ende sogar und ich weis es nur nicht?

Ist mir klar, bei einem Dataset mit tausenden von Dateien können da komische Sachen bei rauskommen.

Auto-Snapshot sind mir bekannt, es steckt jetzt auch kein Anwendungsfall dahinter, es geht mir mehr ums Verständnis.

Vielen Dank & Gruß

Thorsten
 
Du meinst sowas wie Datum mit date aendern, snapshot erstellen und Datum wieder auf das korrekte Datum stellen? Habe ich noch nicht versucht und weiss daher nicht, ob zfs ueberhaupt date nutzt. Ist jedenfalls eine interessante Frage.
 
Moin midnight,

ja so halb. Ich möchte das Datum vorher nicht ändern, im schlimmsten Falle weis ich ja gar nicht wann welcher Block geändert wurde, das weis nur ZFS.
Ich sags mal mit SQL: Select * from all_blocks where "Änderungsdaum" <= "vorgestern"

und wenn das valid is dann: Create table "snapshot" as select * from all_blocks where "Änderungsdatum" <= "vorgestern"

(In Wahrheit wäre das SQL komplizierter weil ich zu der Datei alle Blöcke haben müsste die nur einmal (initial) geschrieben wurden und nur die, die vorgestern geändert wurden)

Gruß
 
Zuletzt bearbeitet:
hm...

vielleicht ist das SQL Beispiel doof! Also mal anders erklärt:

Mache ich einen Snapshot steht der im Verzeichnis /dataset/.zfs/snapshot/dataset@mein_snapshot_vorgestern, die Blöcke sind vom ZFS als ro markiert und ich kann lesend drauf zugreifen, sowie einen Rollback machen

Diesen Snapshot habe ich aber nicht gemacht, also gibt es das so nicht.
Aber in meiner verrückten Vorstellung gibt es so eine art "dark_snapshot" der wie folgt zu finden sein könnte:

/dataset/.zfs/.dark_snapshot/dataset@darksnapshot_heute
/dataset/.zfs/.dark_snapshot/dataset@darksnapshot_gestern
/dataset/.zfs/.dark_snapshot/dataset@darksnapshot_vorgestern
/dataset/.zfs/.dark_snapshot/dataset@darksnapshot_vorvorgestern ... usw.

In meinem Fall von oben müssten ja alle Änderungen vorhanden sein und ich könnte ja, wenn es das denn gäbe, sogar in die Dateien hineinschauen, mir eine aussuchen, und mit einem "create Magic" diesen ausgesuchten

/dataset/.zfs/.dark_snapshot/dataset@darksnapshot_vorgestern

in

/dataset/.zfs/snapshot/dataset@mein_snapshot_vorgestern

wandeln, auf dem ich dann einen Rollback machen kann.

(Ist klar, in echten leben hätte ich viele und auch große Dateien, wo die "alten" Blöcke vielleicht teilweise schon wieder überschrieben sind, weil sie ja nicht von snapshot auf ro gesetzt wurden. Im Idealfall wüsste ZFS dann sogar, welche Versionen valide wiederhergestellt werden könnten)

... alles nur Theorie!?
 
Auch wenn ich keine Snapshot mache, existieren ja trotz täglicher Änderung dieser Datei alle Versionen dieser Datei, da die ZFS Blöcke durch CoW ja "nie" über schrieben werden.
(In diesem Fall erst bei der 500 Mrd 'sten Kopie)
Das bezweifle ich. CoW bedeutet ja nur, dass beim Schreiben der Block von vor dem Schreibvorgang erhalten bleibt. Nach dem Schreibvorgang hat dieser Block keine Relevanz mehr und wird dann sicherlich invalidiert. Man könnte das ganze also abwechselnd mit den selben 2 4k-Blöcken machen und hätte dennoch CoW.

Rob
 
Moin Rob,

ja, die Überlegung hatte ich auch schon, aber ZFS schaut m.W.n. auch auf die MTBF und ist dadurch besonders gut geeignet um die Lebensdauer von SSDs zu erhalten. Somit weis ZFS welchen Block es wie oft beschrieben hat und nimmt, solange vorhanden, immer neue Blöcke, oder eben die, die seltener beschrieben wurden...
... sicher bin ich mir aber nicht!

Edith: Nee, das weis die SSD selbst, aber da ZFS immer nur die geänderten Blöcke neu schreibt anstatt der ganzen Datei ist es besonders gut geeignet...

VG
 
Zuletzt bearbeitet:
Jetzt müsste es ja rein theoretisch möglich sein, einen Snapshot in die Vergangenheit zu machen, also ZFS anweisen eine Referenz auf alle Blöcke zu erstellen, die vorgestern geändert wurden
Das unterstellt ja, das es ein Zeitpunkt gibt. Sprich das man irgendwie im nachhinein rauskriegen kann, wann welcher Block wie referenziert war. Bei einem echten Snapshot ist das ja klar und man markiert einfach nur die Blöcke, die zum Zeitpunkt des Snapshots "aktiv" waren. Diese zeitliche Information hast Du aber im nachhinein nicht mehr. Es müsste ja irgendwo hinterlegt sein, wann welcher Block beschrieben wurde, um das in die Vergangenheit hinein zu rekonstruieren.

Ich kenne mich jetzt nicht detailliert in den ZFS-Datenstrukturen aus. Aber so mal als lose Idee zum ansetzen würde ich gar nicht direkt auf die Blöcke schauen (das da eine zeitliche Information hinterlegt ist würde ich bezweifeln), sondern in die Transaktionen. Ich weiß nur nicht, wie lange die erhalten bleiben. Um einzelne Dateien zu recovern kann man das sicher mal machen/versuchen. Aber ob das dazu taugt in zuverlässiger Weise einen Vergangensheits-Snapshot zu erstellen, das würde ich spontan erst mal verneinen (schon allein aus dem simplen Grund, das "nicht referenzierte" Blöcke als "frei" gelten und man mit einer erneuten Belegung rechnen muss und man sich nicht darauf verlassen kann, das ein bisher unbenutzter Block belegt wird).
 
Zuletzt bearbeitet:
Es müsste ja irgendwo hinterlegt sein, wann welcher Block beschrieben wurde, um das in die Vergangenheit hinein zu rekonstruieren.
... genau das ist die Frage, und ob man da irgendwie mit get "Hidden_value" drankommt
sondern in die Transaktionen. Ich weiß nur nicht, wie lange die erhalten bleiben.
... das wäre ja noch besser, da könnte man gleich sehen, ob das valide wiederherstellbar ist
Aber ob das dazu taugt in zuverlässiger Weise einen Vergangensheits-Snapshot zu erstellen, das würde ich spontan erst mal verneinen.
... na ja, wer es zuverlässig haben will soll snapshot erstellen! :belehren:

Wie gesagt ich spiele in einem dedizierten Lab da gerade mit rum und wie man am besten datasets plant und die auto_snapshots dazu, immer mit dem "was wäre wenn ...", und da kam mir der Gedanke

VG

Thorsten
 
... genau das ist die Frage, und ob man da irgendwie mit get "Hidden_value" drankommt

nein, denn es wird kein Log geführt, wann was mal aktuell war ... wenn man das weiter überlegt, wäre dieses Log ggf auch größer als das Dataset selber; quasi wie ein Datenbank-Index, welcher größer ist, als die Datenbank selber...

... das wäre ja noch besser, da könnte man gleich sehen, ob das valide wiederherstellbar ist

du kannst dir die noch vorhandenen "transaction groups (txg)" auflisten lassen (mit zdb, die Parameter hab ich grad nicht im Kopf parat), du könntest dann den Pool exportieren, und mit einer dieser txg wieder reimportieren, dann wäre der Stand wie zu dem Zeitpunkt der txg - hatten wir hier im Forum schon mal bei einem Pool-Rettungs-Thread;

... na ja, wer es zuverlässig haben will soll snapshot erstellen! :belehren:
richtig!
dann hast mit der Zeit auch "snapshots in die Vergangenheit"
du kannst pro dataset 2^64 Snapshots erstellen - es spricht nichts gegen ein Skript, was sekündlich nen Snap erstellt - wobei hier die Performance dann vermutlich doch mal leidet (habs selber noch nicht ausprobiert), kleinste Einheit je waren 15 Minuten
 
nein, denn es wird kein Log geführt, wann was mal aktuell war ... wenn man das weiter überlegt, wäre dieses Log ggf auch größer als das Dataset selber; quasi wie ein Datenbank-Index, welcher größer ist, als die Datenbank selber...
... ich hatte auch nicht an ein Log gedacht, sondern dass das irgendwie an dem Block "dransteht", so mit Parent /child und timestamp Informationen
du kannst dir die noch vorhandenen "transaction groups (txg)" auflisten lassen (mit zdb, die Parameter hab ich grad nicht im Kopf parat), du könntest dann den Pool exportieren, und mit einer dieser txg wieder reimportieren, dann wäre der Stand wie zu dem Zeitpunkt der txg - hatten wir hier im Forum schon mal bei einem Pool-Rettungs-Thread;
... eines der nächsten Themen...

nun ja, hat Spaß gemacht dieses "Brainstorming" und mir gezeigt, dass ich zumindest einige grundlegende Prinzipien von ZFS verstanden habe.

Vielen Dank & Gruß

Thorsten
 
... ich hatte auch nicht an ein Log gedacht, sondern dass das irgendwie an dem Block "dransteht", so mit Parent /child und timestamp Informationen
naja, aber...
... wenn man zu jedem Zeitpunkt so Sachen wie parent/child und timestamp mit aufschreibt (mitloggt?) - was ist das dann denn anderes als: ein Log?? :)
 
ZFS liegt bei Beginn Block 0 - 8478674378347 schlagmichtot als 'frei' direkt vor. Es ist nicht so, dass die fein säuberlich und geordnet von 0 an beschrieben werden, sondern ZFS 'rotzt' sozusagen zufällig in einen freien Bereich (und den findest du ohne snapshot nicht, da wie gesagt nicht mehr referenziert ohne), aber zusammengehörige Blöcke dennoch nah beieinander. Dieses spreading begünstigt die gleichmäßige Auslastung aller devices des/r vdev(s) sowie geringe Latenz. Das ist auch der Grund, warum es ab 80% Füllstand immer langsamer wird...es dauert länger, freie Blöcke zum Beschreiben zu finden. Wichtig und immer wieder vorkauen sollte man in dem Zusammenhang auch, dass die Fragmentierung im pool irrelevant ist, da in Ecken des Internets doch immer mal wieder die Frage aufkommt, wieso man ZFS denn nicht defragmentieren kann. Das bezieht sich rein auf die freien Blöcke (Löcher im Käse :) ), die im Laufe des poollebens entstehen, wenn man mal alte Dateien löscht. Klassisches defrag gibts daher nicht. Wen es stört, der kann sein vdev growen, noch eins draufsatteln und wen es autistisch bis ins Mark stört, der muss den pool in einen neuen reinschreiben.
 
... ich hatte auch nicht an ein Log gedacht, sondern dass das irgendwie an dem Block "dransteht", so mit Parent /child und timestamp Informationen
Das da an einem Block ein timpstamp (last-write-time) dran steht, würde ich erstmal verneinen. Wozu auch? Auf Dateiebene hat man sowas natürlich und kennt es auch. Aber auf Blockebene macht es wenig Sinn.
 
Was du glaube ich auch noch falsch im Kopf hast: ZFS kennt nur eine maximale Blockgröße (default 128k). Erstellst du eine Datei < dieser, wird die Blockgröße quasi auf Dateigröße verringert (nicht ganz, es muss noch zu den HW Blöcken der HDs passen und raidz ist nochmal bisschen was anderes).

Zur Snapshothäufigkeit: Du kannst quasi beliebig viele Snapshots machen. Ich hab zur Absicherung gegen Verschlüsselungstrojaner und Co. z.b auf unsrem Fileserver in der Firma (12TB, ca ein delta von 100-200GB/Tag) Snapshots alle 5 Minuten aktiv, lösche die erst nach ner Woche und stündliche lass ich sogar 2 Wochen. Und ja, das ist natürlich nur EIN Baustein im Schutzkonzept gegen diese Art von Angriffen.
 
Zurück
Oben