Comment faire une copie complète du contenu d'un système de fichiers btrfs? Par copie complète, je veux dire non seulement les données actuelles , mais aussi différents sous-volumes avec leurs instantanés , préservant idéalement leurs structures CoW (c'est-à-dire: ne pas dupliquer des blocs avec le même contenu.
Il semble qu'une copie au niveau du bloc (comme avec dd
) n'est pas une bonne idée, car elle duplique l'UUID, et il n'y a aucun moyen de le changer facilement , apparemment.
Je n'ai pas trouvé de solution toute faite à ce jour (2016-05-06), mais j'ai résolu le problème à mes fins, y compris la gestion de la copie sur écriture. Les étapes à « clone »
/source
pour/target
sont:Obtenir une liste des sous - volumes commandés par
ogen
:btrfs subvolume list -qu --sort ogen /source
. Le tri est probablement suffisant pour garantir que les instantanés ou les sous-volumes qui dépendent des précédents sont traités en premier. Ceci est important pour gérer la copie sur écriture, car nous devons d'abord transférer les volumes de base.Rendez tous les sous-volumes en lecture seule à l'aide de
btrfs property set -ts /source/some-volume ro true
.Maintenant, pour chaque sous-volume de la liste ci-dessus, en commençant par le haut, procédez comme suit:
Si le volume n'a pas d'UUID parent (affiché comme
-
) ou si l'UUID parent n'existe plus dans la liste, exécutez:btrfs send /source/some/volume | btrfs receive /target/some/
Si le volume a un UUID parent qui existe toujours, nous aurions dû le transférer déjà à cause de
--sort ogen
et nous pouvons l'utiliser comme base pour éviter la duplication des données. Par conséquent, recherchez le chemin de l'UUID parent dans la liste et exécutez:btrfs send -p /source/parent/volume/ -c /source/parent/volume/ /source/some/volume/ | btrfs receive /target/some/
(btrfs devinerait probablement l'-p
argument automatiquement, mais je préfère être explicite).Après avoir exécuté l' une des commandes ci - dessus font la cible et la source à nouveau en lecture-écriture:
btrfs property set -ts /source/some/volume ro false; btrfs property set -ts /target/some/volume ro false
. Cette étape peut être ignorée si la source a été précédemment en lecture seule.Cela devrait gérer de nombreux cas. Mises en garde:
Il peut y avoir quelques complications en ce qui concerne la commande lors de l'imbrication de sous-volumes / instantanés.
L'ensemble du processus est évidemment plus amusant lorsqu'il est écrit.
btrfs send
accepte plusieurs-c
arguments source ( ) de clone . Il peut être avantageux de spécifier non seulement le chemin du volume du parent, mais aussi ceux de tous les ancêtres ou simplement de tout volume précédemment envoyé. Cela n'a fait aucune différence ici, mais cela pourrait - juste une supposition - aider à éviter la duplication des données dans certains cas.Je ne sais pas si des méta-informations sur les instantanés ou les sous-volumes sont perdues en cours de route, mais à peu près tout ce qui est intéressant pour la plupart des cas d'utilisation devrait être conservé.
L'ensemble du processus m'a aidé à transférer un système de fichiers de 800 Go avec 3,8 Go utilisés (selon
df
) à une image de 10 Go avec 3,8 Go utilisés. Le transfert sans-p
et-c
aurait utilisé environ 190 Go, la duplication des données a donc été évitée.la source
ogen
signifie?ogen
est la "génération d'origine" du sous- volume . Je dois admettre que je ne comprends pas complètement les différences ou si l'utilisation de la génération (non d'origine) serait correcte, mais je suppose qu'un test a indiqué que cela fonctionnait mieux (éviter les doublons). La génération semble être mise à jour lors de la création d'instantanés basés sur un sous-volume, ce n'est pas le cas d'ogen. Je serais intéressé à entendre certaines conclusions. Il est probablement préférable de vérifier sur IRC ou sur la liste de diffusion Btrfs.J'ai créé un outil python qui peut le faire. J'ai fait cela parce que j'ai essayé l'approche de @Thomas Luzat dans ma propre implémentation et celle de @Johannes Ernst, et l'espace utilisé a doublé de 20 Go à 40 Go dans la procédure de clonage. Je pensais que quelque chose de plus efficace était nécessaire.
Considérez cet historique de système de fichiers commun:
Avec l'algorithme de Thomas, "courant" serait cloné en premier, et tous les instantanés (étant des instantanés d'anciens états de "courant") utiliseraient "courant" comme source / parent de clone. Évidemment, il serait préférable de baser snap3 sur snap4, snap2 sur snap3, etc.
Et ce n'est que la pointe de l'iceberg; trouver les "meilleures" sources de clones (en termes d'économie d'espace) dans un système de fichiers btrfs avec une histoire complexe n'est pas un problème trivial. J'ai trouvé 3 autres stratégies pour résoudre ce problème, qui semblent utiliser l'espace beaucoup plus efficacement. L'un a en fait abouti à des clones de taille légèrement inférieure à celle de la source.
Vous pouvez lire les détails sur la page github si vous êtes intéressé.
la source
Il y a une question similaire sur unix.stackexchange.com qui pointe vers partclone.btrfs, mais je ne connais aucun détail à ce sujet.
Il y a aussi une discussion sur la liste de diffusion du noyau , pas vraiment prometteuse ...
la source
Avec
btrfs-send
, ce que j'ai vu pour la dernière fois, il y avait encore des correctifs expérimentaux flottant sur la liste de diffusion btrfs.la source