Ich erkläre es kurz. Ich habe zwei separate Untervolumes für Filme und Musik, die ich mit Senden/Empfangen auf einer anderen Festplatte sichere. Ich möchte die beiden Untervolumes zu einem zusammenführen (mit cp --reflink
) und dieses an das Sicherungslaufwerk senden, indem ich neu verknüpfte Dateien aus vorhandenen Snapshots klone.
Ich habe versucht, zu erstellen new_volume
, dann cp -rx --reflink "music" "movies"
hinein, dann:
btrfs send \
-c music-snapshot \
-c movies-snapshot \
new_volume-snapshot | btrfs receive /path/to/backup
aber es wird bemängelt, dass das übergeordnete Element für new_volume
(identifiziert durch ID) nicht ermittelt werden kann:
ERROR: parent determination failed for <id_number>
Natürlich sind music-snapshot
und movies-snapshot
im Backup vorhanden. Ich habe auch versucht, einen Snapshot movies
in zu machen new_volume
, dann cp -rx --reflink "music"
hinein, dann einen Snapshot und ihn mit zu senden btrfs send -c music-snapshot -p movies-snapshot new_volume-snapshot
, aber es scheint, dass das -c music-snapshot
keine Auswirkungen hat, die Daten werden trotzdem gesendet.
Ist das, was ich tun möchte, überhaupt möglich?
EDIT: Ich habe auch versucht, dies zu tun:
btrfs sub snap -r movies movies-A
btrfs sub snap -r music music-A
btrfs sub snap movies new_volume
btrfs sub snap -r new_volume new_volume-A
An diesem Punkt habe ich:
movies-A
music-A
new_volume-A (exact clone of movies-A)
Dann:
cp -rx --reflink music/* new_volume/
btrfs sub snap -r new_volume new_volume-B
movies-A
Wenn beide im Ziel vorhanden sind music-A
, kann ich letztendlich Folgendes tun:
btrfs send \
-p movies-A \
new_volume-A | btrfs receive /backup/
und das funktioniert immer einwandfrei (es werden fast keine Daten gesendet). Aber ...
btrfs send \
-p new_volume-A \
-c music-A \
new_volume-B | btrfs receive /backup/
Ich weiß nicht, wie ich es erklären soll: Bei „einigen Dateien“ music
funktioniert es, während es bei anderen weiterhin Daten sendet, als ob es die Quelle ignoriert hätte. Ich denke, dass diese Methode definitiv funktionieren SOLLTE, aber ich kann weder das „funktioniert“- noch das „funktioniert nicht“-Verhalten zuverlässig reproduzieren. Ich neige dazu zu glauben, dass irgendwo ein Fehler vorliegt. Könnte das jemand versuchen?
Antwort1
(HAFTUNGSAUSSCHLUSS: Der Kommentar von lgaudino legt nahe, dass der vorgeschlagene Ansatz zum Zusammenführen für btrfs-progs >= nicht mehr funktioniert.Version 5.14.2aufgrund geänderterbtrfs-EigenschaftVerhalten beim Ändern des schreibgeschützten Status eines Snapshots)
Was Sie wollen, kann erreicht werden, aber nicht direkt, weil btrfs send
(und btrfs receive
) ziemlich einfache Werkzeuge sind,Es gibt keine Möglichkeit, Snapshots durch die Angabe eines sekundären übergeordneten Snapshots zu einem einzigen Snapshot zusammenzuführen.aus dem Inneren der Werkzeuge.
Auf der Absenderseite ( btrfs send
)
btrfs send
AusgängeDateisystemOperationen auf Ebene (Verzeichnis-/Dateierstellung, Übertragung von Metadaten, Übertragung von Dateiinhalten usw.), die auf btrfs receive
der „Empfängerseite“ verwendet werden können, um einen entsprechenden Snapshot auf einem anderen btrfs-Dateisystem zu erstellen. Diese Operationen können durch einen „Trockenlauf“ überbtrfs receive --dump
.
Eininkrementellsend (eg btrfs send -p <parent> <snapshot>
) funktioniert im Übrigen genauso , mit der Ausnahme, dass nur die zum Erstellen bzw. Ändern (Hinzufügen/Entfernen von Verzeichnissen/Dateien, Aktualisieren von Metadaten) btrfs send
notwendigen Dateisystemoperationen aufgezeichnet werden.<snapshot>
<parent>
Es findet auch keine spezielle Überprüfung der „Eltern-Kind“-Beziehung statt. Vorausgesetzt, der -p
Parameter wird verwendet, um das „Elternteil“ anzugeben, btrfs send
werden einfach die erforderlichen Befehle generiert, um von diesem Snapshot zu einem anderen zu gelangen (der als „Kind“ fungiert). Dies würde sogar funktionieren, wenn die beiden Snapshots völlig unabhängig voneinander wären.
Auf der Sendeseite btrfs send
besteht die einzige Anforderung darin, dass alle Schnappschüsseschreibgeschützt. Nur lesbare Subvolumes/Snapshots werden normalerweise über die -r
Option inbtrfs subvolume snapshot -r <subvol> <snap>
, Obwohlbtrfs property set <snap> ro true/false
kann auch verwendet werden, um die Flagge nach der Erstellung zu ändern.
btrfs send
nimmt keinerlei Rücksicht darauf, was auf der Empfangsseite vorhanden ist oder nicht, was unvermeidlich ist, da zwischen den Seiten keine bidirektionale Kommunikation stattfindet, wie beispielsweise bei rsync
BTRFS, wo das Senden/Empfangen möglicherweise nicht einmal gleichzeitig ausgeführt wird, sondern jeweils zu unterschiedlichen Zeiten das Lesen aus einer Datei/das Schreiben in eine Datei ausgeführt wird.
Es kann nur einen Elternteil geben
Dermanpageund Alt)Wiki-FAQsind leider ziemlich verwirrend. Der Autor vonbtrfs-clone
behauptetdass btrfs senden und empfangen kann höchstens berücksichtigeneinsübergeordnetes Element für inkrementelle Übertragungen. Das übergeordnete Element kann entweder direkt -p
oder indirekt über eine oder mehrere -c
Optionen angegeben werden:
btrfs-send
ab btrfs-tools 4.13 wählt das übergeordnete Element für ein Subvolume S und einen Satz von gegebenen Klonquellen C_i ausso was:
- Wenn
-p
eine Option angegeben ist, verwenden Sie sie- Wenn S kein
parent_uuid
Set hat oder diese UUID nicht gefunden werden kann, aufgeben- wenn es
C_i
mit gibtC_i->uuid == S->parent_uuid
(das Untervolumen, von dem S ein Kind ist (Schnappschuss), nennen wir es "Mutter"), verwenden Sie es- wenn kein C_i das gleiche
parent_uuid
wie S hat, aufgeben- Wählen Sie aus allen C_i, die Kinder von „Mama“ sind, dasjenige aus, das der Generation
ctransid
„Mama“ am nächsten steht (was ist eigentlich der Unterschied zu „Generation“?).Beachten Sie, dassdas Wikiist etwas irreführend, da es suggeriert, dass
-c
„ohne“ sich von „mit“p
unterscheidet , obwohl dies normalerweise durch den obigen Algorithmus impliziert wird. Die einzige relevante Ausnahme ist das Senden von Untervolumes, die kein übergeordnetes Volume haben.-c
-p
-p
Zusammenfassend schlage ich vor, immer explizit einen Elternteil über anzugeben -p
und zu ignorieren -c
, btrfs receive
da es das Konzept „zwei Elternteile“ einfach nicht gibt.
Auf der Empfangsseite ( btrfs receive
)
Derbtrfs-receive
Die Manpage beschreibt den Zweck des Programms wie folgt:
Empfangen Sie einen Datenstrom von Änderungen und replizieren Sie ein oder mehrere Subvolumes, die zuvor von btrfs send generiert wurden
Bei einer vollständigen Übertragung wird ein neues Subvolume erstellt, bei einer inkrementellen Übertragung wird ein neuer Snapshot des (entspricht auf der Empfangsseite) Snapshots <parent>
erstellt. In beiden Fällen wird das neu erstellte Subvolume/der Snapshot zunächstlesen Schreibenerst nachdem der "Stream der Änderungen" btrfs send
erfolgreich angewendet wurde, dann wird das Subvolume/der Snapshot erstelltschreibgeschützt.
Offensichtlich gibt es keine Möglichkeit, zwei übergeordnete Elemente zu implementieren, da es im „Stream der Änderungen“ von vornherein keine Copy-on-Write/Reflink-Kopien gibt. Der Snapshot von <parent>
stellt lediglich die Basis dar, auf die der „Stream der Änderungen“ angewendet wird.
Aber wie stellt die empfangende Seite sicher, dass ihr <parent>
Schnappschuss mit dem Schnappschuss auf der sendenden Seite identisch ist <parent>
?prüft/vergleicht nie den tatsächlichen Inhaltder Snapshots/Subvolumes, sondern nutztUUIDMetadaten im Zusammenhang mit derUnveränderlichkeitAnnahme für den übergeordneten Snapshot.
btrfs subvolume show <subvolume>
liefert eine Ausgabe wie:
/mnt/btrfs/subvolume
Name: subvolume
UUID: 5e076a14-4e42-254d-ac8e-55bebea982d1
Parent UUID: -
Received UUID: -
Creation time: 2018-01-01 12:34:56 +0000
Subvolume ID: 79
Generation: 2844
Gen at creation: 2844
Parent ID: 5
Top level ID: 5
Flags: -
Snapshot(s):
Jedes Subvolume/jeder Snapshot hat drei UUID-Slots, von denen zwei leer sein können. Jeder von erstellte Snapshot btrfs subvolume snapshot
hat immer einen Parent UUID
, der seinen übergeordneten Snapshot eindeutig identifiziert, und jeder von erstellte Snapshot btrfs receive
hat immer einen Received UUID
Eintrag. Wenn es sich um eine vollständige Übertragung handelte, hat es keinen Parent UUID
Eintrag, wenn es sich um eine inkrementelle Übertragung handelte, hat es sowohl einen Received UUID
Eintrag als auch einen Parent UUID
Eintrag. UUID-Einträge können vom Benutzer nicht manuell geändert werden.
Diese IDs reichen aus, um btrfs receive
festzustellen, ob es einen <parent>
Snapshot auf der Empfangsseite gibt, dersollenmuss vollständig identisch mit dem Snapshot der "Sendeseite" sein <parent>
, da er Received UUID
mit der UUID des übergeordneten Elements der Sendeseite identisch sein sollte, wodurch sichergestellt wird, dass er von diesem erstellt wurde, und der schreibgeschützte Status aller beteiligten Snapshots bedeutet, dass essollte nichtHat es in der Zwischenzeit Änderungen gegeben?
(Randbemerkung: Obwohl nur eine Seite der beiden übergeordneten Datenträger den Eintrag „Received UUID“ enthält, scheint das Senden/Empfangen von btrfs intelligent genug zu sein, um diese Metadaten im „Änderungsstrom“ bereitzustellen, sodass beide Seiten/Dateisysteme je nach Benutzerbedarf potenziell als „Sende-“ oder „Empfangsseite“ fungieren können.)
So führen Sie zwei Subvolumes/Snapshots zusammen (< v5.14.2)
Wie wir gesehen haben, ist das Zusammenführen mit only nicht möglich, btrfs send/receive
manuell lässt es sich jedoch relativ einfach durchführen, vorausgesetzt, man möchte movies
und music
unter einem neuen Untervolume kombinieren unified
und vorausgesetzt, movies
und music
werden auch auf der Empfangsseite vollständig gespiegelt:
- Erstellen Sie auf der Sendeseite ein neues (leeres) Subvolume:
btrfs subvolume create unified
- Ändern Sie es in schreibgeschützt:
btrfs property set unified ro true
- Senden Sie es zur Sicherung:
btrfs send /path/to/unified | btrfs receive /receiving/side/
- Nur Lesen deaktivierenauf beiden Seiten, zB
btrfs property set /path/to/unified ro false
für die sendende Seite - Manuell
--reflink
den Inhalt vonmusic
undmovies
zuunified
auf beiden Seitencp -a --reflink /path/to/music /path/to/movies /path/to/unified/
- Satzbeidseitig's
unified
Snapshots wieder schreibgeschütztbtrfs property set /path/to/unified ro true
- Erstellen Sie einen neuen Lese-/Schreib-Snapshot von
unified
zur Interaktion, derunified
als übergeordneter Snapshot für zukünftige inkrementelle Übertragungen fungiert.beide Seiten.
Anstatt ein neues/leeres Subvolume zu erstellen und zu senden, hätte man auch einfach bei Schritt 4 mit einem bereits vorhandenen music
oder movies
Snapshot beginnen können. Aus der Sicht von btrfs ist das Einzige, was zählt, dass die (zukünftigen) übergeordneten Elemente der beiden Seiten über das Zeigen einer Seite Received UUID
auf die andere verbunden sind und beide bei zukünftigen Übertragungen nur gelesen werden können.
Was ist zu tun für >= v5.14.2
Deram wenigsten schlechte Lösungist es wahrscheinlicher, dem Ansatz im vorherigen Abschnitt zu folgen, aber zusätzlich den Received UUID
Wert manuell zurückzusetzen überpython-btrfs
nachdem es von aufgehoben wurde btrfs-properties
.
Es gibt keinGutLösung mit nur den Standardwerkzeugen btrfs-progs
. Das, was einer „Lösung“ am nächsten kommt, ist vielleicht die Nutzung derTatsachedass der während erstellte Snapshot btrfs receive
schreibgeschützt ist, bis die Übertragung abgeschlossen ist, und wir versuchen, unsere --reflink
Kopien zu erstellen, bevor der Snapshot auf schreibgeschützt gesetzt wird btrfs-receive
. Mit anderen Worten, die Ausnutzung einesRennbedingungist derzeit die einzige Möglichkeit, dies nur mit den Standardtools von btrfs-progs >=5.14.2 zu tun.
Was jedoch offensichtlich wirklich nötig ist, ist, dass jemand beim btrfs-Projekt eine Funktionsanforderung stellt, um zumindest das Zusammenführen zu ermöglichen, wie es vor 5.14.2 für Leute möglich war, die wissen, was sie tun.
Ein Exploit des Race Condition würde wahrscheinlich etwa so aussehen: Da wir den schreibgeschützten Status eines Snapshots auf der sendenden Seite immer noch ändern können, könnten wir den Snapshot ändern, z. B.
verwenden movies
und eine Kopie mit einem Reflink music
einfügen:
btrfs property set -f movies ro false
cp -a --reflink /path/to/music /path/to/movies/
btrfs property set -f /path/to/movies ro true
btrfs subvolume snapshot /path/to/movies /path/to/unified_prep
Falls erforderlich, können wir jetzt Verzeichnisse und Dateien darin verschieben unified_prep
(das Musikverzeichnis jedoch unverändert lassen) und dann, wenn Sie bereit sind:
btrfs subvolume snapshot -r /path/to/unified_prep /path/to/unified
btrfs send -p /path/to/movies /path/to/unified | btrfs receive /path/to/backups/
btrfs send
und btrfs receive
solltenichtgreifen Sie auf das zusätzliche Musikverzeichnis zurück, da es sowohl movies
(auf der Sendeseite) als auch unified
(auch auf der Clientseite) vorhanden ist. Wenn wir es nun cp -a --reflink /bkp/to/music /bkp/to/unified/
auf der Empfangsseite(!) schaffen, während der neue unified
Snapshot noch übertragen wird und somit lesbar und beschreibbar ist, sollten sowohl das Subvolume auf der Sendeseite unified
als auch sein Snapshot auf der Empfangsseite identisch sein und wir haben die Subvolumes erfolgreich zusammengeführt.