Zum Inhalt springen

Btrfs/Snapshots

Aus Foxwiki

Snapshots

Grundlagen

Snapshots sind – technisch gesehen – Subvolumes, die aus einem anderen Subvolume erzeugt werden

  • Wegen Copy-on-Write geschieht das Erzeugen eines Snapshots augenblicklich und es wird kein zusätzlicher Speicherplatz verbraucht
  • Zusätzlicher Speicherplatz wird erst in dem Moment belegt, in dem der Snapshot oder das Original verändert werden

Technisch besteht zwischen dem Original und dem Snapshot keine Beziehung, die beschreibt, wer Original und wer Snapshot ist

Snapshots können nur von Subvolumes erzeugt werden

  • Wenn man einen Snapshot eines normalen Verzeichnisses erstellen möchte, muss dieses zuerst durch ein Subvolume ersetzt werden

Snapshots erzeugen und lösche n

Snapshots werden über btrfs subvolume snapshot erzeugt

  • Gelöscht werden sie, da sie nichts anderes als Subvolumes sind, über btrfs subvolume delete
root@demo:~# btrfs subvolume create subvol1
Create subvolume './subvol1'
root@demo:~# echo Original > subvol1/test.txt
root@demo:~# cat subvol1/test.txt
Original
root@demo:~# btrfs subvolume snapshot subvol1/ subvol1-snapshot
Create a snapshot of 'subvol1/' in './subvol1-snapshot'
root@demo:~# btrfs subvolume list
ID 265 gen 3537 top level 5 path root/subvol1
ID 266 gen 3537 top level 5 path root/subvol1-snapshot
root@demo:~# cat subvol1-snapshot/test.txt
Original

Jetzt verändern wir die Textdatei im Original:

root@demo:~# echo verändert >> subvol1/test.txt
root@demo:~# cat subvol1/test.txt
Original
verändert
root@demo:~# cat subvol1-snapshot/test.txt
Original
root@demo:~#

Nun löschen wir beide Subvolumes:

root@demo:~# btrfs subvolume delete subvol1
Delete subvolume (no-commit): '/root/subvol1'
root@demo:~# cat subvol1-snapshot/test.txt
Original
root@demo:~# btrfs subvolume delete subvol1-snapshot
Delete subvolume (no-commit): '/root/subvol1-snapshot'

Original aus Snapshot wiederherstellen

Es gibt keine Beziehung zwischen Original und Snapshot, die sie als Original und Snapshot kennzeichnet

  • Daher gibt es auch keine Funktion, die ein verändertes Original auf den Stand eines Snapshots zurücksetzt
  • Statt dessen
  1. löscht man das Original und
  2. erzeugt einen neuen Snapshot des Snapshots mit dem Namen des Originals

Zunächst bauen wir uns ein Subvolume auf und erzeugen einen Snapshot:

root@demo:~# btrfs subvolume create subvol1
Create subvolume './subvol1'
root@demo:~# echo Original > subvol1/test.txt
root@demo:~# btrfs subvolume snapshot subvol1/ subvol1-snapshot
Create a snapshot of 'subvol1/' in './subvol1-snapshot'
root@demo:~# echo verändert >> subvol1/test.txt
root@demo:~# cat subvol1/test.txt
Original
verändert
root@demo:~# cat subvol1-snapshot/test.txt
Original

Jetzt stellen wir das Original aus dem Snapshot wieder her:

root@demo:~# btrfs subvolume delete subvol1
Delete subvolume (no-commit): '/root/subvol1'
root@demo:~# btrfs subvolume snapshot subvol1-snapshot/ subvol1
Create a snapshot of 'subvol1-snapshot/' in './subvol1'
root@demo:~# cat subvol1/test.txt
Original

In diesem Beispiel bleibt der Snapshot bestehen:

root@demo:~# btrfs subvolume list
ID 268 gen 3543 top level 5 path root/subvol1-snapshot
ID 269 gen 3543 top level 5 path root/subvol1

Falls man den Snapshot von vornherein nicht mehr braucht, löscht man einfach das Original und benennt den Snapshot um

