BTRFS est un système de fichiers, comparable à ZFS, encore en développement très actif, mais déjà intégré au noyau Linux et considéré stable pour un bon nombre de fonctionnalités. Il est cependant conseillé d'avoir un noyau Linux le plus récent possible pour l'utiliser.

Il a un fonctionnement de type Copy-on-Write, ce qui donne accès à plusieurs fonctionnalités intéressantes, comme les instantanés et la déduplication. D'autres fonctionnalités sont aussi disponibles, comme la compression des données, la gestion des sous-volumes ou encore une gestion de RAID logiciel.

Installation

Pour manipuler un système de fichiers BTRFS sous Debian, il faut installer le paquet btrfs-progs. Il n'est pas nécessaire de synchroniser sa version avec celle du noyau Linux utilisé, mais seules les fonctionnalités gérées par ces deux éléments seront disponibles.

$ sudo apt-get install --no-install-recommends btrfs-progs

Note : Dans les précédentes versions de Debian, le paquet se nommait btrfs-tools.

Utilisation

La plupart des opérations peuvent être effectuées à chaud, comme l'ajout ou le retrait d'un disque, la compression, le redimensionnement (même en réduction) ou encore le changement d'un type de RAID.

Création du système de fichiers

Bien que BTRFS permette la création du système sur le disque complet, plutôt que dans des partitions, ceci n'est pas conseillé pour un disque système. En effet, il n'est alors pas possible de démarrer le système dans certaines configurations, ni de créer d'espace de SWAP, puisque cela nécessite des fonctionnalités non gérées par BTRFS.

Il est aussi possible de créer un système de fichiers BTRFS sur une ou plusieurs partitions. Dans le cas de l'aggrégation de plusieurs partitions, il est possible de définir séparément le niveau de RAID des données et des métadonnées.

$ # Système de fichiers sur un disque complet
$ mkfs.btrfs /dev/sda
$ # Système de fichiers créé sur une partition
$ mkfs.btrfs /dev/sdb1
$ # Système de fichiers dont les données et les métadonnées sont en raid1
$ mkfs.btrfs -d raid1 -m raid1 /dev/sdb2 /dev/sdc2
$ # Système de fichiers dont les données sont en raid0 et les métadonnées sont en raid1
$ mkfs.btrfs -d raid0 -m raid1 /dev/sdb3 /dev/sdc3

Note : Pour monter un système de fichiers créé sur plusieurs partitions, il est possible d'utiliser n'importe laquelle des partitions utilisées par le système de fichiers. On peut bien évidemment aussi utiliser l'UUID du système de fichiers.

Attention : Les niveaux de RAID 5 et 6 sont actuellement affectés par des bugs de corruption de données confirmés. Leur usage est fortement déconseillé !

Compression

La compression des données permet d'économiser de l'espace de stockage, et peut aussi améliorer les performances générales. Elle peut être activée pour le système de fichiers complet en ajoutant le paramètre compress dans les options de montage du périphérique BTRFS. Les différentes méthodes disponibles sont lzo et zlib.

Il est aussi possible de modifier les paramètres de compression pour un fichier précis.

$ # Activation de la compression pour le système de fichiers complet
$ sudo mount -o compress /dev/sdb1 /mount/path
$ # Activation de la compression lzo pour le système de fichiers complet
$ sudo mount -o compress=lzo /dev/sdb1 /mount/path
$ # Activation de la compression pour un fichier ou répertoire spécifique
$ sudo chattr -c /mount/path/file

Note : Lors de l'ajout de la compression pour sur un système de fichiers existant, il est possible de compresser l'ensemble des fichiers déjà présents avec la commande sudo btrfs filesystem defragment -c.

Ajouter des partitions

Que le système de fichiers ait été créé avec une ou plusieurs partitions, il est possible d'en ajouter par la suite. Après l'ajout d'une ou plusieurs partitions, il est nécessaire d'utiliser la commande btrfs balance, pour répartir les données entre les différentes partitions.

$ sudo mount -o compress,autodefrag,subvol=/ /dev/sda2 /mount/path
$ sudo btrfs device add /dev/sdc1 /mount/path
$ sudo btrfs balance start -dconvert=raid1 -mconvert=raid1 /mount/path

