If it works, Dante will fix it !

Aller au contenu | Aller au menu | Aller à la recherche

samedi 17 octobre 2009

ZFS et USB 2. Resilvering et vdev failure

Comme indiqué dans mon billet précédent, je possède des disques durs USBs utilisés dans un zpool[1].

Il peut arriver qu'on ai des erreurs ZFS: vdev I/O failure lors du resilvering d'un disque entier. Et ce, au remplacement d'un disque dur USB ou à celui d'un disque SATA en couple avec un disque dur USB.

Cela a pour conséquences le freeze du zpool et des utilitaires zfs, et aussi de la led du boitier USB dans mon cas (elle reste rouge en mode "activité"). La manière la plus simple de débloquer la situation est de rebooter le boitier USB. Une fois le disque dur redémarré, le resilvering reprend depuis le début... et on se retrouve ainsi coincé dans une boucle sans fin.

Pour éviter ce genre de problème, on peut modifier la propriété failmode du zpool concerné. Pour cela, on l'export puis l'import en modifiant la propriété de la façon suivante :

zpool export tank
zpool import -o failmode=continue tank

Par défaut[2], le mode est wait. Ce qui fait que lors d'une erreur I/O, le système attend que l'utilisateur rebranche ou remplace le disque concerné et effectue un zpool replace/clear. Or dans notre cas, il s'agit d'une erreur ponctuelle causée par le boitier USB ou le driver umass.

Une fois le resilvering complété, vous pouvez exporter puis importer le zpool sans options pour repasser en failmode wait. Si jamais vous avez régulièrement ce genre d'erreurs, vous pouvez laisser votre zpool en failmode continue mais cela peut cacher l'apparition d'un vrai problème matériel.

Notes

[1] Je déconseille ce genre d'utilisation, préférez acquérir une carte pci-e e-sata avec les boitiers qui vont bien par exemple.

[2] Sous FreeBSD-7.2

ZFS et USB. Erreur sur la synchronisation du cache

J'ai un vieux serveur que j'utilise comme entité de stockage et sauvegarde. La carte mère n'étant pas très récente (A7N8X-X), il n'y a pas de port SATA à disposition. J'ai donc acheté une carte promise TX4 qui marche à perfection. Manquant d'espace, je me suis aussi procuré deux boitiers externes USB Cooler Master X-Craft 350.

Le tout est dans un même zpool avec une configuration mirror.

Seul souci : les disques durs USB flood mon dmesg avec l'erreur suivante :

(da0:umass-sim0:0:0:0): SYNCHRONIZE CACHE(10). CDB: 35 0 0 0 0 0 0 0 0 0 
(da0:umass-sim0:0:0:0): CAM Status: SCSI Status Error
(da0:umass-sim0:0:0:0): SCSI Status: Check Condition
(da0:umass-sim0:0:0:0): ILLEGAL REQUEST asc:20,0
(da0:umass-sim0:0:0:0): Invalid command operation code
(da0:umass-sim0:0:0:0): Unretryable error

Pour m'en débarrasser il m'a suffit d'indiquer au driver umass le fait que ces disques ne supporte pas l'opération SYNCHRONIZE CACHE.

J'ai tout d'abord récupéré les codes vendor et product du chipset sata des boitiers.

lsusb # Présent dans le port sysutils/usbutils
Bus /dev/usb Device /dev/ugen2.2: ID 152d:2338 JMicron Technology Corp. / JMicron USA Technology Corp. JM20337 Hi-Speed USB to SATA & PATA Combo Bridge
Bus /dev/usb Device /dev/ugen5.2: ID 152d:2338 JMicron Technology Corp. / JMicron USA Technology Corp. JM20337 Hi-Speed USB to SATA & PATA Combo Bridge

Voici donc mes deux boitiers externes, 152d correspond au code vendor et 2338 au code product Je vais ensuite éditer le fichier /usr/src/sys/dev/usb/usbdevs :

Y ajouter le vendor JMicron :

...
vendor UBIQUAM          0x1529  UBIQUAM Co., Ltd.
vendor JMICRON          0x152d  JMicron Technology Corp.
vendor UBLOX            0x1546  U-blox
...

Et la catégorie lui correspondant avec le produit JM20337 :

/* Jaton products */
....

/* JMicron products */
product JMICRON JM20337         0x2338  Hi-Speed USB to SATA & PATA Combo Bridge

/* JVC products */
....

Ensuite, dans /usr/src/sys/dev/usb/storage/umass.c J'indique que ce produit ne support pas la synchronisation du cache :