root@demo:~# btrfs subvolume delete subvol1
Delete subvolume (no-commit): '/root/subvol1'
root@demo:~# mv subvol1-snapshot/ subvol1
root@demo:~# btrfs subvolume list
ID 268 gen 3543 top level 5 path root/subvol1

Schreibgeschützte Snapshots

Snapshots lassen sich mit dem Parameter -r schreibgeschützt erzeugen:

root@demo:~# btrfs subvolume create subvol1
Create subvolume './subvol1'
root@demo:~# echo Original > subvol1/test.txt
root@demo:~# btrfs subvolume snapshot -r subvol1/ subvol1-snapshot
Create a readonly snapshot of 'subvol1/' in './subvol1-snapshot'
root@demo:~# echo verändert >> subvol1-snapshot/test.txt
bash: subvol1-snapshot/test.txt: Das Dateisystem ist nur lesbar

Will man das Original aus einem solchen Snapshot wiederherstellen, muss man zunächst das Original löschen und dann einen neuen, nicht schreibgeschützten Snapshot erzeugen

root@demo:~# btrfs subvolume delete subvol1
Delete subvolume (no-commit): '/root/subvol1'
root@demo:~# btrfs subvolume snapshot subvol1-snapshot/ subvol1
Create a snapshot of 'subvol1-snapshot/' in './subvol1'

Der neue Snapshot ist nicht schreibgeschützt:

root@demo:~# echo verändert >> subvol1/test.txt

Der alte Snapshot ist weiterhin schreibgeschützt:

root@demo:~# echo verändert >> subvol1-snapshot/test.txt
bash: subvol1-snapshot/test.txt: Das Dateisystem ist nur lesbar

Alternativ kann man über btrfs property den Schreibschutz entfernen und danach den Snapshot umbennnen

  • Dabei verliert man aber das „Backup“ in Form des vorhandenen Snapshot

Snapshots und verschachtelte Subvolumes

Wenn man einen Snapshot eines Subvolumes erzeugt, das wiederum Subvolumes enthält, dann landen die enthaltenen Subvolumes als leere Verzeichnisse im Snapshot:

root@demo:~# btrfs subvolume list
ID 268 gen 3543 top level 5 path root/subvol1
root@demo:~# btrfs subvolume create subvol1/subvol2
Create subvolume 'subvol1/subvol2'
root@demo:~# touch subvol1/subvol2/dateiinsubvol2
root@demo:~# btrfs subvolume list
ID 268 gen 3545 top level 5 path root/subvol1
ID 270 gen 3545 top level 268 path root/subvol1/subvol2
root@demo:~# btrfs subvolume snapshot subvol1/ subvol1-snapshot
Create a snapshot of 'subvol1/' in './subvol1-snapshot'

subvol2 ist im Snapshot enthalten, aber kein Subvolume:

root@demo:~# btrfs subvolume list
ID 268 gen 3546 top level 5 path root/subvol1
ID 270 gen 3545 top level 268 path root/subvol1/subvol2
ID 271 gen 3546 top level 5 path root/subvol1-snapshot
root@demo:~# ls subvol1-snapshot/
subvol2 test.txt

subvol2 ist im Snapshot leer:

root@demo:~# ls subvol1-snapshot/subvol2/
root@demo:~#

Das Subvolume subvol1 lässt sich nicht löschen, da dort ein weiteres Subvolume enthalten ist:

root@demo:~# btrfs subvolume delete subvol1
Delete subvolume (no-commit): '/root/subvol1'
ERROR: cannot delete '/root/subvol1': Directory not empty

Wenn man nun subvol2 und subvol1 löscht, ist subvol2 als normales Verzeichnis weiterhin im Snapshot enthalten:

root@demo:~# btrfs subvolume delete subvol1/subvol2/
Delete subvolume (no-commit): '/root/subvol1/subvol2'
root@demo:~# btrfs subvolume delete subvol1
Delete subvolume (no-commit): '/root/subvol1'
root@demo:~# btrfs subvolume list
ID 271 gen 3547 top level 5 path root/subvol1-snapshot
root@demo:~# ls subvol1-snapshot/
subvol2 test.txt