Wie kann eine vollständige Kopie des Inhalts eines btrfs-Dateisystems erstellt werden? Mit vollständiger Kopie meine ich nicht nur die aktuellen Daten , sondern auch verschiedene Subvolumes mit ihren Schnappschüssen , wobei ihre CoW-Strukturen idealerweise erhalten bleiben (dh keine Blöcke mit demselben Inhalt duplizieren.
Es scheint, dass eine Kopie auf Blockebene (wie mit dd
) keine gute Idee ist, da sie die UUID dupliziert und es anscheinend keine Möglichkeit gibt, sie einfach zu ändern .
Ich habe bis heute (06.05.2016) keine fertige Lösung gefunden, aber das Problem für meine Zwecke gelöst, einschließlich der Copy-on-Write-Behandlung. Die Schritte zu „klonen“
/source
zu/target
werden:Holen Sie sich eine Liste der Subvolumes, sortiert nach
ogen
:btrfs subvolume list -qu --sort ogen /source
. Das Sortieren reicht wahrscheinlich aus, um sicherzustellen, dass Snapshots oder Subvolumes, die von vorherigen abhängen, zuerst verarbeitet werden. Dies ist wichtig für den Umgang mit Copy-on-Write, da zuerst die Basisvolumes übertragen werden müssen.Machen Sie alle Subvolumes schreibgeschützt mit
btrfs property set -ts /source/some-volume ro true
.Führen Sie nun für jedes Teilvolumen aus der obigen Liste, beginnend oben, Folgendes aus:
Wenn das Volume keine übergeordnete UUID (angezeigt als
-
) hat oder die übergeordnete UUID nicht mehr in der Liste vorhanden ist, führen Sie Folgendes aus:btrfs send /source/some/volume | btrfs receive /target/some/
Wenn das Volume eine übergeordnete UUID hat, die noch vorhanden ist, sollten wir diese bereits übertragen haben,
--sort ogen
und wir können diese als Basis verwenden, um Datenverdopplungen zu vermeiden. Suchen Sie daher den Pfad der übergeordneten UUID in der Liste und führen Siebtrfs send -p /source/parent/volume/ -c /source/parent/volume/ /source/some/volume/ | btrfs receive /target/some/
Folgendes aus : (btrfs würde das-p
Argument wahrscheinlich automatisch erraten , aber ich bevorzuge es, explizit zu sein).Nachdem Sie einen der oben genannten Befehle ausgeführt haben, lassen Sie das Ziel und die Quelle erneut lesen und schreiben :
btrfs property set -ts /source/some/volume ro false; btrfs property set -ts /target/some/volume ro false
. Dieser Schritt kann übersprungen werden, wenn die Quelle zuvor schreibgeschützt war.Dies sollte viele Fälle behandeln. Vorsichtsmaßnahmen:
Beim Verschachteln von Subvolumes / Snapshots kann es zu Komplikationen bei der Reihenfolge kommen.
Der gesamte Prozess macht offensichtlich mehr Spaß, wenn Skripte erstellt werden.
btrfs send
akzeptiert mehrere clone source (-c
) Argumente. Es kann vorteilhaft sein, nicht nur den Datenträgerpfad des übergeordneten Datenträgers anzugeben, sondern auch den eines Vorfahren oder einfach eines zuvor gesendeten Datenträgers. Hier machte es keinen Unterschied, aber es könnte - nur eine Vermutung - in einigen Fällen helfen, Datenverdopplungen zu vermeiden.Ich bin mir nicht sicher, ob Metainformationen zu Snapshots oder Subvolumes auf dem Weg verloren gehen, aber fast alles, was für die meisten Anwendungsfälle interessant ist, sollte erhalten bleiben.
Der gesamte Prozess hat mir geholfen, ein 800-GB-Dateisystem mit 3,8 GB (entsprechend
df
) auf ein 10-GB-Image mit 3,8 GB zu übertragen. Die Übertragung ohne-p
und-c
hätte etwa 190 GB verbraucht, sodass eine Duplizierung der Daten tatsächlich vermieden wurde.quelle
ogen
bedeutet?ogen
ist die "Ursprungsgeneration" des Subvolumens. Ich muss zugeben, dass ich die Unterschiede nicht vollständig verstehe oder ob die Verwendung der (Nicht-Ursprungs-) Generation korrekt wäre, aber ich gehe davon aus, dass ein Test ergab, dass dies besser funktioniert hat (Vermeidung von Doppelarbeit). Die Generation scheint aktualisiert zu werden, wenn Snapshots basierend auf einem Subvolume erstellt werden, ogen nicht. Ich würde gerne etwas über einige Ergebnisse erfahren. Am besten überprüfen Sie das IRC oder die Btrfs-Mailingliste.Ich habe ein Python-Tool erstellt, das dies kann. Ich habe dies getan, weil ich den Ansatz von @Thomas Luzat sowohl in meiner eigenen als auch in der Implementierung von @Johannes Ernst ausprobiert habe und der verwendete Speicherplatz beim Klonen von 20 GB auf 40 GB verdoppelt wurde. Ich dachte, etwas effizienteres wäre nötig.
Betrachten Sie diesen allgemeinen Dateisystemverlauf:
Mit dem Algorithmus von Thomas würde "current" zuerst geklont, und alle Snapshots (Schnappschüsse früherer Zustände von "current") würden "current" als Klonquelle / übergeordnetes Element verwenden. Offensichtlich wäre es besser, snap3 auf snap4, snap2 auf snap3 usw. zu basieren.
Und das ist nur die Spitze des Eisbergs; Das Finden der "besten" Klonquellen (in Bezug auf Platzersparnis) in einem btrfs-Dateisystem mit einem komplexen Verlauf ist ein nicht triviales Problem. Ich habe 3 andere Strategien entwickelt, um dieses Problem zu lösen, die den Raum viel effizienter zu nutzen scheinen. Man hat tatsächlich zu Klongrößen geführt, die etwas unter der der Quelle liegen.
Sie können die Details auf der Github-Seite lesen, wenn Sie interessiert sind.
quelle
Es gibt eine ähnliche Frage auf unix.stackexchange.com , die auf partclone.btrfs verweist, aber ich kenne keine Einzelheiten dazu.
Es gibt auch eine Diskussion auf der Kernel-Mailingliste , die nicht wirklich vielversprechend aussieht ...
quelle
Mit
btrfs-send
, was ich zuletzt gesehen habe, schwebten immer noch experimentelle Patches auf der btrfs-Mailingliste herum.quelle