Retirer des partitions

Il est possible de retirer des partitions d'un système de fichiers BTRFS, par exemple pour libérer un disque afin de l'enlever de la machine Cette opération commence par répartir les données écrites sur la partition retirée sur les autres partitions, puis effectue le retrait proprement dit.

$ sudo mount -o compress,autodefrag,subvol=/ /dev/sda2 /mount/path
$ sudo btrfs device delete /dev/sdc1 /mount/path

Réorganiser les données entre les disques

BTRFS permet de modifier l'organisation des données entre les disques, séparément pour les trois types de données (données, métadonnées, et données système). Cette modification, effectuée par la commande btrfs balance, réorganise automatiquement les données entre les différents périphériques, et permet aussi de modifier le niveau de RAID utilisé..

Chaque filtre (-d, -m et -s) accepte différents paramètres. Il est possible d'utiliser plusieurs paramètres en même temps, en les séparant par une virgule.

Pour désigner les niveaux de RAID, un certain nombre de profiles sont définis, dont :

  • single : Données simplement réparties entre tous les disques.
  • dup : Données dupliquées sur tous les disques.
  • raid0i, raid1, raid10, raid5, raid6 : Données organisées selon le niveau de RAID correspondant.

Exemples :

$ # Modification du niveau de RAID des données vers le profile RAID1
$ sudo btrfs balance start -dconvert=raid1 /mount/path
$ # Réorganiser uniquement un nombre limité de blocs de données parmi ceux organisés en RAID1
$ sudo btrfs balance start -dprofiles=raid1,limit=10

Note : Lors du passage d'un RAID 1 à un RAID 10, il peut être nécessaire de commencer par effectuer une réorganisation simple, puis une conversion du niveau de RAID.

Remplacer un disque défectueux

Lorsqu'un disque est manquant, ou montre des signes d'usure élevée, il faut le remplacer. Si le système de fichiers n'est pas déjà monté, et qu'il manque l'un des disques, il est possible de le monter en mode dégradé :

$ sudo mount -o compress,autodefrag,subvol=/,degraded /dev/sda2 /mount/path

Le remplacement nécessite ensuite de connaître l'identifiant du disque à remplacer. Cette information peut être obtenue avec cette commande :

$ sudo btrfs filesystem show

Une fois cet identifiant obtenu, il est possible de lancer l'opération, en indiquant le disque remplaçant :

$ sudo btrfs replace start ID /dev/sdd1 /mount/path
$ # Afficher l'état d'avancement de l'opération de replacement
$ sudo btrfs replace status /mount/path

Gestion des sous-volumes

Les sous-volumes sont des sortes de sous-partitions, permettant de séparer de manière logique les données au sein d'un même système de fichiers. Ils sont semblables aux volumes logiques de LVM, à la différence que ce ne sont pas des périphériques virtuels de type block, mais plus des espaces de stockage au sein du même système de fichiers. Il n'est donc pas possible d'y créer d'autres systèmes de fichiers.

Lors de sa création, un sous-volume apparaît comme un répertoire vide. Il est possible d'agir dessus comme sur n'importe quel répertoires, par exemple, avec la commande mv.

$ sudo mount -o compress,autodefrag,subvol=/ /dev/sda2 /mount/path
$ sudo mkdir /mount/path/subvolumes
$ sudo btrfs subvolume create /mount/path/subvolumes/path

Note : Lors du montage de plusieurs sous volumes créés sur un même système de fichiers, seules les options de montage du premier sous-volume monté sont prises en compte. Les montages suivants utiliseront automatiquement les mêmes options. Ce comportement est susceptible de changer dans le futur.

Afficher la liste des sous-volumes existants :

$ sudo btrfs subvolume list /mount/path

Afficher les informations sur un sous-volume :

$ sudo btrfs subvolume show /mount/path/subvolume/path

Les instantanés

Les instantanés sont des sous-volumes, créés par duplication d'un sous-volume déjà existant. Dû au fonctionnement Copy-on-Write, leur création est immédiate, et n'occupe pas d'espace disque supplémentaire. Ils peuvent être utilisés, par exemple, pour dupliquer un répertoire, afin d'y faire des modifications sans altérer l'original, ou encore pour des sauvegardes.

