ZFS est un système de fichiers dédié serveur qui promet de réconcilier les administrateurs système avec les systèmes de fichiers. Il a été écrit par les développeurs de Sun. Il est donc disponible nativement sous Solaris. Il simplifie toutes les opérations qui nous horripilent ou nous rebutent. Il a une fonctionnalité qui m'a vraiment fait craquer et qui me paraît tellement évidente qu'on se demande pourquoi les autres systèmes de fichiers ne la proposent pas : il est capable (avec un système de disques redondants) de s'auto-réparer ! Le code [0] est placé sous licence CDDL, approuvée par l'OSI (l'Open Source Initiative [1]), c'est donc un logiciel libre même si l'on peut regretter ce choix pour des raisons éthiques [2]. Voyons ce dont ZFS est capable.
1. Des chiffres
Lorsque l'on parle de chiffres, pour un système de fichiers, il s'agit généralement de ses limites. ZFS, dans ce domaine, a été conçu directement pour le futur, jugez plutôt :
- Système de fichiers entièrement 128 bits, c'est-à-dire non seulement pour le nombre d'inodes, mais aussi pour la taille maximale d'un fichier .
- 264 soit plus de 18 milliards de milliards de fichiers au maximum dans chaque système de fichiers.
- 248snapshots au maximum. Si on en fait 10 par seconde, on peut tenir pendant plus de 890 000 ans ! Mais, il faudrait de la place et justement…
- 16 exa octets, soit plus de 16 000 peta octets. C'est la taille maximale d'un système de fichiers. 16 exa octets, c'est aussi la taille maximale d'un fichier !
- 248 fichiers au maximum dans un répertoire.
- 256 zeta octets, soit plus de 256 000 exa octets. C'est la taille maximale d'un pool (un ensemble de périphériques) qui peut contenir au maximum 264 systèmes de fichiers.
- Les pools peuvent être formés d'au maximum 264 périphériques.
Ces chiffres sont tellement immenses qu'on ne se rend pas bien compte de ce que cela représente. Aussi, il est probable que l'énergie nécessaire pour remplir un système de fichiers comme celui-là soit si gigantesque qu'elle pourrait suffire à faire bouillir l'eau des océans [3]. On comprend mieux pourquoi ce système de fichiers a été nommé Zeta File System, soit ZFS.
2. Installation
Donc, en cherchant bien, on trouve Ricardo Correia (connu sous le pseudonyme wizeman), un gentil développeur, qui a porté ZFS pour qu'il utilise fuse sous GNU/Linux. En effet, la licence CDDL est incompatible avec la licence GPL (dans sa version 2), celle du noyau GNU/Linux. C'est pourquoi ZFS n'est pas intégré au noyau et que l'on doit utiliser fuse pour le faire fonctionner sous GNU/Linux. Ce n'est par exemple pas le cas de FreeBSD où ZFS est intégré nativement depuis la version 7.0. Sur le site de FreeBSD [4], il est écrit qu'il s'agit d'un support expérimental, mais un certain D.B., rédacteur en chef d'un magazine sur GNU/Linux me souffle qu'en réalité c'est « intégré de manière très très propre » !
Du coup, avant toute chose sous GNU/Linux (les noms des paquets cités ici proviennent de ma Debian), il faut installer fuse-utils et aussi libfuse-dev, car nous allons compiler le programme qui utilise les structures de fuse. Il faut aussi installer libaio-dev et libaio1 qui permettent d'effectuer les entrées/sorties de manière asynchrone. La bibliothèque de compression de données zlib vous sera demandée avec sa version de développement. Il faut également un noyau GNU/Linux2.6.x supérieur à 2.6.15 et une glibc avec les pthreads dans une version supérieure à 2.3.3. Le système de compilation utilise la commande scons [5] en remplacement de la commande make. Il vous la faudra également.
Téléchargez [6] l'archive et décompressez-la avant de lancer la compilation :
$ tar jxvf zfs-fuse-0.5.0.tar.bz2
$ cd zfs-fuse-0.5.0/src/
$ scons
Si, comme moi, vous avez une machine dont l'âge est honorable, il faudra une bonne dizaine de minutes avant que cette opération ne se termine.
Installons le programme :
$ sudo scons install
Et voilà !!
Par défaut, tout s'installe dans /usr/local/sbin. Vous pouvez modifier cela en spécifiant une option à scons :
$ sudo scons install install_dir=/chemin/vers/les/programmes
3. Tour d'horizon rapide des commandes et des fonctionnalités
Nous venons d'installer les commandes zdb, zfs, zfs-fuse, zpool et ztest.
zdb est la commande qui permet de diagnostiquer des pannes et erreurs de ZFS. Toutefois, comme le fonctionnement de ZFS lui garantit d'être toujours cohérent et qu'il se répare tout seul, cette commande n'est pas très utile dans un premier temps.
zpool permet de gérer les « pools » de stockage, c'est-à-dire les regroupements de disques de stockage.
zfs permet de configurer le ou les systèmes de fichiers contenus dans les « pools ».
ztest permet de faire des tests.
zfs-fuse va nous servir sous GNU/Linux puisqu'il s'agit du mauvais génie (le démon quoi !) qui gère tout ça !!
Mentionnons l'option pour obtenir l'aide des commandes. Cette dernière n'étant pas très POSIX [7], elle est un peu inhabituelle. Aussi, vous devrez utiliser l'option -?.
Les fonctionnalités présentes dans la version 0.5 sont les suivantes :
- Créer et détruire des pools, des snapshots et des clones.
- Fonctionnalités de raid, raid-0 ou agrégats, raid 1 ou miroir, raid 5 ou à parité contrôlée (cette fonctionnalité se nomme raidz pour ZFS), raid 6 à double parité (nommée raidz2).
- Possibilité d'utiliser n'importe quel périphérique en mode bloc ou n'importe quel fichier (sauf un issu d'un système de fichiers ZFS) pour réaliser un périphérique virtuel.
- La compression, la détection d'erreur, la vérification des données ainsi que l'auto-réparation (sur un volume de type raid redondant type raid 1, raid 5 ou raid 6).
- Les quotas et la réservation fonctionnent, même s'il ne s'agit pas de « vrais quotas » à la sauce POSIX du terme.
- Sauvegarde et restauration (via les snapshots).
Bien qu'il y ait déjà de nombreuses fonctionnalités opérationnelles, il en existe beaucoup d'autres qui ne le sont pas encore, soit qu'elles ne sont pas encore implémentées, soit qu'elles ne peuvent l'être du fait de limitations dues principalement à fuse (que l'on remercie quand même d'exister). Pour avoir une idée plus précise des fonctionnalités qui restent à écrire, reportez-vous au fichier STATUS qui se trouve à la racine des sources.
4. Passons aux choses sérieuses
4.1 Création d'un pool
Avant toute chose, vérifiez que fuse est bien là et lancer le processus ZFS pour ce dernier comme suit. Attention, la commande ne se termine pas, ouvrez donc un terminal dédié :
$ sudo -s
# modprobe fuse
# zfs-fuse --no-daemon
Si cela ne fonctionne pas, reportez vous au paragraphe 6. Pour faire mes tests, vu qu'à la maison je n'ai pas un serveur de fichiers avec plusieurs contrôleurs et plusieurs disques, j'utilise des fichiers comme s'ils étaient des disques. Je me crée dix « disques » de 512 Mo :
$ mkdir test_zfs
$ cd test_zfs
$ for i in $(seq 0 9); \
do dd if=/dev/zero of=./disque_$i bs=1M count=512; \
done;
Après un long moment (ma machine a mis plus de 5 minutes), vous obtenez dix magnifiques fichiers, tous d'une taille identique de 512 Mo. Nous admettrons qu'il s'agit là de dix disques durs très haute performance !
Attention : La création d'un pool nécessite des périphériques (ou fichiers) dont la taille est supérieure ou égale à 64 Mo.
Donc, nous allons créer un pool avec les dix disques, en raidz2, c'est-à-dire un genre de raid 6 et disons que, comme on est très prudent, on va utiliser un disque de réserve (« spare » en anglais). On souhaite aussi que le volume correspondant soit monté sur /media/zfs_test (qui est un dossier qui n'existe pas sur le système utilisé). Utilisons la commande suivante :
# zpool create raid6 raidz2 \
/tmp/test_zfs/disque_{0,1,2,3,4,5,6,7,8} \
spare /tmp/test_zfs/disque_9 -m /media/zfs_test
S'agissant de fichiers et non de périphériques, veillez à bien spécifier le chemin absolu (depuis la racine) de chaque fichier.
Hop et voilà !! Si si, c'est tout ce qu'il y a à faire. D'ailleurs, vérifions tout de suite avec la commande df -h qui donne :
# df -h
Sys. de fich. Tail. Occ. Disp. %Occ. Monté sur
/dev/hda2 12G 7,9G 3,5G 70% /
tmpfs 237M 0 237M 0% /lib/init/rw
udev 10M 104K 9,9M 2% /dev
tmpfs 237M 0 237M 0% /dev/shm
/dev/hda1 236M 145M 79M 65% /boot
/dev/hda5 24G 9,2G 14G 41% /home
raid6 3,4G 42K 3,4G 1% /media/zfs_test
3,4 Go de libre, c'est bien 7*512Mo, car, pour schématiser, on a 9 disques dans le raidz2 dont 2 disques de parités soit 7 disques utiles plus un disque de réserve (ici spare). Cette place est directement utilisable, car montée automatiquement sur /media/zfs_test (comme on lui avait demandé). Ici, pas besoin d'un long mkfs. La commande s'est exécutée en un clin d’œil : la taper a presque été plus long ! Une commande utile à ce stade est zpool status qui permet de connaître l'état des pools (ici un seul) :
# zpool status
pool: raid6
state: ONLINE
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
raid6 ONLINE 0 0 0
raidz2 ONLINE 0 0 0
/tmp/zfs_test/disque_0 ONLINE 0 0 0
/tmp/zfs_test/disque_1 ONLINE 0 0 0
/tmp/zfs_test/disque_2 ONLINE 0 0 0
/tmp/zfs_test/disque_3 ONLINE 0 0 0
/tmp/zfs_test/disque_4 ONLINE 0 0 0
/tmp/zfs_test/disque_5 ONLINE 0 0 0
/tmp/zfs_test/disque_6 ONLINE 0 0 0
/tmp/zfs_test/disque_7 ONLINE 0 0 0
/tmp/zfs_test/disque_8 ONLINE 0 0 0
spares
/tmp/zfs_test/disque_9 AVAIL
errors: No known data errors
Ici, on voit très nettement qu'il y a 9 disques dans le raidz2 que j'ai nommé « raid6 » et un disque de réserve qui est disponible (AVAIL). Cette commande nous servira, par la suite, pour connaître l'état du pool.
Copions donc des données. Une commande du -hs /var/cache m'indique que ce dernier occupe 3,4 Go, parfait pour être copié dans mon volume de test :
# cp -a /var/* /media/zfs_test/
Là, pour le coup, c'est long, très long même, plus de 30 minutes sur ma machine. Mais c'est normal, car toutes les opérations ont lieu sur le même disque physique. De plus, ZFS crée le système de fichiers à la volée et calcule les sommes de contrôle (checksums) qui lui seront utiles au cas où il lui arriverait malheur (et croyez-moi, je ne vais pas être tendre). Si, comme moi, vous essayez de mettre plus de données que le volume ne peut en contenir, vous allez vous rendre compte, vers la fin, que ZFS cherche de la place et se réorganise. Si vous regardez la place libre avec la commande df -h régulièrement, il est possible que vous voyiez cette dernière augmenter, alors même que vous copiez des données !! Astuce : Pour réaliser cela, utilisez la commande watch comme suit (utilisez [Ctrl-C] pour quitter le programme) :
$ watch -t -d -n1 "df -h"
La recherche de place libre est très consommatrice de ressources et écroule totalement les performances (sous GNU/Linux en tout cas). Il est préférable de ne jamais remplir totalement un système de fichiers ZFS pour éviter ce problème. Notamment, cela vous évitera de vous demander pourquoi vous n'arrivez pas à effacer un fichier de 2 Go quand votre pool ZFS est plein à 99%...
Notons que ZFS gère plusieurs types de systèmes de fichiers tels que « raidz2 » que nous venons de voir ou « raidz » qui est une sorte de raid5 et « mirror » qui est une sorte de raid1. De base, il gère le raid0 qui est un simple agrégat. Nous le verrons plus tard. Il est possible de mélanger, dans une certaine mesure, tout cela.
4.2 Faisons souffrir le système de fichiers
4.2.1 Un disque rempli d'erreurs
Écrivons n'importe quoi dans le fichier disque_4 par exemple :
# shred -n 1 disque_4
Après une manœuvre pareille, le contenu du fichier disque_4 n'est plus du tout le même qu'avant.
La commande zpool status annonce qu'il y a eue une erreur, mais que les applications n'ont pas été affectées. Elle indique aussi les actions à réaliser pour effacer les erreurs ou pour remplacer le disque défectueux. Par contre, l'accès aux fichiers dans /media/zfs_test/ reste possible et sans erreurs, car ZFS les détecte et les corrige à la volée. À noter que la commande zpool scrub raid6 permet de corriger l'ensemble des données du volume (moins le volume est rempli, plus c'est rapide).
La colonne CKSUM de la commande zpool status indique le nombre de sommes de contrôle trouvées en erreur.
4.2.2 Un disque en moins
Bon, dans la vrai vie, c'est rare que l'on puisse réécrire sur les secteurs défectueux d'un disque. Pour simuler un disque défectueux, tuez le processus zfs-fuse, supprimez le fichier de votre choix, relancez le processus zfs-fuse et réimportez le pool (voir § 6.) :
# killall zfs-fuse
# rm -f disque_4
# zpool import -d . raid6
# zpool status
pool: raid6
state: DEGRADED
status: One or more devices could not be opened. Sufficient replicas exist for
the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
see: http://www.sun.com/msg/ZFS-8000-2Q
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
raid6 DEGRADED 0 0 0
raidz2 DEGRADED 0 0 0
/tmp/zfs_test/disque_0 ONLINE 0 0 0
/tmp/zfs_test/disque_1 ONLINE 0 0 0
/tmp/zfs_test/disque_2 ONLINE 0 0 0
/tmp/zfs_test/disque_3 ONLINE 0 0 0
7760834922797222775 UNAVAIL 0 0 0 was /tmp/zfs_test/disque_4
/tmp/zfs_test/disque_5 ONLINE 0 0 0
/tmp/zfs_test/disque_6 ONLINE 0 0 0
/tmp/zfs_test/disque_7 ONLINE 0 0 0
/tmp/zfs_test/disque_8 ONLINE 0 0 0
spares
/tmp/zfs_test/disque_9 AVAIL
errors: No known data errors
L'indication est claire : il manque un disque. La commande conseille de le brancher et de le mettre en ligne en utilisant la commande zpool online.
4.2.3 Deux disques en moins ! Vite, utilisons le disque de réserve !
Soyons fous, recommençons et supprimons disque_5. Les sorties sont les mêmes, mais, cette fois, nous n'avons plus la ceinture, ni les bretelles et le moindre problème dans l'un des disques restant serait fatal aux données. Utilisons donc le disque de spare :
# zpool replace /tmp/zfs_test/disque_4 /tmp/zfs_test/disque_9
Et voilà ! Comment ça et voilà ? Si si, je vous assure, c'est tout, ZFS s'occupe de reconstruire en arrière-plan le système de fichiers, de noter que le périphérique disque_9 est maintenant utilisé et qu'il remplace disque_4 et vous continuez d'avoir accès à vos fichiers de manière transparente, comme si de rien était :
# zpool status
pool: raid6
state: DEGRADED
status: One or more devices could not be opened. Sufficient replicas exist for
the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
see: http://www.sun.com/msg/ZFS-8000-2Q
scrub: resilver in progress for 0h2m, 11,20% done, 0h16m to go
config:
NAME STATE READ WRITE CKSUM
raid6 DEGRADED 0 0 0
raidz2 DEGRADED 0 0 0
/tmp/zfs_test/disque_0 ONLINE 0 0 0
/tmp/zfs_test/disque_1 ONLINE 0 0 0
/tmp/zfs_test/disque_2 ONLINE 0 0 0
/tmp/zfs_test/disque_3 ONLINE 0 0 0
spare DEGRADED 0 0 0
7760834922797222775 UNAVAIL 0 0 0 was /tmp/zfs_test/disque_4
/tmp/zfs_test/disque_9 ONLINE 0 0 0
2705405041636850921 UNAVAIL 0 0 0 was /tmp/zfs_test/disque_5
/tmp/zfs_test/disque_6 ONLINE 0 0 0
/tmp/zfs_test/disque_7 ONLINE 0 0 0
/tmp/zfs_test/disque_8 ONLINE 0 0 0
spares
/tmp/zfs_test/disque_9 INUSE currently in use
errors: No known data errors
Regardez bien. La commande indique même depuis combien de temps elle reconstruit (ici 2 minutes) et combien de temps il va lui falloir pour terminer (à vitesse constante, ici 16 minutes – en réalité, il ne lui a fallu que 12 minutes).
4.2.4 Allons y gaiement...
Ce qui est agréable avec la commande zpool status, c'est qu'elle indique tout de manière précise et concise. Par exemple, supprimons le disque de spare (disque_9) et inscrivons 10 Mo de données aléatoires dans l'un des disques restants. Le résultat sera qu'un certain nombre de fichiers seront illisibles, oui, mais lesquels ?
# rm -f disque_9
# dd if=/dev/urandom of=disque_7 bs=1024 count=10000 \ seek=56654 conv=notrunc
10000+0 enregistrements lus
10000+0 enregistrements écrits
10240000 bytes (10MB) copied, 3,51317 s, 2,9 MB/s
# zpool import -d . raid6
# zpool status
pool: raid6
state: DEGRADED
status: One or more devices could not be opened. Sufficient replicas exist for
the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
see: http://www.sun.com/msg/ZFS-8000-2Q
scrub: none requested
config:
NAME STATE READ WRITE CKSUM
raid6 DEGRADED 0 0 0
raidz2 DEGRADED 0 0 0
/tmp/zfs_test/disque_0 ONLINE 0 0 0
/tmp/zfs_test/disque_1 ONLINE 0 0 0
/tmp/zfs_test/disque_2 ONLINE 0 0 0
/tmp/zfs_test/disque_3 ONLINE 0 0 0
spare UNAVAIL 0 0 0 insufficient replicas
7760834922797222775 UNAVAIL 0 0 0 was /tmp/zfs_test/disque_4
9623051411205814655 UNAVAIL 0 0 0 was /tmp/zfs_test/disque_9
2705405041636850921 UNAVAIL 0 0 0 was /tmp/zfs_test/disque_5
/tmp/zfs_test/disque_6 ONLINE 0 0 0
/tmp/zfs_test/disque_7 ONLINE 0 0 0
/tmp/zfs_test/disque_8 ONLINE 0 0 0
spares
/tmp/zfs_test/disque_9 UNAVAIL cannot open
errors: No known data errors
# zpool scrub raid6
#
Après l'import du nouveau pool très dégradé, zpool status nous indique bien avoir perdu le disque de réserve et qu'il n'y a pas assez de disques pour la réserve. Mais, la commande n'indique pas les éventuelles erreurs dans le système de fichiers (erreurs dues à la commande dd). La commande zpool scrub raid6 permet de parcourir l'ensemble des données pour y détecter des erreurs et éventuellement les corriger, le tout de manière transparente. Voyons le résultat avec la commande zpool status –v :
# zpool status -v
pool: raid6
state: DEGRADED
status: One or more devices has experienced an error resulting in data
corruption. Applications may be affected.
action: Restore the file in question if possible. Otherwise restore the
entire pool from backup.
see: http://www.sun.com/msg/ZFS-8000-8A
scrub: scrub in progress for 0h5m, 77,37% done, 0h1m to go
config:
NAME STATE READ WRITE CKSUM
raid6 DEGRADED 1,07K 0 0
raidz2 DEGRADED 1,07K 0 0
/tmp/zfs_test/disque_0 ONLINE 0 0 0
/tmp/zfs_test/disque_1 ONLINE 0 0 0
/tmp/zfs_test/disque_2 ONLINE 0 0 0
/tmp/zfs_test/disque_3 ONLINE 0 0 0
spare UNAVAIL 0 0 0 insufficient replicas
7760834922797222775 UNAVAIL 0 0 0 was /tmp/zfs_test/disque_4
9623051411205814655 UNAVAIL 0 0 0 was /tmp/zfs_test/disque_9
2705405041636850921 UNAVAIL 0 0 0 was /tmp/zfs_test/disque_5
/tmp/zfs_test/disque_6 ONLINE 0 0 0
/tmp/zfs_test/disque_7 ONLINE 0 0 39
/tmp/zfs_test/disque_8 ONLINE 0 0 0
spares
/tmp/zfs_test/disque_9 UNAVAIL cannot open
errors: Permanent errors have been detected in the following files:
/media/zfs_test/apt/archives/iceape-browser_1.1.9-5_i386.deb
/media/zfs_test/apt/archives/libnspr4-0d_4.7.1-3_i386.deb
/media/zfs_test/apt/archives/libedataserver1.2-9_2.22.2-1_i386.deb
/media/zfs_test/apt/archives/libcamel1.2-11_2.22.2-1_i386.deb
/media/zfs_test/apt/archives/libexchange-storage1.2-3_2.22.2-1_i386.deb
/media/zfs_test/apt/archives/libgnome-pilot2_2.0.15-2.4_i386.deb
/media/zfs_test/apt/archives/libgtkhtml3.14-19_3.18.2-1_i386.deb
/media/zfs_test/apt/archives/libnm-glib0_0.6.6-1_i386.deb
/media/zfs_test/apt/archives/libpisock9_0.12.3-5_i386.deb
/media/zfs_test/apt/archives/libpisync1_0.12.3-5_i386.deb
/media/zfs_test/apt/archives/libpanel-applet2-0_2.20.3-5_i386.deb
/media/zfs_test/apt/archives/evolution-common_2.22.2-1.1_all.deb
/media/zfs_test/apt/archives/libwnck22_2.22.3-1_i386.deb
/media/zfs_test/apt/archives/libxslt1.1_1.1.24-1_i386.deb
Et ainsi de suite... La commande indique non seulement le disque où se sont produites les erreurs, via la colonne CKSUM, mais aussi très précisément quels sont les fichiers qui ne sont plus bons. Dans l'exemple, il s'agit de 79 fichiers du dossier /apt/archives/.
Dans le cas d'un système de fichiers réel, si une telle chose se produit, l'administrateur connaît rapidement le nom des fichiers erronés et peut, après avoir réparé, c'est-à-dire remplacé les disques, faire une restauration à partir de la sauvegarde.
4.2.6 Remplacement des disques
Comme vous avez des données très importantes sur vos disques, vous commandez de nouveaux disques qui iront remplacer les anciens. Manque de bol, la capacité ridicule de 512 Mo n'existe plus et les seuls nouveaux disques que vous trouvez sont des disques de 650 Mo :
# dd if=/dev/zero of=nouveau_0 bs=1M count=650
# dd if=/dev/zero of=nouveau_1 bs=1M count=650
Comment va se comporter le système avec des disques de taille supérieure ? Est-ce qu'il va subsister de la place non utilisée sur le disque ?
Le remplacement des disques manquant est possible, même avec des disques de plus grande taille. Toutefois, il n'est pas complètement effectif dans notre exemple, notamment, le système refuse obstinément d'enlever l'ancien disque arguant du fait qu'il manque des données. Supprimons donc ces données qui sont de toute manière perdues (on pensera à remercier l'administrateur d'avoir fait des sauvegardes sur bande) :
# zpool status -v raid6 | grep media | xargs rm -f
Demandons-lui de se réparer avec une commande du type fsck :
# zpool scrub raid6
La commande s'exécute en arrière plan et zpool status raid6 vous dit où elle en est. En attendant qu'elle termine, profitez-en pour regarder le résultat de la commande zpool iostat -v raid6. Elle indique la place utilisée et restante des pools et systèmes de fichiers, ainsi que le nombre d'opérations d'écriture et de lecture par secondes effectuées sur chaque disque et la bande passante que cela représente. Il est possible de demander à ce que l'exécution de cette commande se répète selon un intervalle donné, par exemple toutes les 3 secondes : zpool iostat -v raid6 3.
Lorsque la commande est terminée, vous pouvez enlever les anciens disques défectueux avec la commande zpool detach raid6 /tmp/zfs_test/disque_5 ou en utilisant le nom système du disque (dans notre exemple, il s'agit de : 2705405041636850921).
La commande zpool list qui donne un résumé très synthétique des pools indique qu'il n'y a pas eu d'augmentation de la capacité. Si l'on souhaite que la capacité augmente, il faudra remplacer tous les anciens disques avec des nouveaux de capacité identique. Tout cela se réalise bien entendu alors que le système de fichiers est monté, vous pouvez accéder à vos fichiers en toute transparence !
Un bémol toutefois, pour que mon système prenne effectivement en compte l'augmentation de la capacité totale, il a fallu que j'arrête puis relance zfs-fuse et que j'importe à nouveau le pool. Cette manipulation n'a pris que quelques secondes, mais, pendant ces quelques secondes, les fichiers ne sont plus accessibles (pensez à prévenir les utilisateurs).
4.2.7 Augmentation de capacité par ajout d'un nouveau raidz au pool
Un autre moyen d'augmenter la capacité est d'ajouter un nouvel ensemble de disques dans notre pool (que nous avons nommé raid6). Nous pouvons faire cela avec la commande suivante :
# zpool add raid6 raidz2 /tmp/zfs_test/dvd_{0,1,2,3,4,5,6,7,8}
Il faut garder en tête que ZFS a besoin d'un nombre de périphériques identiques entre ensemble de fichiers d'un même pool. Cela lui simplifie le travail (il est toutefois possible de le forcer avec l'option -f). Nous obtenons ainsi une sorte de raid 0+6 :
# zpool status -v
pool: raid6
state: ONLINE
scrub: resilver completed after 0h11m with 0 errors on Thu Oct 16 22:35:33 2008
config:
NAME STATE READ WRITE CKSUM
raid6 ONLINE 0 0 0
raidz2 ONLINE 0 0 0
/tmp/zfs_test/nouveau_3 ONLINE 0 0 0
/tmp/zfs_test/nouveau_4 ONLINE 0 0 0
/tmp/zfs_test/nouveau_2 ONLINE 0 0 0
/tmp/zfs_test/nouveau_5 ONLINE 0 0 0
/tmp/zfs_test/nouveau_0 ONLINE 0 0 0
/tmp/zfs_test/nouveau_1 ONLINE 0 0 0
/tmp/zfs_test/nouveau_6 ONLINE 0 0 0
/tmp/zfs_test/nouveau_7 ONLINE 0 0 0
/tmp/zfs_test/nouveau_8 ONLINE 0 0 0
raidz2 ONLINE 0 0 0
/tmp/zfs_test/dvd_0 ONLINE 0 0 0
/tmp/zfs_test/dvd_1 ONLINE 0 0 0
/tmp/zfs_test/dvd_2 ONLINE 0 0 0
/tmp/zfs_test/dvd_3 ONLINE 0 0 0
/tmp/zfs_test/dvd_4 ONLINE 0 0 0
/tmp/zfs_test/dvd_5 ONLINE 0 0 0
/tmp/zfs_test/dvd_6 ONLINE 0 0 0
/tmp/zfs_test/dvd_7 ONLINE 0 0 0
/tmp/zfs_test/dvd_8 ONLINE 0 0 0
errors: No known data errors
Soit une capacité portée à
# df -h
Sys. de fich. Tail. Occ. Disp. %Occ. Monté sur
/dev/hda1 9,2G 5,1G 3,7G 59% /
udev 10M 52K 10M 1% /dev
/dev/hda3 141G 102G 32G 77% /home
overflow 1,0M 12K 1012K 2% /tmp
raid6 32G 1,8G 30G 6% /media/zfs_test
ou encore :
# zpool list
NAME SIZE USED AVAIL CAP HEALTH ALTROOT
raid6 40,7G 2,21G 38,4G 5% ONLINE -
En faisant ainsi, on a augmenté, de manière transparente, la taille totale du système de fichiers.
La taille donnée par la commande zfs-list et celle donnée par la commande du -h sont différentes. Il semble que la commande zfs-list ne prenne pas en compte dans son calcul les disques réservés au calcul des sommes de contrôle (deux dans notre cas).
4.2.8 Rappel des commandes utiles
zpool create nom_du_pool type_du_pool noms_des_périphériques crée un pool selon les options spécifiées. Le type du pool peut-être « mirror », « raidz » ou « raidz2 ».
zpool destroy nom_du_pool pour détruire un pool entier. Attention, cette commande ne demande pas de confirmation et il ne semble pas exister d'option « garde fou » du type « -i » des coreutils !
zpool iostat -v permet l'affichage des statistiques d'entrées/sorties des pools tout en indiquant la répartition des données et de ces entrées/sorties sur chacun des fichiers ou périphériques constituant le pool.
zpool status -v donne l'état de chacun des pools. Cette commande détaille les erreurs lorsqu'il y en a.
5. Systèmes de fichiers
La commande zpool que nous venons de voir crée un système de fichiers racine dans le pool et le monte sur le point de montage qu'on lui a indiqué. Il est toutefois possible de créer, dans le pool, des systèmes de fichiers indépendants. Listons les systèmes de fichiers déjà utilisables :
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
raid6 32,7M 26,6G 32,6M /media/zfs_test
Nous retrouvons notre système de fichiers raid6 (qui est aussi le nom du pool) monté sur /media/zfs_test. Nous pouvons maintenant créer au maximum 264 systèmes de fichiers dans ce pool, par exemple :
# zfs create raid6/usr
# zfs create raid6/home
# zfs create raid6/var
Ce qui donne :
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
raid6 32,9M 26,7G 32,6M /media/zfs_test
raid6/home 41,9K 26,7G 41,9K /media/zfs_test/home
raid6/usr 41,9K 26,7G 41,9K /media/zfs_test/usr
raid6/var 41,9K 26,7G 41,9K /media/zfs_test/var
Vous pouvez vérifier avec la commande df -h que les systèmes de fichiers sont bien montés. Ils se partagent tous un même espace de stockage qui est le pool en lui-même. Si on le souhaite, on peut remplir raid6/home et, dans ce cas, il ne restera plus de place pour les autres systèmes de fichiers. On peut voir cela comme des répertoires. À la différence prêt qu'il est possible de préciser quelques options nommées « propriétés ». Par exemple, il est possible de redéfinir le point de montage :
# zfs set mountpoint=/media/sauvegarde raid6
# zfs set mountpoint=/media/var raid6/var
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
raid6 32,9M 26,7G 32,6M /media/sauvegarde
raid6/home 41,9K 26,7G 41,9K /media/sauvegarde/home
raid6/usr 41,9K 26,7G 41,9K /media/sauvegarde/usr
raid6/var 41,9K 26,7G 41,9K /media/var
# zfs mount raid6/var
La dernière commande permet de remonter le système de fichiers dont on vient de modifier le point de montage, le changement l'ayant démonté automatiquement. Si on change plusieurs points de montage, on pourra utiliser la commande zfs mount -a.
Pour obtenir les propriétés d'un système de fichiers, utilisez la commande zfs get all nom_du_systeme_de_fichiers, par exemple :
# zfs get all raid6/var
NAME PROPERTY VALUE SOURCE
raid6/var type filesystem -
raid6/var creation lun oct 27 23:10 2008 -
raid6/var used 41,9K -
raid6/var available 26,7G -
raid6/var referenced 41,9K -
raid6/var compressratio 1.00x -
raid6/var mounted yes -
raid6/var quota none default
raid6/var reservation none default
raid6/var recordsize 128K default
raid6/var mountpoint /media/var local
raid6/var sharenfs off default
raid6/var checksum on default
raid6/var compression off default
raid6/var atime on default
raid6/var devices on default
raid6/var exec on default
raid6/var setuid on default
raid6/var readonly off default
raid6/var zoned off default
raid6/var snapdir hidden default
raid6/var aclmode groupmask default
raid6/var aclinherit restricted default
raid6/var canmount on default
raid6/var shareiscsi off default
raid6/var xattr on default
raid6/var copies 1 default
raid6/var version 3 -
raid6/var utf8only off -
raid6/var normalization none -
raid6/var casesensitivity sensitive -
raid6/var vscan off default
raid6/var nbmand off default
raid6/var sharesmb off default
raid6/var refquota none default
raid6/var refreservation none default
raid6/var primarycache all default
raid6/var secondarycache all default
raid6/var usedbysnapshots 0 -
raid6/var usedbydataset 41,9K -
raid6/var usedbychildren 0 -
raid6/var usedbyrefreservation 0 -
Le paramètre SOURCE peut prendre trois valeurs :
- default qui indique une valeur par défaut (ou inchangée) ;
- local qui indique que la valeur a été fixée spécifiquement pour ce système de fichiers ;
- inherited qui indique que la valeur est héritée d'un système de fichiers parent.
On a déjà vu que l'on peut changer le point de montage en changeant la propriété mountpoint, mais ce changement nécessite de remonter les systèmes de fichiers. Heureusement, ce n'est pas toujours le cas et, notamment, il est possible de changer, de manière transparente et alors que le système de fichiers est en fonctionnement, certaines propriétés telles que compression, quota et reservation par exemple.
5.1 Compression
Il est possible d'indiquer, à la volée, à un système de fichier ZFS s'il doit compresser les données ou non. Pour l'exemple, créons un système de fichiers nomméraid6/etc. En général, ce dossier contient plein de fichiers de configuration de type texte qui se prêtent bien à la compression. Puis, indiquons-lui qu'il doit maintenant compresser les données en mettant la propriété compression à on. Enfin, copions le contenu de /etc et voyons le résultat de la compression :
# zfs create raid6/etc
# zfs set compression=on raid6/etc
# zfs get compression raid6/etc
NAME PROPERTY VALUE SOURCE
raid6/etc compression on local
# cp -a /etc/* /media/sauvegarde/etc/
# zfs get compression, compressratio raid6/etc
NAME PROPERTY VALUE SOURCE
raid6/etc compression on local
raid6/etc compressratio 2.05x -
# zfs list raid6/etc
NAME USED AVAIL REFER MOUNTPOINT
raid6/etc 18,2M 26,7G 18,2M /media/sauvegarde/etc
# du -hs /etc
35M /etc
La propriété compressratio indique le taux effectif de compression des données, ici un peu plus de 2 fois.
Lorsqu'il existe des données préalablement à la modification de la propriété, ces dernières ne sont pas compressées. Elles restent non compressées sur le disque. Toutefois, et c'est là que c'est intéressant, les nouvelles données ajoutées aux fichiers non compressés, seront, elles, compressées. Ainsi, un fichier peut avoir une partie non compressée et une partie compressée (celle qui aura été écrite après le changement de la propriété).
De même, lorsque l'on modifie à nouveau la propriété vers la valeur off, c'est-à-dire sans compression, les données ajoutées le seront sans compression, mais l'état de celles qui étaient compressées précédemment n'est pas modifié.
Cet exemple montre que certaines propriétés affectent les blocs et pas, comme on pourrait s'y attendre, les fichiers eux-mêmes.
5.2 Quotas
Les quotas sur ZFS ne fonctionnent pas à la manière des quotas POSIX. Ils sont fixés par système de fichiers et non par utilisateur. Deux propriétés permettent de les fixer :
- quota limite l'espace du système de fichiers, pour lui-même et tous les systèmes de fichiers fils, incluant les instantanés ou snapshots.
- refquota fait exactement la même chose, mais la limite n'inclut pas les instantanés ou les descendants.
Il est donc possible de jouer avec ces deux propriétés de manière à limiter la taille maximale occupée par un système de fichiers. Dans notre exemple, on pourrait fixer la taille maximale de /var à 5 Go avec la propriété refquota et autoriser 5 Go pour les instantanés en fixant à 10 Go la propriété quota.
Dès que l'une ou l'autre des propriétés sont définies, la commande df -h indique la taille du disque, ainsi que la place restante. Elles sont déterminées par la propriété qui contraint le plus (en général, il s'agit de refquota).
Utilisée avec l'option de compression, le quota s'applique, une fois les données compressées. Ainsi, si un système de fichiers est plein avec un quota de 100 Mo, que la propriété de compression est à vrai et que le taux de compression est de 2x alors ce système de fichiers contient 200 Mo de données non compressées.
Lorsque que le quota est atteint, une erreur survient pour l'indiquer et, dès lors, il n'est plus possible d'ajouter des données ou des fichiers.
5.3 Réservation
La propriété reservation permet de réserver de l'espace sur un système de fichiers. Cet espace est directement et immédiatement consommé sur l'espace disponible du système de fichiers parent. Il doit donc être disponible au moment où l'on fixe la valeur de la propriété.
5.4 Héritage des propriétés
Certaines propriétés peuvent être héritées directement de leur(s) parent(s). C'est le cas par exemple pour la compression, le point de montage, les quotas et la réservation. Si l'on change les propriétés d'un système de fichiers, tous ses sous-systèmes hériteront de la nouvelle valeur.
5.5 Instantanés ou snapshots
Comme pour toutes les fonctionnalités que nous avons déjà vues, celle ci est très simple d'emploi. De plus, la création d'un instantané ne consomme pas de place supplémentaire. Seules les données créées ou modifiées à la suite de cette création utiliseront de l'espace supplémentaire. Un exemple d'utilisation des instantanés :
# zfs list raid6/home
NAME USED AVAIL REFER MOUNTPOINT
raid6/home 57,0K 26,7G 57,0K /media/sauvegarde/home
# ls -lsa /media/sauvegarde/home
total 25
3 drwxr-xr-x 2 root root 5 nov 30 19:08 .
5 drwxr-xr-x 6 root root 10 oct 28 19:43 ..
11 -rw------- 1 root root 10653 nov 30 19:08 .bash_history
3 -rw------- 1 root root 701 nov 30 19:08 .bash_profile
3 -rw------- 1 root root 1244 nov 30 19:08 .bashrc
Maintenant que nous avons vu ce qu'il y a dans notre répertoire, créons notre premier instantané en utilisant la commande zfs snapshot nom_du_snapshot et observons le résultat :
# zfs snapshot raid6/home@premier
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
raid6/home 57,0K 26,7G 57,0K /media/sauvegarde/home
raid6/home@premier 0 - 57,0K -
Comme on peut le voir, l'instantané premier n'occupe aucune place. Copions des données :
# cp /etc/passwd /media/sauvegarde/home
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
raid6/home 98,9K 26,7G 61,6K /media/sauvegarde/home
raid6/home@premier 37,2K - 57,0K -
Il est ainsi possible de créer autant d'instantanés que l'on désire. Nous pouvons par exemple réitérer l'opération : créer un instantané, puis copier un fichier dans le répertoire :
# zfs snapshot raid6/home@deuxieme
# cp /etc/X11/xorg.conf /media/sauvegarde/home
L'intérêt de tout cela, c'est qu'il est possible de revenir en arrière. Par exemple, je peux revenir à l'état initial en utilisant la commande zfs rollback raid6/home@premier ou encore à l'état juste avant la copie de mon dernier fichier avec zfs rollback raid6/home@deuxieme. Mieux, il est même possible d'obtenir la différence avec la commande zfs send -i raid6/home@premier raid6/home@deuxieme > diff. Dans l'exemple, il s'agit du fichier /etc/passwd copié entre les prises des instantanés. Cette différence pourra être relue avec la commande zfs receive qui créera alors un instantané correspondant à ce qui lui a été envoyé.
Ces deux dernières commandes peuvent être utilement combinées avec ssh pour, par exemple, générer des sauvegardes différentielles et les envoyer sur un serveur distant.
6. Après un redémarrage
Dans le cas où vous avez redémarré votre machine, votre beau système de fichiers ZFS n'est plus présent. Que faire pour le retrouver ? Comment se souvenir, après quelques jours, mois (ou années) quelle configuration vous aviez utilisée, les disques de spare, raidz1, raidz2, mirror ou pas, le point de montage ?
Avec ZFS, rien de plus simple. Après avoir chargé le module fuse et redémarré le démon zfs-fuse, rendez-vous directement dans le dossier où vous avez créé vos fichiers (les faux disques) et tapez la commande zpool import -d ..
Cette commande recherche, parmi les fichiers du dossier courant (« . »), les périphériques virtuels (vdev), puis elle indique le nom et la configuration de chaque pool trouvé parmi ces périphériques. Pour importer réellement un pool, nommez-le à la fin de la commande, par exemple : zpool import -d . raid6 . Après quelques instants, le système de fichiers est à nouveau monté (sur le bon point de montage) et prêt à être utilisé.
Si le système de fichiers n'est pas monté correctement, vérifiez que vous avez bien le module fuse chargé (modprobe fuse), que vous avez bien lancé le démon zfs-fuse (zfs-fuse –no-daemon) et que les répertoires sur lesquels sont montés vos systèmes de fichiers ZFS sont vides.
7. En conclusion
Cet article n'a pas fait le tour de toutes les fonctionnalités et propriétés de ZFS. Aussi, le lecteur curieux pourra regarder de près le système de clones et les permissions liées à l'administration par exemple.
Il est vraiment dommage que ce système de fichiers ne puisse être inclus nativement dans le noyau GNU/Linux par la faute d'une bête incompatibilité de licence...
Bien entendu, tout ce qui est décrit dans cet article est réalisable nativement, c'est-à-dire sans fuse et son démon zfs-fuse, sous FreeBSD 7.0, Solaris 10, Mac OS X et, me souffle-t-on, Nexenta [11].
Je tiens à remercier mes mentors qui ont été attentifs aux erreurs et imprécisions et m'ont patiemment relu et corrigé : Bruno Bonfils, Guillaume Lelarge et Sébastien Tricaud.
Références
[0] http://opensolaris.org/os/community/zfs/source/
[2] http://www.opensolaris.org/os/licensing/cddllicense.txt
[3] http://blogs.sun.com/bonwick/date/20040925#128_bit_storage_are_you
[4] http://www.freebsd.org/releases/7.0R/announce.html
[6] https://developer.berlios.de/project/showfiles.php?group_id=6836
[7] http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
[8] http://www.manpagez.com/man/8/zpool/
[9] http://docs.sun.com/app/docs/doc/817-2271/gazss?l=en&a=view
[10] http://opensolaris.org/os/community/zfs/docs/
[11] http://foss-boss.blogspot.com/2008/11/nexenta-can-you-say-solabuntu-part1.html