Auf der Absenderseite ( btrfs send)

Auf der Absenderseite ( btrfs send)

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-snapshotund movies-snapshotim Backup vorhanden. Ich habe auch versucht, einen Snapshot moviesin 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-snapshotkeine 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-AWenn 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“ musicfunktioniert 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 sendAusgängeDateisystemOperationen auf Ebene (Verzeichnis-/Dateierstellung, Übertragung von Metadaten, Übertragung von Dateiinhalten usw.), die auf btrfs receiveder „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 sendnotwendigen Dateisystemoperationen aufgezeichnet werden.<snapshot><parent>

Es findet auch keine spezielle Überprüfung der „Eltern-Kind“-Beziehung statt. Vorausgesetzt, der -pParameter wird verwendet, um das „Elternteil“ anzugeben, btrfs sendwerden 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 sendbesteht die einzige Anforderung darin, dass alle Schnappschüsseschreibgeschützt. Nur lesbare Subvolumes/Snapshots werden normalerweise über die -rOption inbtrfs subvolume snapshot -r <subvol> <snap>, Obwohlbtrfs property set <snap> ro true/falsekann auch verwendet werden, um die Flagge nach der Erstellung zu ändern.

btrfs sendnimmt 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 rsyncBTRFS, 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 -poder indirekt über eine oder mehrere -cOptionen angegeben werden:

btrfs-sendab btrfs-tools 4.13 wählt das übergeordnete Element für ein Subvolume S und einen Satz von gegebenen Klonquellen C_i ausso was:

  1. Wenn -peine Option angegeben ist, verwenden Sie sie
  2. Wenn S kein parent_uuidSet hat oder diese UUID nicht gefunden werden kann, aufgeben
  3. wenn es C_imit gibt C_i->uuid == S->parent_uuid(das Untervolumen, von dem S ein Kind ist (Schnappschuss), nennen wir es "Mutter"), verwenden Sie es
  4. wenn kein C_i das gleiche parent_uuidwie S hat, aufgeben
  5. 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“ punterscheidet , 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 -pund zu ignorieren -c, btrfs receiveda es das Konzept „zwei Elternteile“ einfach nicht gibt.

Auf der Empfangsseite ( btrfs receive)

Derbtrfs-receiveDie 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 senderfolgreich 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 snapshothat immer einen Parent UUID, der seinen übergeordneten Snapshot eindeutig identifiziert, und jeder von erstellte Snapshot btrfs receivehat immer einen Received UUIDEintrag. Wenn es sich um eine vollständige Übertragung handelte, hat es keinen Parent UUIDEintrag, wenn es sich um eine inkrementelle Übertragung handelte, hat es sowohl einen Received UUIDEintrag als auch einen Parent UUIDEintrag. UUID-Einträge können vom Benutzer nicht manuell geändert werden.

Diese IDs reichen aus, um btrfs receivefestzustellen, ob es einen <parent>Snapshot auf der Empfangsseite gibt, dersollenmuss vollständig identisch mit dem Snapshot der "Sendeseite" sein <parent>, da er Received UUIDmit 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/receivemanuell lässt es sich jedoch relativ einfach durchführen, vorausgesetzt, man möchte moviesund musicunter einem neuen Untervolume kombinieren unifiedund vorausgesetzt, moviesund musicwerden auch auf der Empfangsseite vollständig gespiegelt:

  1. Erstellen Sie auf der Sendeseite ein neues (leeres) Subvolume:btrfs subvolume create unified
  2. Ändern Sie es in schreibgeschützt:btrfs property set unified ro true
  3. Senden Sie es zur Sicherung:btrfs send /path/to/unified | btrfs receive /receiving/side/
  4. Nur Lesen deaktivierenauf beiden Seiten, zB btrfs property set /path/to/unified ro falsefür die sendende Seite
  5. Manuell --reflinkden Inhalt von musicund movieszuunified auf beiden Seiten cp -a --reflink /path/to/music /path/to/movies /path/to/unified/
  6. Satzbeidseitig's unifiedSnapshots wieder schreibgeschütztbtrfs property set /path/to/unified ro true
  7. Erstellen Sie einen neuen Lese-/Schreib-Snapshot von unifiedzur Interaktion, der unifiedals ü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 musicoder moviesSnapshot 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 UUIDauf 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 UUIDWert manuell zurückzusetzen überpython-btrfsnachdem 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 receiveschreibgeschützt ist, bis die Übertragung abgeschlossen ist, und wir versuchen, unsere --reflinkKopien 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 moviesund eine Kopie mit einem Reflink musiceinfü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 sendund btrfs receivesolltenichtgreifen 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 unifiedSnapshot noch übertragen wird und somit lesbar und beschreibbar ist, sollten sowohl das Subvolume auf der Sendeseite unifiedals auch sein Snapshot auf der Empfangsseite identisch sein und wir haben die Subvolumes erfolgreich zusammengeführt.

verwandte Informationen