L'utilisation des instantanés permet, entre autres, d'assurer la cohérence des sauvegardes, même lorsque celles-ci durent plusieurs heures. En effet, pour sauvegarder le contenu d'un sous-volume, il est intéressant de créer un instantané de ce sous-volume. Les données y seront alors figées, sans pour autant interdire les modifications dans le sous-volume à sauvegarder. On peut ensuite sauvegarder le contenu de l'instantané, sans risquer que les données ne soient modifiées pendant le déroulement de la sauvegarde.

Les instantanés étant eux-mêmes des sous-volumes, il est possible de créer des instantanés à partir d'instantanés.

$ sudo mount -o compress,autodefrag,subvol=/snapshots /dev/sda2 /mount/path/mnt/snapshots
$ sudo btrfs subvolume snapshot -r /mount/path/home /mount/path/mnt/snapshots/home/$(date +'%Y%m%d-%H%M%S')
$ sudo umount /mount/path/mnt/snapshots

Note : Le paramètre -r indique que l'on veut créer un instantané en lecture seule. Il est par exemple utilisé pour les sauvegardes, qui ne doivent pas être modifiable dans la plupart des cas.

Note : Lors de la création de sous-volumes dans d'autres sous-volumes, les sous-volumes enfants ne sont pas inclus lors de la création d'un instantané du parent.

Note : Il existe une fonctionnalité d'instantanés automatiques nommée autosnap. Elle est cependant encore en développement actif, et n'est pas utilisable pour le moment.

Restauration d'un instantané

Pour restaurer un instantané à la place du sous-volume d'origine, il suffit de supprimer, ou déplacer, le sous-volume, puis de refaire un instantané de l'instantané à restaurer, à la place du sous-volume à restaurer.

$ sudo mount -o compress,autodefrag,subvol=/snapshots /dev/sda2 /mount/path/mnt/snapshots
$ sudo btrfs subvolume delete /mount/path/home
$ sudo btrfs subvolume snapshot /mount/path/mnt/snapshots/home/some_snapshot_name /mount/path/home
$ sudo umount /mount/path/mnt/snapshots

Cette façon de faire a deux avantages :

  • Le sous-volume restauré n'est pas en lecture seule, même si l'instantané l'est.
  • L'instantané utilisé pour la restauration n'est pas altéré.

Vérification et réparation

La commande scrub permet de vérifier, et réparer, les données présentes sur le disque. Pour cela, il faut appeler sa sous-commande start :

$ sudo btrfs scrub start /mount/path

Il est aussi possible d'interrompre temporairement la vérification, de l'annuler, et d'afficher l'état d'avancement.

$ # Mettre la vérification en pause
$ sudo btrfs scrub pause /mount/path
$ # Annuler la vérification
$ sudo btrfs scrub cancel /mount/path
$ # Afficher l'état d'avancement de la vérification
$ sudo btrfs scrub status /mount/path

Options de montage

Certaines options de montage ont déjà été citées plus haut, mais d'autres existent. Voici celles que j'utilise :

  • compress : Définit le mode de compression (no, lzo, zlib).
  • degraded : Permet de monter le système de fichiers en mode dégradé, lorsqu'il manque au moins un des disques membres.
  • autodefrag : Active la défragmentation automatique du système de fichiers.
  • subvol : Définit le sous-volume à monter. Par défaut, le sous-volume racine est monté.
  • discard : Option à utiliser si le système de fichier est placé sur un disque SSD, pour activer la fonction TRIM.

Organisation des sous-volumes

De par son fonctionnement spécifique, le système de fichiers BTRFS permet d'organiser l'arborescence des répertoires et sous-volumes de différentes manières.

Arborescence à plat

Dans ce type d'organisation, tous les sous-volumes sont placés les uns à coté des autres, dans un même répertoire. Les sous-volumes sont alors indépendants.

  • Déplacer ou restaurer un sous-volume ne nécessite pas de modifier ou déplacer les autres.
  • Des options de montage différentes peuvent être définies par sous-volume.
  • Les options de montage identiques doivent être répétées pour chaque point de montage.
  • La gestion des instantanés est simplifiée, puisque tous les sous-volumes se situent au même endroit.
  • Tous les sous-volumes doivent être montés séparément.

