Btrfs

Aus DebianforumWiki
Zur Navigation springen Zur Suche springen

Ü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.png Hinweis: Btrfs ist noch in der Entwicklung und nicht alle Funktionen sind ausreichend stabil für Produktivsysteme. Bitte beachtet den Status.


Getestet.png 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 Debianpackage.png 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 Debianpackage.png 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 Debianpackage.png 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 Debianpackage.png 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

  1. das Verzeichnis umbenennen,
  2. ein Subvolume mit dem ursprünglichen Namen des Verzeichnisses neu erzeugen,
  3. den Inhalt des Verzeichnisses in das Subvolume verschieben und
  4. 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

  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

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 Debianpackage.png 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.png 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.png 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.png 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.png 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 Debianpackage.png 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