{USB_VENDOR_JMICRON, USB_PRODUCT_JMICRON_JM20337, RID_WILDCARD,
        UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
        NO_SYNCHRONIZE_CACHE
},
{USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_L3, RID_WILDCARD,
...

Puis on recompile et réinstalle le kernel:[1]

cd /usr/src
make buildkernel
make installkernel

Et on redémarre dessus.

Notes

[1] Il est aussi possible de ne faire recompiler que le module umass avec l'option MODULES_OVERRIDE, voir le handbook pour plus de détails.

Mise à Jour Freebsd de 7.2 à 8.0-RC1 avec une racine en ZFS

Les mises à jour avec une racine ZFS ne sont jamais évidentes. En ce qui concerne le passage de FreeBSD 7 à 8 il y a une petite astuce à connaître. En effet le userland 7 n'étant pas compatible avec le kernel 8, il n'est pas possible d'utiliser les utilitaires zfs lors du premier redémarrage sur le nouveau kernel; démarrage qui se fait en mode single user.

Ainsi, pour monter la racine de votre système, veuillez tapez la commande suivante :

mount -t zfs tank/racine /

Au lieu de vous battre avec la commande zfs et l'erreur de mémoire qui en résulte. Pour rappel, la mise à jour peut être binaire ou source.

samedi 31 janvier 2009

Affichage cassé lors d'un make config

Il s'agit du genre de bug spécifique à ma personne :)

Pour information :

make -j8 config

Casse l'affichage et ne permet pas de sélectionner les options. Pour y remédier, il est intéressant de rajouter le code suivant dans votre /etc/make.conf :

.if !(make(*install) || make(package))
MAKE_ARGS+=-j8
.endif

Bon, le second problème qui peut arriver est que certaines applications n'aiment pas la compilation en parallèle, donc pour les exclure :

.if ${.CURDIR:M*/converters/libiconv} || ${.CURDIR:M*/devel/gperf} || ${.CURDIR:M*/lang/perl5.8} || ${.CURDIR:M*/x11-toolkits/gtk20} || ${.CURDIR:M*/lang/python25}
MAKE_ARGS:=${MAKE_ARGS:C/-j8//}
.endif

Et voilà !

jeudi 11 décembre 2008

Migration d'une gentoo LVM-Reiserfs à une Freebsd ZFS - Partie I

Le but de ce post est principalement de me faire un pense-bête car avant d'effectuer la migration sur la machine finale, je vais d'abord tenter de reproduire cette configuration dans une virtualbox kvm, étant donné que virtualbox supporte très mal freebsd sur un hôte linux.

Recommandations

Attention, même si le but de ce post est d'éviter de devoir acheter plus de stockage afin de faire des backups, il est à suivre à vos risques et périls. De plus, je recommande vivement la lecture préalable des liens suivants :

La configuration initiale

Configuration système :

  • Gentoo 32bit
  • Athlon XP
  • 1 Go de Ram

Stockage

  • 1 disque dur de 120Go : Racine + Home
  • 1 disque dur de 400Go: lvm
  • 1 disque dur de 750Go : lvm

Les logical volumes du lvm sont tous formatés en reiserfs.

La configuration finale

Configuration système :

  • FreeBSD 7.0 (i386)
  • 3 Go de Ram (pour subvenir aux besoins de ZFS)

Stockage

  • 2 disques durs de 160Go (ad0 et ad1)
    • Pour remplacer le vieux de 120
    • Contiendra le /boot et le premier zpool : system
  • 2 disques durs de 400Go (ad2 et ad4): zpool tank
  • 2 disques durs de 750Go (ad3 et ad5) : zpool tank

Zpools

Il y aura 2 zpools. Le premier system sera en mirroring, contiendra l'ensemble des partitions systèmes (/, /var, /tmp...) et le /home.
Le second tank Contiendra les données déjà présentes dans le lvm. Il sera en z-raid, sachant qu'à terme, deux autres disques durs de 400Go et 750 Go seront rajoutés (en attendant, ce sera la même chose qu'un mirror).

Ce qu'il y a à faire

La difficulté réside dans l'installation de la racine freebsd dans un zpool mirror, mais aussi le paramétrage du boot manager : gestion intelligente de la présence de /boot sur les disques en mirroring) et enfin, la sauvegarde des données : données présentes sur du lvm/reiserfs, espace disque limité, création des zpool avec un seul disque.

Première installation

Du fait que les librairies pour zfs ne semblent pas être présentes sur le livecd, je n'ai pas trouvé d'autre solution que d'installer FreeBSD de façon normale pour ensuite créer le zpool system et y copier les fichiers.

Donc on va installer freebsd sur ad0 (le plus grand!), il n' a pas de consigne particulière si ce n'est que les fichiers correspondront à l'installation finale.
Pour le partitionnement, j'ai tout mis en automatique, cela me permettra de faire la même séparation dans le zpool system (/,/var,/tmp,/usr).
J'ai choisi l'ensemble de paquet "User", car on aura besoin des sources du kernel pour le recompiler. Penser à installer :

  • editor/vim-lite (sans les gui) si besoin
  • net/rsync
  • screen (non présent sur le cd)

Tuning du système

Une fois le système installé, on va tout d'abord le tuner pour faire marcher zfs (cf. TuningZFS). Cela comprend une recompilation du kernel. Vous devez donc d'abord récupérer les sources du kernel. Dans le cas où vous voudriez ensuite faire marcher un lvm, veuillez prendre les sources du kernel avec cvsup pour avoir celles de la 7.0-STABLE, il vous faut src-base, src-sys et src-crypto.

On ajoute dans le /boot/loader.conf ceci :
zfs_load="YES"
vm.kmem_size="512M"
vm.kmem_size_max="512M"
vfs.zfs.arc_max="100M"

On recompile le kernel en rajoutant la ligne options KVA_PAGES="512" et options GEOM_LINUX_LVM (si besoin) dans le fichier de config et on ajoute zfs_enable="YES" dans le /etc/rc.conf.

Ensuite, on reboot.

Création du zpool system

On créé zpool system sur ad1 (160-2), pour cela suit les instructions de ZFSOnRoot, il peut-être intéressant d'avoir le swap hors du ZFS tout comme le /boot (cf. ZFS Best Practices Guide).

Partitionnement de ad1 (160-2)

On initialise le disque avec un seul slice bootable :

fdisk -BI /dev/ad1

Puis on créé les partitions dans le slice ad1s1 :

bsdlabel -wB /dev/ad1s1
bsdlabel -e /dev/ad1s1

Ceci permet d'avoir un /boot a de 512Mo, un swap b de 2Go et le reste d pour le zpool system :

# /dev/ad1s1:
8 partitions:
# size offset fstype [fsize bsize bps/cpg]
a: 1048576 0 unused 2048 16384
b: 4142688 1048576 swap
c: * 0 unused 0 0 # "raw" part, don't edit
d: * * unused 2048 16384

Ensuite on créé le zpool system :

zpool create system ad1s1d

On indique au bootloader où se trouve la racine et on active zfs en ajoutant :

vfs.root.mountfrom="zfs:system"
dans le /boot/loader.conf

On créé le répertoire qui contiendra le /boot :

mkdir /system/bootdir1
cd /system
ln -s bootdir1/boot /system/boot

On formate /dev/ad1s1a :

newfs /dev/ad1s1a
mount /dev/ad1s1a /system/bootdir1

J'ai ensuite suivi les instructions de cette page ZFSQuickStartGuide. J'ai ainsi créé les dossiers tmp,var,home et usr dans le zpool system.

zfs create system/usr
zfs create system/tmp
zfs create system/var
zfs create system/home

Puis j'ai copié les fichiers depuis ad0 avec vers le zpool :

rsync -Pia --exclude=system --exclude=boot /* /system/
cp -Rp /boot /system/bootdir1/

Puis on oublie pas de configurer les points de montages de toutes les partitions :

zfs set mountpoint=/tmp system/tmp
zfs set mountpoint=/usr system/usr
zfs set mountpoint=/home system/home
zfs set mountpoint=/var system/var

On modifie le fstab du nouveau système /system/etc/fstab afin qu'il ne contienne que ceci :
/dev/ad1s1b none swap sw 0 0
/dev/ad1s1a /bootdir1 ufs rw 1 1
/dev/acd0 /cdrom cd9660 ro,noauto 0 0

Puis on paramètre le point de montage en legacy pour que le ZFS ne tente de le monter tout seul :

umount /system/bootdir1/
zfs set mountpoint=legacy system

Et enfin, on reboot sur 160-2 (ad1), un paramétrage du bios est sûrement nécessaire pour qu'il ignore 160-1. Il n'y a plus qu'à croiser les doigts.

Finalisation du zpool system

Ensuite, on recopie le bsdlabel de ad1 sur ad0 en ce qui concerne le bsdlabel : bsdlabel -wB /dev/ad0s1
bsdlabel /dev/ad1s1 > savedlabel
bsdlabel -R /dev/ad0s1 savedlabel

Puis on attache le disque en mirror :
zpool attach system ad1s1d ad0s1d
(L'ordre des partitions est important).

Et on rajoute le swap se trouvant sur ad0 et le boot dans /etc/fstab :

mkdir /bootdir0
/dev/ad0s1b none swap sw 0 0
/dev/ad0s1a /bootdir0 ufs rw 1 1

On effectue une copie :
cp -Rp /bootdir1/boot /bootdir0/

Et on va privilégier le /boot se trouvant sur ad0 :

rm -f /boot
ln -s /bootdir0/boot /boot

Il faudra donc penser à mettre à jour bootdir1 si on modifie le /boot.

Malheureusement, si un disque crash, la Freebsd ne sera pas capable de booter sans intervention, car le fait de ne pas arriver à monter des partitions dans le fstab bloque le processus de démarrage. Celui-ci peut-être repris et la FreeBSD démarrée, mais pas sans une intervention humaine. Seule solution trouvée à ce jour : enlever les swap et /boot du fstab et ajouter un script rc.d qui se charge de faire les swapon et les mount au démarrage.

/etc/rc.d/my_mountfs :
#!/bin/sh

. /etc/rc.subr

name="my_mountfs"
start_cmd="${name}_start"
stop_cmd="${name}_stop"

my_mountfs_start()
{
swapon /dev/ad1s1b
swapon /dev/ad0s1b
mount /dev/ad0s1a /bootdir0
mount /dev/ad1s1a /bootdir1
}

my_mountfs_stop()
{
swapoff /dev/ad1s1b
swapoff /dev/ad0s1b
umount /dev/ad0s1a
umount /dev/ad1s1a
}

load_rc_config $name
run_rc_command "$1"