Exemple :

/
    subvolumes/
        root/
        home/
        postgresql/
    snapshots/
        root/
        home/
        postgresql/

Astuce : Créer un sous-volume pour les instantanés, plutôt qu'un simple répertoire, permet de le monter dans à un emplacement spécifique. Cela évite d'avoir à monter la racine du système de fichiers pour accéder aux instantanés.

Sous-volumes imbriqués

Dans ce type d'organisation, les sous-volumes sont créés dans l'arborescence du système, directement à leur emplacement final.

  • Les sous-volumes apparaîssent à leur emplacement final, sans devoir être montés sépaément.
  • L'ensemble du système a les mêmes options de montage.
  • La totalité du système de fichiers reste accessible, dont le contenu de tous les instantanés. Cela peut poser problème lors de la correction d'une faille de type setuid, puisque l'élément vulnérable est alors toujours utilisable.

Exemple :

/
    home/
    var/
        lib/
            postgresql/
    snapshots/
        root/
        home/
        postgresql/

Mixte

Il est bien évidemment possible de mélanger ces deux organisations, pour tirer parti des avantages de chacune, selon le sous-volume. Dans un système globalement organisé à plat, il est possible de créer des sous-volumes dans un répertoire précis, si cela convient à l'organisation voulue. De cette manière, on peut, par exemple, créer un sous volume pour un répertoire contenant des données temporaire, ou pouvant être regénérées, afin de ne pas surcharger les instantanés.

La déduplication

La déduplication est un mécanisme qui permet de ne stocker physiquement qu'une seule fois les éléments identiques. Cela permet principalement d'économiser de l'espace de stockage.

Contrairement à ZFS, BTRFS n'effectue pas la déduplication à la volée, afin d'économiser des ressources. Pour en bénéficier, il faut donc exécuter régulièrement une tâche de maintenance, qui effectuera la déduplication.

Il n'est pas possible de dédupliquer les fichiers présents dans un instantané en lecture seule. Exécuter l'outil de déduplication avant la création d'un instantané en lecture seule est donc conseillé.

Il existe principalement deux outils permettant de gérer la déduplication du système de fichiers BTRFS.

Bedup

Bedup est développé en python3. Il utilise l'instruction clone pour effectuer la déduplication.

Installation

$ sudo apt-get install -t jessie-backports --no-install-recommends python3-virtualenv virtualenv python3-dev gcc libffi-dev
$ sudo virtualenv -p python3 /opt/bedup
$ sudo /opt/bedup/bin/pip install cffi
$ sudo /opt/bedup/bin/pip install bedup

Utilisation

$ sudo mount -o compress,autodefrag,subvol=/ /dev/sda2 /mount/path
$ sudo /opt/bedup/bin/bedup scan
$ sudo /opt/bedup/bin/bedup dedup [/path]
$ sudo /opt/bedup/bin/bedup show

Duperemove

Duperemove est développé en C. Il utilise l'instruction extent-same pour effectuer la déduplication.

Installation

$ sudo apt-get install -t jessie-backports --no-install-recommends unzip gcc make pkg-config libglib2.0-dev libsqlite3-dev
$ wget https://github.com/markfasheh/duperemove/archive/v0.11-branch.zip
$ unzip v0.11-branch.zip
$ cd duperemove-0.11-branch
$ make

Utilisation

$ sudo mount -o compress,autodefrag,subvol=/ /dev/sda2 /mount/path
$ sudo ./duperemove -r -d -A /mmount/path

Autres opérations

Déplacer le sous-volume contenant le système en cours d'exécution

Lors de l'utilisation de l'organisation "arborescence à plat", il est possible de déplacer les sous-volumes montés dans le système en cours d'exécution. En effet, le chemin n'est nécessaire que lors du montage, et BTRFS ne l'utilise plus une fois le sous-volume monté, ce qui permet de le déplacer sans rencontrer d'erreur.

