venerdì 18 dicembre 2009

ZFS: always consistent on disk (parte 3)

Terminiamo questa serie di articoli (parte 1, parte 2) sulla consistenza su disco di ZFS analizzando una comoda proprietà impostabile a livello di filesystem che ci consente di aumentare le probabilità di ripristino di un file in caso di errore anche avendo a disposizione un solo disco fisso. Purtroppo in molti casi ci è impossibile disporre di un secondo disco per impostare il mirroring a livello di pool; pensate ad esempio ai portatili, potrei aggiungere come secondo disco di mirror un disco esterno collegato via USB, ma le prestazioni ne risentirebbero!
Grazie alla proprietà copies, impostabile a livello di filesystem, possiamo indicare a ZFS quante copie deve fare di ogni singolo blocco dati, nel caso in cui uno di questi blocchi fosse danneggiato ZFS provvederà a recuperarlo dalla seconda copia così come avrebbe fatto da un secondo disco. Il limite massimo di copie impostabili è pari a tre.

ATTENZIONE: i test comportano l’alterazione dei dati presenti nei dischi utilizzati nei pool, quindi effettuate questi test su filesystem di prova, che non contengono dati e sopratutto A VOSTRO RISCHIO E PERICOLO!!!!



Andiamo a valutare il comportamento di ZFS in caso di alterazione del disco come visto negli altri esempi.
Cominciamo creando il nostro pool di test con un solo disco:
$ mkfile 150m disk1
$ pfexec zpool create testPool `pwd`/disk1

impostiamo a due il numero delle copie settando l'apposita opzione in fase di creazione del filesystem:
$ pfexec zfs create -o copies=2 testPool/fs1

copiamo il solito file di test e rileviamo l'Object-ID e il DVA del primo blocco dati:
$ pfexec cp /etc/bash/bash_completion /testPool/fs1/
$ ls -li /testPool/fs1/
total 1
5 -rwxr-xr-x 1 root root 217434 2009-12-16 11:37 bash_completion*
$ pfexec zdb -ddddd testPool/fs1 5
Dataset testPool/fs1 [ZPL], ID 30, cr_txg 6, 547K, 5 objects,
rootbp DVA[0]=<0:5c800:200> DVA[1]=<0:1c5c800:200> DVA[2]=<0:3814a00:200> [L0 DMU objset]
fletcher4 lzjb LE contiguous unique triple size=800L/200P
birth=10L/10P fill=5
cksum=155932587a:748a6697e34:1521b17e820db:2b3b6c4032fb3a

Object lvl iblk dblk dsize lsize %full type
5 2 16K 128K 515K 256K 100.00 ZFS plain file
264 bonus ZFS znode
dnode flags: USED_BYTES USERUSED_ACCOUNTED
dnode maxblkid: 1
path /bash_completion
uid 0
gid 0
atime Wed Dec 16 11:37:03 2009
mtime Wed Dec 16 11:37:03 2009
ctime Wed Dec 16 11:37:03 2009
crtime Wed Dec 16 11:37:03 2009
gen 10
mode 100755
size 217434
parent 3
links 1
xattr 0
rdev 0x0000000000000000
Indirect blocks:
0 L1 0:5a000:400 4000L/400P F=2 B=10/10
0 L0 0:19e00:20000 20000L/20000P F=1 B=10/10
20000 L0 0:39e00:20000 20000L/20000P F=1 B=10/10

segment [0000000000000000, 0000000000040000) size 256K

frammentiamo, sporchiamo e ricostruiamo il disco come al solito:
$ pfexec zpool export testPool
$ ./zsplit.sh disk1 0x19e00
8399+0 records in
8399+0 records out
4300288 bytes (4.3 MB) copied, 0.100184 s, 42.9 MB/s
256+0 records in
256+0 records out
131072 bytes (131 kB) copied, 0.00666101 s, 19.7 MB/s
298545+0 records in
298545+0 records out
152855040 bytes (153 MB) copied, 3.43945 s, 44.4 MB/s
$ head disk1-p2
#
# This file contains an example set of shell completions that can be used with
# bash(1). These completions allow a user to complete filenames, commands
# name, command line options, and command line arguments using the [tab] key.
# The completions defined here are specific to the GNU command set, as a result
# they will provide the choice of GNU command line options in response to the
# [tab] key. For the completed options to match the command implementation,
# you may have to have /usr/gnu/bin at the head of your PATH.
#
# These completions are not included in the default bash(1) environment. To
$ sed "s/ file / FILE /g" disk1-p2 > disk1-p2-bad
$ cat disk1-p1 disk1-p2-bad disk1-p3 > disk1

ora non ci resta che accedere nuovamente al file e vedere come si comporta ZFS:
$ pfexec zpool import -d `pwd` testPool
$ zpool status testPool
pool: testPool
state: ONLINE
scrub: none requested
config:

NAME STATE READ WRITE CKSUM
testPool ONLINE 0 0 0
/export/home/luca/itl-osug/zfs/disk1 ONLINE 0 0 0

errors: No known data errors
$ head /testPool/fs1/bash_completion
#
# This file contains an example set of shell completions that can be used with
# bash(1). These completions allow a user to complete filenames, commands
# name, command line options, and command line arguments using the [tab] key.
# The completions defined here are specific to the GNU command set, as a result
# they will provide the choice of GNU command line options in response to the
# [tab] key. For the completed options to match the command implementation,
# you may have to have /usr/gnu/bin at the head of your PATH.
#
# These completions are not included in the default bash(1) environment. To
$ zpool status testPool
pool: testPool
state: ONLINE
status: One or more devices has experienced an unrecoverable error. An
attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace'.
see: http://www.sun.com/msg/ZFS-8000-9P
scrub: none requested
config:

NAME STATE READ WRITE CKSUM
testPool ONLINE 0 0 0
/export/home/luca/itl-osug/zfs/disk1 ONLINE 0 0 1

errors: No known data errors

benissimo, ZFS è riuscito a recuperare il contenuto del file dalla seconda copia e ci informa dell'accaduto, spetterà poi a noi valutare se è giunti il momento di sostituire il disco!
Ricordate che è possibile variare il numero di copie impostando l'apposita opzione:
$ pfexec zfs set copies=3 testPool/fs1

tuttavia il nuovo numero di copie riguarderà solo i nuovi file che verranno scritti o modificati dopo la modifica della proprietà.