Btrfs
Überblick
Btrfs (B-tree FS, gelegentlich „Butterface“ ausgesprochen) ist ein noch relativ junges Copy-on-Write-Dateisystem, welches integriertes RAID, Volume-Management, Quotas und Prüfsummenberechnung bietet.
Btrfs bietet einige Anwendungsfälle, die sich auch mit Logical Volume Management oder ZFS darstellen lassen. Dieser Artikel soll nicht die verschiedenen Möglichkeiten vergleichen, sondern das Vorgehen mit btrfs zeigen.
GRUB kann von btrfs booten; es kann daher als Wurzeldateisystem verwendet werden. Es unterstützt den TRIM-Befehl und ist für SSDs geeignet.
Hinweis: Btrfs ist noch in der Entwicklung und nicht alle Funktionen sind ausreichend stabil für Produktivsysteme. Bitte beachtet den Status. |
Getestet: Dieser Hinweis soll dir dabei helfen, zu entscheiden, ob dieser Artikel auf deinem System funktionieren wird oder nicht. Solltest du feststellen, dass dieser Artikel bei einer ungetestet Version funktioniert, kannst du das gerne hier korrigieren oder im Forum anmerken.
|
Grundlagen
Grundlegende Konzepte
Dateisystem und Geräte
Bei btrfs gibt es keine 1:1-Beziehung zwischen physikalischem Gerät (d.h. einer Festplattenpartition) und Dateisystem. Da btrfs ein integriertes Volume Management ähnlich mdadm mit sich bringt, muss man sich vorstellen, dass ein btrfs-Dateisystem immer auf einem „Pool“ von physikalischen Geräten aufsetzt. Bei der Nutzung des Dateisystems ist es für den Anwender weitestgehend irrelevant, wie das Dateisystem die einzelnen Geräte anspricht.
Copy-on-Write
Copy-on-Write bedeutet, dass beim Kopieren von Daten diese erst in dem Moment „echt“ kopiert werden, wenn diese verändert werden. Vorher „zeigen“ sowohl Original als auch Kopie auf die gleichen Speicherbereiche.
Dieses Verfahren wird für Snapshots genutzt: ein Snapshot ist „sofort“ angelegt, da dafür keine wesentlichen Datenmengen kopiert werden müssen, und belegt keinen zusätzlichen Speicherplatz. Änderungen am Original werden in neue Speicherbereiche geschrieben.
Copy-on-Write lässt sich über die Mountoption nodatacow global abschalten. Für einzelne Dateien kann es über chattr gesteuert werden. Die Deaktivierung kann für bestimmte Dateien sinnvoll sein, bspw. für Images von virtuellen Maschinen oder Datenbankdateien.
Chunks
Die Daten werden in Chunks (auch Block Groups) genannt abgelegt. Ein Chunk ist ein Speicherbereich fester Größe. Es gibt drei unterschiedliche Chunk Types:
- Data: diese Chunks speichern ausschließlich Dateiinhalte. Ein Data Chunk ist in der Regel 1 GiB groß.
- Metadata: diese Chunks speichern dateisysteminterne Metadaten in B-Bäumen sowie kleine Dateien, wenn sie in den Chunk hineinpassen. Ein Metadata Chunk ist abhängig von der Dateisystemgröße 256 MiB oder 1 GiB groß.
- System: diese Chunks speichern Informationen über die Geräte, auf denen das Dateisystem liegt. System Chunks sind ein paar MiB groß.
Profile
Für die drei Chunk Types können Chunk Profiles ausgewählt werden. Die Profile entscheiden, wie die Chunks auf die physikalischen Geräte verteilt werden. In der Manpage von mkfs.btrfs findet sich eine Übersicht:
┌────────┬────────────────────────────────────┬────────────┐ │ │ │ │ │Profile │ Redundancy │ Min/max │ │ ├──────────────┬────────┬────────────┤ devices │ │ │ │ │ │ │ │ │ Copies │ Parity │ Striping │ │ ├────────┼──────────────┼────────┼────────────┼────────────┤ │ │ │ │ │ │ │single │ 1 │ │ │ 1/any │ ├────────┼──────────────┼────────┼────────────┼────────────┤ │ │ │ │ │ │ │ DUP │ 2 / 1 device │ │ │ 1/any (see │ │ │ │ │ │ note 1) │ ├────────┼──────────────┼────────┼────────────┼────────────┤ │ │ │ │ │ │ │ RAID0 │ │ │ 1 to N │ 2/any │ ├────────┼──────────────┼────────┼────────────┼────────────┤ │ │ │ │ │ │ │ RAID1 │ 2 │ │ │ 2/any │ ├────────┼──────────────┼────────┼────────────┼────────────┤ │ │ │ │ │ │ │RAID10 │ 2 │ │ 1 to N │ 4/any │ ├────────┼──────────────┼────────┼────────────┼────────────┤ │ │ │ │ │ │ │ RAID5 │ 1 │ 1 │ 2 to N - 1 │ 2/any (see │ │ │ │ │ │ note 2) │ ├────────┼──────────────┼────────┼────────────┼────────────┤ │ │ │ │ │ │ │ RAID6 │ 1 │ 2 │ 3 to N - 2 │ 3/any (see │ │ │ │ │ │ note 3) │ └────────┴──────────────┴────────┴────────────┴────────────┘
Bei der Erzeugung eines btrfs-Dateisystems auf einer rotierenden Festplatte wird mkfs.btrfs für Metadata- und System-Chunks das Profil DUP wählen, auf einer SSD dagegen Single. Durch die redundante Speicherung wird die Ausfallsicherheit erhöht. Da viele SSD-Controller intern Deduplizierung betreiben, lässt sich dort die Sicherheit so nicht erhöhen, weshalb mkfs.btrfs dann Single wählt.
Neben den in der Tabelle gezeigten Profilen werden nach und nach weitere Profile für besondere Einsatzzwecke hinzugefügt, bspw. für Metadaten für Daten-RAID56. Für eine aktuelle Übersicht schaut man am Besten in der Manpage nach.
Subvolumes
Ein Subvolume ist eine zusätzliche interne Dateisystemwurzel, die separat eingehängt werden kann. Aus Anwendungssicht erscheinen Subvolumes wie Verzeichnisse, sie lassen sich jedoch nicht über rmdir löschen. Auch ein rm -rf auf ein Verzeichnis schlägt fehl, wenn darin Subvolumes enthalten sind.
Subvolumes sind die Grundlage für Snapshots und Quotas.
Befehle
Für den Umgang mit btrfs-Dateisystemen müssen die btrfs-progs installiert werden. Das grundlegende Userspace-Tool heißt btrfs; die wichtigsten zugehörigen Befehle sind
- btrfs balance: Ausbalancieren eines Dateisystem, d.h. die Neuanordnung der Chunks, in denen die Daten abgelegt sind
- btrfs check: diverse Offline-Überprüfungen eines btrfs-Dateisystems
- btrfs device: Verwaltung der einem btrfs-Dateisystem zugeordneten Geräte
- btrfs filesystem: Verwaltung eines btrfs-Dateisystems an sich
- btrfs qgroups: Verwalten von Quota Groups
- btrfs quota: Verwalten von Quotas
- btrfs replace: Austauschen von Geräten bei RAID
- btrfs rescue: Reparieren beschädigter Dateisysteme
- btrfs scrub: Online-Überprüfungen eines btrfs-Dateisystems
- btrfs subvolume: Verwaltung von btrfs-Subvolumes und Snapshots
Für jeden Befehl gibt eine eigene Manpage. Die für balance ruft man bspw. über
user@debian:~$ man btrfs-balance
auf.
btrfs-Dateisysteme erzeugen
Ein btrfs-Dateisystem wird mit mkfs.btrfs angelegt.
root@demo:~# mkfs -t btrfs /dev/sdb1 btrfs-progs v4.20.1 See http://btrfs.wiki.kernel.org for more information. Label: (null) UUID: 13e1b03d-1610-436f-8589-925897f2a1ca Node size: 16384 Sector size: 4096 Filesystem size: 8.00GiB Block group profiles: Data: single 8.00MiB Metadata: DUP 409.50MiB System: DUP 8.00MiB SSD detected: no Incompat features: extref, skinny-metadata Number of devices: 1 Devices: ID SIZE PATH 1 8.00GiB /dev/sdb1
Kompression
btrfs bietet eine transparente Datenkompression, die sich mit der mount-Option compress aktivieren lässt. Neu geschriebene oder veränderte Daten werden dann automatisch komprimiert. Das Dateisystem erkennt anhand eines Algorithmus’, welche Daten sich komprimieren lassen. Dadurch können Daten auch unkomprimiert gespeichert werden.
Verschlüsselung
Eine integrierte Verschlüsselung ist nicht vorhanden. Will man btrfs verschlüsseln, so kann man dm-crypt verwenden. Da btrfs auf mehreren Geräten aufsetzen kann, muss man darauf achten, jedes Gerät zu verschlüsseln. Weitere Informationen gibt im btrfs-Wiki. (Bitte beachten: das Wiki spiegelt immer den aktuellen Entwicklungsstand von btrfs wieder, der nicht mit dem in Debian übereinstimmen wird.)
Freien Speicherplatz anzeigen
btrfs speichert die Daten intern in sog. Chunks, die Datenbereiche bestimmter Größe darstellen. Innerhalb eines Chunks können Daten unterschiedlicher Dateien abgelegt werden. Für das Vorhandensein freien Speicherplatzes auf einem btrfs-Dateisystem ist das Vorhandensein freier Chunks entscheidend. Anders ausgedrückt: bei btrfs muss man zwischen freiem Platz auf dem Dateisystem und freiem Platz auf den Geräten unterscheiden.
Da btrfs mit Copy-on-Write arbeitet und die Daten in Chunks allokiert, sind die Ausgaben von df und du mitunter irreführend. Bei Vorhandensein von Snapshots kann du u.U. mehr belegten Platz ausweisen, als das Dateisystem groß ist.
root@proliant:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 105G 35G 69G 34% / root@proliant:~# btrfs filesystem show / Label: none uuid: 2a485f0a-0fcc-4198-a92e-e0a9f854ac46 Total devices 1 FS bytes used 33.98GiB devid 1 size 104.31GiB used 61.03GiB path /dev/sda1
Wie interpretiert man diese Ausgabe?
- Total devices 1: das Dateisystem liegt ist einem Gerät zugeordnet
- FS bytes used 33.98GiB: auf dem Dateisystem sind 33,98 GiB belegt
- devid 1: es folgen Angaben zum ersten zugeordneten Gerät
- size 104.31GiB: dieses Gerät ist 104,31 GiB groß
- used 61.03GiB: es sind Chunks im Volumen von 61,03 GiB in Verwendung
- path /dev/sda1: das Gerät ist /dev/sda1
Die entscheidende Angabe ist die unterhalb der Devices: sie gibt an, in welchem Umfang Chunks belegt sind. Wenn keine freien Chunks mehr vorhanden sind, ist das Dateisystem voll. Bei der Angabe der belegten Chunks werden diese immer voll gezählt unabhängig davon, in welchem Umfang sie belegt sind.
Im Beispiel oben sind also nicht die von df ausgegebenen 69 GB frei. Das Dateisystem wird weitaus früher melden, dass kein Speicherplatz mehr vorhanden ist.
Wird innerhalb eines Chunks Speicherplatz durch Löschen einer Datei frei, so wird der Chunk immer noch als voll belegt angezeigt. Durch Neubalancieren des Dateisystems können Daten zwischen Chunks verschoben und so freier Speicherplatz gewonnen werden. Chunks, die keine Daten mehr enthalten, werden freigegeben.
Wie sich die belegten Daten über unterschiedliche Chunks verteilen, lässt sich über
root@proliant:~# btrfs filesystem df / Data, single: total=59.00GiB, used=33.33GiB System, single: total=32.00MiB, used=16.00KiB Metadata, single: total=2.00GiB, used=668.80MiB GlobalReserve, single: total=81.98MiB, used=0.00B
detaillierter anzeigen. Die Angabe „single“ zeigt an, dass es sich hier um Chunks handelt, die nur auf einem Gerät existieren.
Aber wieviel Platz ist belegt? Die Ausgabe von du ist genau wie die von df irreführend:
root@proliant:~# du -h --max-depth=0 /var/lib/lxc/ 83G /var/lib/lxc/
du meldet, dass unterhalb eines Verzeichnisses 83 GB belegt sind. Dies rührt daher, dass btrfs mit Copy-on-Write arbeitet, mehrere identische Dateien also nur einmal Speicherplatz belegen, du diesen aber mehrfach zählt. Im Beispiel oben existieren unter /var/lib/lxc mehrere Snapshots, die aber nur in soweit Speicherplatz belegen, wie sich das per Snapshot gesicherte Subvolume verändert hat. Auch das kann man sich ausgeben lassen:
root@proliant:~# btrfs filesystem du -s /var/lib/lxc Total Exclusive Set shared Filename 69.35GiB 2.30GiB 8.54GiB /var/lib/lxc
Tatsächlich sind nur knapp 11 GiB belegt, von denen 8,54 GiB von mehreren Snapshots und den Originalen gemeinsam verwendet werden. Nur 2,30 GiB entfallen auf sich unterscheidende Daten.
Balancieren
Unter Balancieren oder Balancing wird die Neuanordnung der Daten in den Chunks verstanden. Dies ist im Regelfall in zwei Fällen erforderlich:
- Das Chunk-Profil soll gewechselt werden. Beispiele dazu finden sich weiter unten unter Multidisk zu finden.
- Der Speicherplatz geht zur Neige, weil nur noch wenige freie Chunks vorhanden sind. Per Balancieren kann man btrfs dazu bewegen, Daten aus wenig belegten Chunks in andere Chunks zu verlagern und anschließend nicht mehr verwendete Chunks freizugeben.
Das Ergebnis sieht man hier in einer (gekürzten) Ausgabe von btrfs-balance, eines Tools von btrfsmaintenance:
/etc/cron.monthly/btrfs-balance: Before balance of / Data, single: total=60.00GiB, used=29.93GiB System, single: total=64.00MiB, used=16.00KiB Metadata, single: total=2.00GiB, used=582.12MiB GlobalReserve, single: total=74.83MiB, used=0.00B Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 112G 33G 78G 30% / Done, had to relocate 0 out of 64 chunks Dumping filters: flags 0x1, state 0x0, force is off DATA (flags 0x2): balancing, usage=1 Done, had to relocate 0 out of 64 chunks … Dumping filters: flags 0x6, state 0x0, force is off METADATA (flags 0x2): balancing, usage=30 SYSTEM (flags 0x2): balancing, usage=30 Done, had to relocate 2 out of 39 chunks After balance of / Data, single: total=36.00GiB, used=29.92GiB System, single: total=32.00MiB, used=16.00KiB Metadata, single: total=1.00GiB, used=577.44MiB GlobalReserve, single: total=70.14MiB, used=0.00B
Vorher waren Data Chunks im Umfang von 60 GiB vorhanden, die nur knapp 30 GiB Daten enthielten. Danach waren Data Chunks im Umfang von 36 GiB vorhanden. De facto sind 24 GiB Speicherplatz freigeworden. (Das darunterliegende Gerät ist übrigens 104,31 GiB groß.)
Das Balancieren zum Neuordnen von Chunks wird über den Filter usage gesteuert. Möchte man bspw. alle Data Chunks, die zu weniger als 40% belegt sind, umgliedern, so geschieht dies über btrfs balance -dusage=40 /. Den Prozess muss man möglicherweise mehrfach wiederholen und dabei steigende Prozentwerte verwenden. Das oben gezeigte btrfsmaintenance führt wiederholtes Balancieren mit steigenden Prozentwerten bis 30% durch.
Scrubbing
Beim Scrubbing werden alle Daten mit den gespeicherten Prüfsummen verglichen. Bei redundant gespeicherten Chunks (Profile DUP, RAID1/5/6) werden Fehler automatisch korrigiert. Es wird über btrfs scrub ausgelöst.
Das Ergebnis sieht man hier in einer Ausgabe von btrfs-scrub, eines Tools von btrfsmaintenance:
/etc/cron.monthly/btrfs-scrub: Running scrub on / scrub device /dev/sda1 (id 1) done scrub started at Fri Dec 1 07:06:06 2017 and finished after 00:01:26 total bytes scrubbed: 30.49GiB with 0 errors
Scrubbing belastet die Festplatte und den Prozessor enorm. Der Vorgang kann bei großen Dateisystemen mehrere Stunden dauern.
Debian auf btrfs installieren
Der Debian-Installer installiert Debian auf btrfs, wenn dieses während der Installation explizit ausgewählt wird. Die btrfs-progs werden dann automatisch installiert.
Subvolumes
Grundlagen
Ein Subvolume ist eine zusätzliche interne Dateisystemwurzel, die separat eingehängt werden kann. Aus Anwendungssicht erscheinen Subvolumes wie Verzeichnisse. Alle unterhalb eines eingehängten Subvolumes vorhandenen Subvolumes erscheinen gleichfalls als eingehängt. Bei der Nutzung von Subvolumes sind grundsätzlich zwei Vorgehensweisen denkbar: ein „flaches“ (flat) und ein „verschachteltes“ (nested) Layout.
Subvolumes sind die Grundlage für Snapshots und Quotas.
Flaches Layout
Beim flachen Layout wird die Dateisystemwurzel an sich nicht eingehängt, dafür aber die einzelnen Subvolumes. Es hat sich als Namenskonvention herausgebildet, die Namen solcher Subvolumes mit einem Klammeraffen beginnen zu lassen.
toplevel (Dateisystemwurzel, wird nicht eingehängt) +-- @root (Subvolume, das als Wurzelverzeichnis / eingehängt wird) +-- @home (Subvolume, das als /home eingehängt wird) +-- @topsecret (Subvolume, das nicht eingehängt wird) +-- var (normales Verzeichnis) +-- @lib (Subvolume, das unter /var/lib eingehängt wird) +-- @www (Subvolume, das unter /var/www eingehängt wird)
Im Beispiel wird die Verzeichnisstruktur näherungsweise durch Einfügen des Verzeichnisses /var nachgebildet. Technisch ist dies nicht erforderlich.
In der /etc/fstab wird der Verzeichnisbaum folgendermaßen zusammengebaut:
UUID=… / btrfs defaults,subvol=@root 0 0 UUID=… /home btrfs defaults,subvol=@home 0 0 UUID=… /var/lib btrfs defaults,subvol=/var/@lib 0 0 UUID=… /var/www btrfs defaults,subvol=/var/@www 0 0
Alles, was sich außerhalb/oberhalb der eingehängten Subvolumes befindet, ist aus Anwendersicht nicht vorhanden. Da das Subvolume @topsecret nicht explizit eingehängt wird und die Dateisystemwurzel auch nicht, kann auf Daten in @topsecret nicht zugegriffen werden.
Anstelle des über subvol angegebenen Pfads des Subvolumes kann man auch dessen ID über subvolid angeben. Die ID eines Subvolume kann über btrfs subvolume list oder btrfs subvolume show ermittelt werden. Die Angabe der ID ist kompakter und unempfindlich gegen das Verschieben des Subvolumes im Dateisystem, dafür ist die fstab weniger „sprechend“.
Verschachteltes Layout
Beim verschachtelten Layout wird die Dateisystemwurzel eingehängt. Damit werden auch automatisch alle Subvolumes eingehängt und erscheinen als Verzeichnisse.
toplevel (Dateisystemwurzel, wird als / eingehängt) +-- home (Subvolume, wird nicht explizit eingehängt, erscheint automatisch als Verzeichnis /home) +-- topsecret (Subvolume, wird nicht explizit eingehängt, erscheint automatisch als Verzeichnis /topsecret) +-- var (normales Verzeichnis) +-- lib (Subvolume, wird nicht explizit eingehängt, erscheint automatisch als Verzeichnis /var/lib) +-- www (Subvolume, wird nicht explizit eingehängt, erscheint automatisch als Verzeichnis /var/www)
Die fstab umfasst nur eine Zeile:
UUID=… / btrfs defaults 0 0
Wenn kein Subvolume angegeben wird, wird das als Default festgelegte Volume gemountet. Das ist im Regelfall die Dateisystemwurzel (das „top-level subvolume“); über btrfs subvolume set-default kann dieses geändert werden.
Subvolumes verwalten
Subvolumes lassen sich über btrfs subvolume verwalten. Die wichtigsten Befehle sind
- btrfs subvolume create: erzeuge ein Subvolume am angegebenen Ort.
- btrfs subvolume delete: lösche das angegebene Subvolume.
- btrfs subvolume list: zeige alle Subvolumes unterhalb des angegebenen Ortes.
- btrfs subvolume show: zeige Details des angegebenen Subvolumes.
- btrfs subvolume snapshot: erzeuge einen Snapshot des angegebenen Subvolumes.
root@demo:~# btrfs subvolume create subvol1 Create subvolume './subvol1' root@demo:~# btrfs subvolume create subvol2 Create subvolume './subvol2' root@demo:~# btrfs subvolume list . ID 263 gen 3526 top level 5 path root/subvol1 ID 264 gen 3527 top level 5 path root/subvol2
Hier werden die eindeutigen numerischen IDs der Subvolumes angezeigt. Das „top-level subvolume“, also die Wurzel eines btrfs-Dateisystems, hat immer die ID 5.
root@demo:~# btrfs subvolume delete subvol2 Delete subvolume (no-commit): '/root/subvol2' root@demo:~# btrfs subvolume list . ID 263 gen 3526 top level 5 path root/subvol1
Jetzt hängen wir das verbliebene Subvolume ein und wieder aus:
root@demo:~# mkdir /mnt/subvol1 root@demo:~# mount -t btrfs -o subvol=/root/subvol1 /dev/sda1 /mnt/subvol1/ root@demo:~# touch subvol1/test root@demo:~# ls /mnt/subvol1/ test root@demo:~# umount /mnt/subvol1/ root@demo:~# rmdir /mnt/subvol1/ root@demo:~# ls subvol1/ test
Und nun löschen wir das verbliebene Subvolume:
root@demo:~# btrfs subvolume delete subvol1 Delete subvolume (no-commit): '/root/subvol1' root@demo:~# btrfs subvolume list . root@demo:~# ls subvol1/ ls: Zugriff auf 'subvol1/' nicht möglich: Datei oder Verzeichnis nicht gefunden
Verzeichnisse in Subvolume umwandeln
Es gibt keinen Befehl, um ein Verzeichnis in ein Subvolume umzuwandeln. Man muss von Hand
- das Verzeichnis umbenennen,
- ein Subvolume mit dem ursprünglichen Namen des Verzeichnisses neu erzeugen,
- den Inhalt des Verzeichnisses in das Subvolume verschieben und
- das Verzeichnis löschen.
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öschen
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
- löscht man das Original und
- 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
Multidisk
Grundlagen
Wie oben unter Dateisystem und Geräte erläutert, spricht ein btrfs-Dateisystem im Hintergrund immer einen Pool von Geräten an und verhält sich in dieser Hinsicht ähnlich mdadm. Die Strategie, wie Daten auf Geräte verteilt werden, wird über die Chunk Profiles festgelegt. Die Profile können zur Laufzeit und auch auf einem eingehängten Dateisystem gewechselt werden.
RAID0/1
Single mit zwei Geräten
In der Ausgangssituation liegt ein btrfs-Dateisystem auf /dev/sda1 vor, das als Wurzeldateisystem gemountet ist. Die Platte ist 8 GB groß; ein Teil der Kapazität wird für Swap auf /dev/sda2 verwendet.
root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 7,0G 949M 5,5G 15% / root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 1 FS bytes used 902.12MiB devid 1 size 7.00GiB used 2.13GiB path /dev/sda1
Da es sich um ein frisch installiertes Minimalsystem in einer virtuellen Maschine handelt, ist das Dateisystem größtenteils leer und nur wenige Chunks sind belegt.
root@demo:~# btrfs filesystem df / Data, single: total=1.41GiB, used=872.05MiB System, DUP: total=8.00MiB, used=16.00KiB Metadata, DUP: total=358.31MiB, used=30.06MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Nun „bauen“ wir eine weitere virtuelle Festplatte von 8 GB Größe ein und erzeugen eine Partition /dev/sdb1, die die komplette Platte in Beschlag nimmt, legen darauf aber kein Dateisystem an. Statt dessen fügen wir /dev/sdb1 zum Wurzeldateisystem hinzu.
root@demo:~# btrfs device add /dev/sdb1 /
Als Ergebnis erhalten wir ein um 8 GB vergrößertes btrfs-Dateisystem:
root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 15G 949M 14G 7% /
Wir sehen, dass das neue Gerät dem Dateisystem zugehört, aber noch keine Daten abgelegt sind:
root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 2 FS bytes used 902.12MiB devid 1 size 7.00GiB used 2.13GiB path /dev/sda1 devid 2 size 8.00GiB used 0.00B path /dev/sdb1
Die Chunks werden allerdings nicht als RAID0 abgelegt, sondern unverändert in den Profilen Single und DUP.
root@demo:~# btrfs filesystem df / Data, single: total=1.41GiB, used=872.05MiB System, DUP: total=8.00MiB, used=16.00KiB Metadata, DUP: total=358.31MiB, used=30.06MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Wechsel auf RAID0
Hinweis: Die im folgenden gezeigten Profilwechsel sind weitestgehed willkürlich. Wer auf RAID1 umstellen möchte, kann das direkt tun. |
Nun stellen wir die Data Chunks auf RAID0 um. Am Speicherplatz wird das nichts ändern, allerdings wird btrfs die Chunks dann intern anders allokieren und ein Striping (d.h. eine Verteilung auf beide physikalischen Geräte) anwenden.
root@demo:~# btrfs balance start -dconvert=raid0 / Done, had to relocate 3 out of 5 chunks
btrfs meldet eine Umgliederung der Chunks. Der Speicherplatz ist erwartungsgemäß unverändert:
root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 15G 949M 12G 8% /
Die umgegliederten Chunks tauchen auf dem neuen Gerät auf:
root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 2 FS bytes used 902.47MiB devid 1 size 7.00GiB used 2.96GiB path /dev/sda1 devid 2 size 8.00GiB used 2.25GiB path /dev/sdb1
Die Chunks sind nun in den Profilen RAID0 und DUP abgelegt:
root@demo:~# btrfs filesystem df / Data, RAID0: total=4.50GiB, used=872.17MiB System, DUP: total=8.00MiB, used=16.00KiB Metadata, DUP: total=358.31MiB, used=30.28MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Wechsel auf RAID1
Jetzt stellen wir auf RAID1 um:
root@demo:~# btrfs balance start -dconvert=raid1 -mconvert=raid1 / Done, had to relocate 5 out of 5 chunks
Die Größe des Dateisystems entspricht nun dem des kleineren Geräts:
root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 7,5G 919M 5,9G 14% /
Beide Geräte sind identisch belegt, da Chunks nun identisch auf beide Geräte geschrieben werden:
root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 2 FS bytes used 902.26MiB devid 1 size 7.00GiB used 3.28GiB path /dev/sda1 devid 2 size 8.00GiB used 3.28GiB path /dev/sdb1
Bis auf die Global Reserve werden nun alle Chunks im Profil RAID1 abgelegt:
root@demo:~# btrfs filesystem df / Data, RAID1: total=3.00GiB, used=872.05MiB System, RAID1: total=32.00MiB, used=16.00KiB Metadata, RAID1: total=256.00MiB, used=30.19MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Hinweis: Für die Umstellung sollte ausreichend Zeit einkalkuliert werden, da die Umstellung bei Dateisystemgrößen im Terabyte-Bereich je nach Belegung mehrere Tage dauern kann. Das Dateisystem kann in der Zwischenzeit normal verwendet werden. Diverse btrfs-Aufrufe werden Warnungen ausgeben, dass unterschiedliche Chunk-Profile in Verwendung sind. Dies kann ignoriert werden. |
Sollte der balance-Vorgang unterbrochen werden, so kann er folgendermaßen fortgesetzt werden:
root@demo:~# btrfs balance start -dconvert=raid1,soft -mconvert=raid1,soft /
Die Angabe soft bewirkt, dass ausschließlich noch nicht konvertierte Chunks umgestellt werden.
Umgekehrte Wechsel
Und nun drehen wir das Ganze zurück auf RAID0:
root@demo:~# btrfs balance start -dconvert=raid0 -mconvert=dup / Done, had to relocate 5 out of 5 chunks root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 15G 949M 14G 7% / root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 2 FS bytes used 901.82MiB devid 1 size 7.00GiB used 2.25GiB path /dev/sda1 devid 2 size 8.00GiB used 2.56GiB path /dev/sdb1 root@demo:~# btrfs filesystem df / Data, RAID0: total=4.50GiB, used=871.57MiB System, DUP: total=32.00MiB, used=16.00KiB Metadata, DUP: total=128.00MiB, used=30.23MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Noch ein Schritt zurück zu Single/DUP:
root@demo:~# btrfs balance start -dconvert=single / Done, had to relocate 3 out of 5 chunks root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 15G 948M 14G 7% / root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 2 FS bytes used 901.78MiB devid 1 size 7.00GiB used 1.00GiB path /dev/sda1 devid 2 size 8.00GiB used 2.31GiB path /dev/sdb1 root@demo:~# btrfs filesystem df / Data, single: total=3.00GiB, used=871.58MiB System, DUP: total=32.00MiB, used=16.00KiB Metadata, DUP: total=128.00MiB, used=30.19MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Und jetzt nehmen wir /dev/sdb1 wieder weg:
root@demo:~# btrfs device remove /dev/sdb1 / root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 7,0G 948M 5,9G 14% / root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 1 FS bytes used 901.51MiB devid 1 size 7.00GiB used 1.72GiB path /dev/sda1 root@demo:~# btrfs filesystem df / Data, single: total=1.41GiB, used=871.37MiB System, DUP: total=32.00MiB, used=16.00KiB Metadata, DUP: total=128.00MiB, used=30.12MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Warnung: Wenn btrfs mit RAID0 oder RAID1 betrieben wird, müssen zu jedem Zeitpunkt mindestens zwei Geräte vorhanden sein. Wenn man ein Gerät einfach wegnimmt und das Dateisystem beschreibt, werden Single-Chunks erzeugt. btrfs toleriert diese Mischung möglicherweise nicht. Weitere Infos weiter unten unter Dateisystem unwiderruflich nur lesbar. |
Verschlüsseltes Multidisk
Da btrfs keine Verschlüsselung auf Ebene des Dateisystems bietet, müssen die verwendeten Blockgeräte verschlüsselt werden. Dies ist bspw. bei RAID1 etwas ineffizient, weil geschriebene und gelesene Daten dadurch zweifach ver- bzw. entschlüsselt werden müssen.
Zunächst erzeugt man mit fdisk zwei Partitionen, die verschlüsselt werden sollen. Danach legt man für diese Schlüssel an:
# mkdir /etc/cryptsetup-keys.d # chmod 0700 /etc/cryptsetup-keys.d/ # dd bs=1024 count=4 if=/dev/random of=/etc/cryptsetup-keys.d/sdc1_crypt.key 4+0 Datensätze ein 4+0 Datensätze aus 4096 Bytes (4,1 kB, 4,0 KiB) kopiert, 0,000479491 s, 8,5 MB/s # dd bs=1024 count=4 if=/dev/random of=/etc/cryptsetup-keys.d/sdd1_crypt.key 4+0 Datensätze ein 4+0 Datensätze aus 4096 Bytes (4,1 kB, 4,0 KiB) kopiert, 0,000214758 s, 19,1 MB/s # chmod 0400 /etc/cryptsetup-keys.d/sdc1_crypt.key /etc/cryptsetup-keys.d/sdd1_crypt.key
Danach werden die beiden Partitionen damit verschlüsselt:
# cryptsetup luksFormat /dev/sdc1 /etc/cryptsetup-keys.d/sdc1_crypt.key # cryptsetup luksFormat /dev/sdc1 /etc/cryptsetup-keys.d/sdd1_crypt.key
Danach ermittelt man deren UUID:
# lsblk -f NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINT sda ... sdc └─sdc1 crypto_LUKS 2 04ccf51d-23a8-420e-8d4e-53585947d8e9 sdd └─sdd1 crypto_LUKS 2 b8caa7ce-2097-4a90-a3a5-134c20fb4359
In der /etc/crypttab trägt man folgendes ein:
# <target name> <source device> <key file> <options> sdc1_crypt UUID=04ccf51d-23a8-420e-8d4e-53585947d8e9 none luks sdd1_crypt UUID=b8caa7ce-2097-4a90-a3a5-134c20fb4359 none luks
Beim Booten werden die Partitionen automatisch entschlüsselt und anschließend kann das Dateisystem ganz normal über die fstab gemountet werden.
Durch die Verwendung von UUID können die Festplatten nachträglich beliebig umgesteckt werden. Anstelle von sdc1_crypt und sdd1_crypt können also auch andere Namen gewählt werden.
Wenn man direkt mit dem Erzeugen des Dateisystem fortfahren will, müssen die Partitionen einmalig von Hand entschlüsselt werden:
# cryptsetup luksOpen --key-file /etc/cryptsetup-keys.d/sdc1_crypt.key /dev/sdc1 sdc1_crypt # cryptsetup luksOpen --key-file /etc/cryptsetup-keys.d/sdd1_crypt.key /dev/sdd1 sdd1_crypt
Danach kann das Dateisystem angelegt werden, hier am Beispiel eines RAID1:
# mkfs.btrfs -d raid1 -m raid1 /dev/mapper/sdc1_crypt /dev/mapper/sdd1_crypt
RAID5
Warnung: RAID 5 und 6 sollten nicht für produktive Daten verwendet werden, siehe den Status am Ende des Artikels. |
Single mit drei Geräten
Wir beginnen damit, dass wir dem Wurzeldateisystem zwei Partitionen hinzufügen. Die Profile der Chunks bleiben zunächst unverändert.
root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 1 FS bytes used 901.70MiB devid 1 size 7.00GiB used 1.72GiB path /dev/sda1 root@demo:~# btrfs device add /dev/sdb1 /dev/sdc1 / root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 23G 948M 22G 5% / root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 3 FS bytes used 901.70MiB devid 1 size 7.00GiB used 1.72GiB path /dev/sda1 devid 2 size 8.00GiB used 0.00B path /dev/sdb1 devid 3 size 8.00GiB used 0.00B path /dev/sdc1 root@demo:~# btrfs filesystem df / Data, single: total=1.41GiB, used=871.54MiB System, DUP: total=32.00MiB, used=16.00KiB Metadata, DUP: total=128.00MiB, used=30.14MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Umstellung auf RAID5
Nun stellen wir Data- und Metadata-Chunks auf RAID5 um. Die System-Chunks werden automatisch angepasst:
root@demo:~# btrfs balance start -dconvert=raid5 -mconvert=raid5 / Done, had to relocate 4 out of 4 chunks
df zeigt unzuverlässige Ergebnisse an.
root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 23G 919M 20G 5% /
Die Geräte sind nun alle belegt und die Chunk sind alle im Profil RAID5 gespeichert.
root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 3 FS bytes used 901.99MiB devid 1 size 7.00GiB used 2.16GiB path /dev/sda1 devid 2 size 8.00GiB used 2.16GiB path /dev/sdb1 devid 3 size 8.00GiB used 2.16GiB path /dev/sdc1 root@demo:~# btrfs filesystem df / Data, RAID5: total=4.00GiB, used=871.79MiB System, RAID5: total=64.00MiB, used=16.00KiB Metadata, RAID5: total=256.00MiB, used=30.19MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Zurück auf RAID1
Da RAID5 kaputt ist und wir den Platz nicht brauchen, stellen wir auf RAID1 um und entnehmen eine Platte.
root@demo:~# btrfs balance start -dconvert=raid1 -mconvert=raid1 / Done, had to relocate 4 out of 4 chunks root@demo:~# btrfs device remove /dev/sdc1 / root@demo:~# df -h / Dateisystem Größe Benutzt Verf. Verw% Eingehängt auf /dev/sda1 7,5G 918M 5,9G 14% / root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 2 FS bytes used 901.70MiB devid 1 size 7.00GiB used 1.28GiB path /dev/sda1 devid 2 size 8.00GiB used 1.28GiB path /dev/sdb1 root@demo:~# btrfs filesystem df / Data, RAID1: total=1.00GiB, used=871.54MiB System, RAID1: total=32.00MiB, used=16.00KiB Metadata, RAID1: total=256.00MiB, used=30.14MiB GlobalReserve, single: total=16.00MiB, used=0.00B
Festplatte tauschen
Die Platte eines RAID-Verbundes lässt sich über btrfs-replace austauschen. In der Ausgangssituation sei ein RAID1 gegeben:
root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 2 FS bytes used 1.09GiB devid 1 size 7.00GiB used 2.28GiB path /dev/sda1 devid 2 size 8.00GiB used 2.28GiB path /dev/sdb1
Man beachte, dass es sich hier um ein „schlampiges” RAID1 handelt, das aus Partitionen unterschiedlicher Größe zusammengesetzt ist. Nun wird eine wie sdb partitionierte Platte sdc angeschlossen (auf sdc1 darf kein Dateisystem vorhanden sein) und der Austausch gestartet:
root@demo:~# btrfs replace start /dev/sdb1 /dev/sdc1 /
Der Austausch arbeitet im Hintergrund; der Fortschritt lässt sich über btrfs replace status überwachen. Nach Abschluss des Vorgangs ist sdb1 aus dem Verband entfernt:
root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 2 FS bytes used 1.09GiB devid 1 size 7.00GiB used 2.56GiB path /dev/sda1 devid 2 size 8.00GiB used 2.56GiB path /dev/sdc1
System umziehen
Wenn das System von btrfs bootet, lässt sich das laufende System über btrfs replace auf eine neue Festplatte umziehen.
In der Ausgangssituation sei ein aus einem Device bestehendes btrfs-Dateisystem vorhanden:
root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 1 FS bytes used 1.09GiB devid 1 size 7.00GiB used 2.13GiB path /dev/sda1
Auf der Platte ist ansonsten nur eine Swap-Partition vorhanden. GRUB ist im Bereich vor Sektor 2048 installiert.
root@demo:~# fdisk -l /dev/sda Disk /dev/sda: 8 GiB, 8589934592 bytes, 16777216 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x29880cdd Device Boot Start End Sectors Size Id Type /dev/sda1 * 2048 14680063 14678016 7G 83 Linux /dev/sda2 14682110 16775167 2093058 1022M 5 Extended /dev/sda5 14682112 16775167 2093056 1022M 82 Linux swap / Solaris
Nun wird die neue Platte nahezu identisch partitioniert. sdb1 ist größer als sda1 und soll das btrfs-Dateisystem aufnehmen:
root@demo:~# fdisk -l /dev/sdb Disk /dev/sdb: 12 GiB, 12884901888 bytes, 25165824 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x335e752a Device Boot Start End Sectors Size Id Type /dev/sdb1 2048 23070719 23068672 11G 83 Linux /dev/sdb2 23070720 25165823 2095104 1023M 5 Extended /dev/sdb5 23072768 25165823 2093056 1022M 82 Linux swap / Solaris
Auf sdb1 darf kein Dateisystem erzeugt werden. Das bootable-Flag ist für keine Partition gesetzt, da dieses nicht benötigt wird. (Bekannte Ausnahme: ein HP-Proliant-Microserver weiß nicht, von welcher Platte er den MBR starten soll, wenn keine Partition markiert ist.)
Nun wird das Dateisystem auf sdb1 übertragen:
root@demo:~# btrfs replace start /dev/sda1 /dev/sdb1 /
Das Dateisystem ist nun auf sdb1, welches devid 1 erhält. sda1 ist nicht mehr da.
root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 1 FS bytes used 1.09GiB devid 1 size 7.00GiB used 2.68GiB path /dev/sdb1
Das Dateisystem hat immer noch die alte Größe, was wir nun ändern. Bei resize wird die devid 1 angegeben:
root@demo:~# btrfs filesystem resize 1:max / Resize '/' of '1:max' root@demo:~# btrfs filesystem show / Label: none uuid: c6325d8f-955b-455a-90b8-69ca095f6bf0 Total devices 1 FS bytes used 1.09GiB devid 1 size 11.00GiB used 2.68GiB path /dev/sdb1
Nun muss noch Swap angelegt werden:
root@demo:~# mkswap /dev/sdb5 Setting up swapspace version 1, size = 1022 MiB (1071640576 bytes) no label, UUID=d78f4431-7b12-4987-9c6e-ee750b3f7622
Die UUID muss in der /etc/fstab und der /etc/initramfs-tools/conf.d/resume eingetragen werden. Anschließend wird das initramfs neu gebaut:
root@demo:~# update-initramfs -u -k all
Danach installiert man GRUB auf der neuen Platte:
root@demo:~# grub-install /dev/sdb
Fertig. Nun kann man den Rechner runterfahren, die alte Platte ausbauen und von der neuen booten.
Wartung
btrfsmaintenance
btrfsmaintenance ist eine Sammlung von Skripten, mit denen per crontab u.a. ein Rebalancing und Scrubbing durchgeführt werden kann. Ab Buster sind die Skripte im Paket btrfsmaintenance enthalten. Für ältere Versionen kann man den Code von GitHub via
user@debian:~$ git clone https://github.com/kdave/btrfsmaintenance.git
herunterladen.
btrfs-snap
Mit btrfs-snap lassen sich Snapshots erzeugen, die wie bei rsnapshot automatisch rotiert werden. Der Code wird gleichfalls auf GitHub gehostet und kann via
user@debian:~$ git clone https://github.com/jf647/btrfs-snap.git
heruntergeladen werden.
Skript von scientific
Der Forenuser scientific hat ein Skript geschrieben, mit dem sich Snapshots und Backups erzeugen lassen.
Status
Die Statusseite des Projekts stellt stets den Entwicklungsstand für die aktuelle Kernel-Version dar, die nicht der Kernelversion in Debian entspricht.
Buster
Buster wird mit Kernel 4.19 und btrfs-progs 4.20 ausgeliefert. Die im folgenden Abschnitt zu Stretch genannten Einschränkungen für RAID1 und SSDs treffen nicht mehr zu. RAID56 gilt nach wie vor als „unstable“.
Die Projekt-Statusseite für Kernel 4.19 kann über die Versionshistorie abgefragt werden.
Das Debian-Wiki rät unter Buster von der Verwendung der Backports-Kernel ab und empfiehlt entweder die Verwendung des Standard-Kernels oder eines LTS-Kernels.
Stretch
Stretch wird mit Kernel 4.9 und btrfs-progs 4.7 ausgeliefert.
Die Projekt-Statusseite für Kernel 4.9 kann über die Versionshistorie abgefragt werden.
Das Debian-Wiki empfiehlt für Stretch die Verwendung von Kernel und btrfs-progs aus den Backports.
RAID1 unwiderruflich nur lesbar
Ein RAID1 kann unwiderruflich nur lesbar werden. Die Ursache ist, dass der Kernel ein solches Dateisystem mounten wird, auch wenn eines der Geräte fehlt. Werden dann Daten geschrieben, werden Chunks im Profil Single erzeugt. Beim nächsten Mounten stellt der Kernel fest, dass auf dem Dateisystem Chunks in den Profilen RAID1 und Single vorhanden sind, was als Fehler interpretiert wird. Das Dateisystem wird dann read only eingehängt[1]. Die Daten sind noch lesbar; es hilft jedoch nur ein Backup, gefolgt von einer Neuanlage des Dateisystems.
Dieser Fehler wurde in Kernel 4.14 korrigiert[2].
Datenverlust bei RAID56
RAID56 ist fehlerhaft, Datenverlust droht[3].
Verwendung auf SSDs
Die Mountoption ssd sollte erst ab Kernel 4.14 verwendet werden[4]. Da SSDs automatisch erkannt werden, muss man über nossd gegensteuern.
Weblinks
- btrfs-Dokumentation
- Statusseite des Projekts
- btrfs im Debian-Wiki
- btrfsmaintenance, Skripte für diverse Wartungsarbeiten
- btrbk, Backup auf entfernte Hosts via Snapshot
- btrfs-snap, Skripte zur automatischen Erstellung von Snapshots
- Wikipedia-Artikel