Cela permet, par exemple, de restaurer la sauvegarde de la racine, ou de réorganiser les sous-volumes, sans nécessiter de démarrer un autre système.

Réorganisation des sous-volumes

$ sudo mount -o compress,autodefrag,subvol=/ /dev/sda2 /mount/path
$ # Déplacement du sous-volume
$ sudo mv /mount/path/old_path/old_subvol_name /mount/path/new_path/new_subvol_name
$ # Mise à jour des informations de démarrage
$ sudo grub-install /dev/sda
$ sudo update-grub
$ # Mise à jour du chemin de montage des sous-volumes
$ sudo vi /etc/fstab

Restauration de la sauvegarde d'un sous-volume du système en cours d'exécution

$ sudo mount -o compress,autodefrag,subvol=/ /dev/sda2 /mount/path
$ # Déplacement du sous-volume
$ sudo mv /mount/path/old_path/subvol_name /mount/path/new_path/subvol_name
$ # Restauration d'un instantané de ce sous-volume
$ sudo btrfs subvlume snapshot /mount/path/snapshots/subvol_name/snapshot_name /mount/path/old_path/subvol_name

Convertir une partition EXT4 en BTRFS

L'outil btrfs-convert permet de convertir une partition EXT4 en BTRFS. Le contenu de la partition EXT4 se retrouve alors à la racine de la partition BTRFS.

Durant cette opération, un sous-volume nommé ext2_saved est créé, pour conserver intact le contenu de la partition ext4. Cela permet d'accéder aux données telles qu'elles étaient avant la conversion, ainsi que l'inversion de l'opération. Ce sous-volume peut être supprimé sans risque, si la conversion inverse n'est pas prévue.

$ sudo umount /mount/path
$ sudo fsck.ext4 /dev/sdXY
$ sudo btrfs-convert /dev/sdXY
$ sudo mount -t btrfs -o compress,autodefrag,subvol=/ /dev/sdXY /mount/path
$ sudo btrfs filesystem defragment -t /mount/path
$ sudo btrfs balance start /mount/path
$ # Mise à jour du chemin de montage des sous-volumes (uuid, type de système de fichiers, options, etc.)
$ sudo vi /etc/fstab

Note : S'il s'agit du disque système, il faut ensuite mettre à jour les informations de démarrage, en utilisant par exemple :

$ chroot /mount/path
(chroot) # grub-install
(chroot) # update-grub

Sauvegarde et restauration d'un instantané BTRFS

La commande btrfs send permet de sauvegarder le contenu d'un instantané en lecture seule. Si le paramètre -f n'est pas utilisé, le contenu est envoyé sur la sortie standard. Cette sauvegarde peut être effectuée en totalité, ou de manière incrémentale par rapport à un autre instantané.

$ sudo btrfs send /snapshot/path -f snapshot.path.backup
$ # Sauvegarde incrémentale, par rapport à un autre instantané
$ sudo btrfs send /snapshot/new -f snapshot.old_to_new.backup -p /snapshot/old

La commande btrfs receive permet de restaurer, dans un sous-volume, une sauvegarde effectuée par la commande btrfs send. Si le paramètre -f n'est pas utilisé, le contenu est attendu sur l'entrée standard. Un sous volume du nom de l'instantané sauvegardé est créé dans le répertoire destination lors d'une restauration. Dans le cas d'une sauvegarde incrémentale, la présence du sous-volume parent est nécessaire dans le système de fichiers dans lequel est faite la restauration.

$ sudo btrfs receive /restore/location -f snapshot.path.backup

Avec le passage par l'entrée et la sortie standard, il est bien évidemment possible de passer les données directement d'une commande à l'autre, par exemple, pour transférer un sous-volume sur une autre machine.

$ sudo btrfs send /snapshot/save/path | ssh user@host 'sudo btrfs receive /snapshot/restore'

Gestion des quotas

BTRFS dispose d'une fonctionnalité de gestion de quotas, configurée au moyen de la commande btrfs quota. Lorsque les quotas sont activés, chaque sous-volume est assigné à un groupe qgroup, définissant les limites qui s'y appliquent.

Je n'utilise pas cette fonctionnalité.