Piccola guida completa per l'uso di ZFS
Cosa trovi qui
Questa guida mira a offrire le seguenti conoscenze pratiche:
- cosa è ZFS e quali concetti gli danno forma
- essere capaci di installarlo
- ottenre la competenza per creare un pool con N dataset
- getire i dischi di un pool ZFS.
Introduzione necessaria (ma utile?)
ZFS (Zettabyte File System) è un fantastico filesystem. Per scoprire le sue origini e conoscere i suoi limiti può aiutare WikiPedia: https://it.wikipedia.org/wiki/ZFS_(file_system)
Si tratta di un FileSystem fisico, non di rete, pertanto funziona solo con i dischi interno di un computer e non con dischi esterni, connessi via rete come, ad esempio, GlusterFS.
Nasce con l'idea di astrarre i dati dal disco fisico:
- se con ZFS vedo 4TB di spazio sotto, fisicamente, possono esserci più dischi
- è possibile aggiungere, sostituire, togliere dischi in modo trasparente all'utente e senza interruzione di servizio
- i dischi sotto ZFS possono essere di diverse tecnologie e dimensioni.
Supporta la ridondanza: pertanto, soddisfatti i requisiti, posso perdere uno o più dischi senza perdere nessun dato.
Il tutto senza dover ricorrere ad hardware specializzato (come i costosi controller RAID) e offrendo delle prestazioni eccellenti entro i limiti fisici dei BUS.
Tutto questo, però, ha un costo:
- ZFS usa molta RAM per ottenere questi risultati
- a seconda dei requisiti non è possibile rinunciare ad hardware specializzato.
Possiamo dire, con una battuta, che ZFS porta al limite le possibilità dell'hardware che abbiamo, ma non fa miracoli (anche se possono sembrare miracoli).
Come gestisce lo spazio disco?
ZFS si basa su 2 concetti:
- i dischi sono aggregati in pool. Un pool è costituito da uno o più hard disk (o partizioni di dischi). In un server possiamo ave più pool, magari creati sulla logica dello scopo d'uso (es: dati, homes, databases, ecc...). Questo spazio può essere usato direttamente, ma di norma si creano dei dataset;
- i dataset li possiamo immaginare come partizioni di un disco (più correttamente di un pool). Il dataset è l'oggetto montato e usato per scrivere file.
Come montare un pool o un dataset?
Dobbiamo sapere che ZFS crea automaticamente un mount-point alla creazione di un pool o di un dataset. Inoltre il montaggio non viene fatto dal file ''/etc/fstab '', ma viene scritto nei metadati. Pertanto il punto di montaggio lo definiamo manipolanto il pool o il dataset del nostro ZFS. Ad ogni manipolazione del nostro ZFS e al riavvio del nostro server tutto verrà montato automaticamente.
Nota 1: ZFS funziona su Oracle (una volta Solaris) su Linux, BSD e svariati OS UNIX. Un porting per Windows al momento non c'è.
Nota 2: pur scrivento "ZFS" in realtà useremo OpenZFS, ovvero il porting per i sistemi Linux.
Scenario dei training
Tutti i contenuti che seguono si riferiscono al seguente ambiente virtualizzato in un hypervisor KVM:
- OS
+ Ubuntu Server 24.03
+ installato nel disco vda da 16GB
- 10 HDD da 1GB (VDB, VDC, ecc..)
- le operazioni descritti saranno tutte eseguite da un terminale ssh
- la VM di demo si chiama VM05.
Installazione
Prima di iniziare è necessario dire che per motivi di licenza non è possibile installare ZFS nel kernel. Per uso NON professionale non vedremo significative differenze. In caso di server con OS Linux la questione ha uno spessore.
Iniziamo:
- colleghiamoci al nostro server via ssh
- installiamo ZFS
```
sudo apt install -y zfsutils-linux
```
Installazione fatta!!
Si può vedere il modulo installato
```
lsmod |grep zfs
zfs 6602752 6
spl 180224 1 zfs
```
o un tool in esecuzione
```
zpool list
no pools available
```
RAID-Z
Gli RAID-Z sono una variante del RAID 5, quindi un array RAID potenziato con le peculiarità ZFS (compressione trasparente, transazioni, ecc...) e, a parità di hardware, più efficiente di ``mdadm``. Come ``mdadm`` non è necessario un controller hardware RAID dedicato.
Sostenzialmente condivide le stesse virtù e limiti di ``mdadm``. Il limite più grande è la rigidità e la limitata malleabilità degli array.
Prima di passare all'operatività vale la pena di indicare che ZFS ha anche il dRAID ( https://openzfs.github.io/openzfs-docs/Basic%20Concepts/Pool%20Structure/dRAID%20Howto.html ed https://docs.google.com/presentation/d/1uo0nBfY84HIhEqGWEx-Tbm8fPbJKtIP3ICo4toOPcJo/edit?slide=id.p1#slide=id.p1 ), una variante di RAID-Z che lo migliora ulteriormente.
Non lo tratteremo.
Da dire anche che ZFS implementa alcune tipologie specifiche di RAID (RAIDZ1, RAIDZ2): non li tratteremo.
Prima di passare alla parte eseguibile vediamo la composizione dei sichi nella nostra VM;
```
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sr0 11:0 1 2K 1 rom
vda 253:0 0 32G 0 disk
├─vda1 253:1 0 1G 0 part /boot/efi
└─vda2 253:2 0 30.9G 0 part /
vdb 253:16 0 1G 0 disk
vdc 253:32 0 1G 0 disk
vdd 253:48 0 1G 0 disk
vde 253:64 0 1G 0 disk
vdf 253:80 0 1G 0 disk
vdg 253:96 0 1G 0 disk
vdh 253:112 0 1G 0 disk
vdi 253:128 0 1G 0 disk
vdj 253:144 0 1G 0 disk
vdk 253:160 0 1G 0 disk
```
Creazione di un RAID-Z
Creiamo un pool RAID-Z con i dischi da vdb a vdg:
```
sudo zpool create test1 raidz vdb vdc vdd vde vdf vdg
sudo zfs set mountpoint=none test1
```
Se non abbiamo visto alcun messaggio di output vuol dire che tutto è andato ok.
Quindi vediamo il pool creato che non è montato né ha un punto di montaggio.
```
zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
test1 5.50G 212K 5.50G - - 0% 0% 1.00x ONLINE -
zpool status test1
pool: test1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
test1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
vdb ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
errors: No known data errors
zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 176K 4.42G 36.5K none
zfs get all test1
NAME PROPERTY VALUE SOURCE
test1 type filesystem -
test1 creation Fri Sep 18 19:44 2026 -
test1 used 176K -
test1 available 4.42G -
test1 referenced 36.5K -
test1 compressratio 1.00x -
test1 mounted no -
test1 quota none default
test1 reservation none default
test1 recordsize 128K default
test1 mountpoint none local
test1 sharenfs off default
test1 checksum on default
test1 compression on default
test1 atime on default
test1 devices on default
test1 exec on default
test1 setuid on default
test1 readonly off default
test1 zoned off default
test1 snapdir hidden default
test1 aclmode discard default
test1 aclinherit restricted default
test1 createtxg 1 -
test1 canmount on default
test1 xattr on default
test1 copies 1 default
test1 version 5 -
test1 utf8only off -
test1 normalization none -
test1 casesensitivity sensitive -
test1 vscan off default
test1 nbmand off default
test1 sharesmb off default
test1 refquota none default
test1 refreservation none default
test1 guid 14602359646799777781 -
test1 primarycache all default
test1 secondarycache all default
test1 usedbysnapshots 0B -
test1 usedbydataset 36.5K -
test1 usedbychildren 139K -
test1 usedbyrefreservation 0B -
test1 logbias latency default
test1 objsetid 54 -
test1 dedup off default
test1 mlslabel none default
test1 sync standard default
test1 dnodesize legacy default
test1 refcompressratio 1.00x -
test1 written 36.5K -
test1 logicalused 46.5K -
test1 logicalreferenced 12K -
test1 volmode default default
test1 filesystem_limit none default
test1 snapshot_limit none default
test1 filesystem_count none default
test1 snapshot_count none default
test1 snapdev hidden default
test1 acltype off default
test1 context none default
test1 fscontext none default
test1 defcontext none default
test1 rootcontext none default
test1 relatime on default
test1 redundant_metadata all default
test1 overlay on default
test1 encryption off default
test1 keylocation none default
test1 keyformat none default
test1 pbkdf2iters 0 default
test1 special_small_blocks 0 default
```
Creazione di un dataset
Creiamo ora 3 dataset, ovvero 3 partizioni che possono essere montate e usate.
Li monteremo nei path ``/opt/zfs/test1/fix``, ``/opt/zfs/test1/var`` e ``/opt/zfs/test1/comp``.
- Creiamo il dataset ``fix`` con una quota di 1G:
```
$ sudo zfs create -o quota=1G -o mountpoint=/opt/zfs/test1/fix test1/fix
```
- creiamo ora il dataset ``var`` senza nessuna quota:
```
$ sudo zfs create -o mountpoint=/opt/zfs/test1/var test1/var
```
- creiamo anche un dataset compresso senza quota:
```
$ sudo zfs create -o compression=on -o mountpoint=/opt/zfs/test1/comp test1/comp
```
- vediamo il lavoro fatto
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 358K 4.42G 36.5K none
test1/comp 36.5K 4.42G 36.5K /opt/zfs/test1/comp
test1/fix 36.5K 1024M 36.5K /opt/zfs/test1/fix
test1/var 36.5K 4.42G 36.5K /opt/zfs/test1/var
```
- e il dettaglio di ogni dataset (output omesso per eccesso di lungaggine)
```
$ zfs get all test1/comp
[...]
$ zfs get all test1/fix
[...]
$ zfs get all test1/var
[...]
```
- e, infine, usiamo l'antico ``df`` per avere un semplice e sorprendente report
```
$ df -h
Filesystem Size Used Avail Use% Mounted on
[...]
test1/fix 1.0G 128K 1.0G 1% /opt/zfs/test1/fix
test1/var 4.5G 128K 4.5G 1% /opt/zfs/test1/var
test1/comp 4.5G 128K 4.5G 1% /opt/zfs/test1/comp
```
Facciamo due considerazioni:
- secondo ``df`` dal nostro pool RAID-Z abbiamo a disposizione 1G+4.5G+4.5G (in totale 10G)
- il ppol RAID-Z ha una capienza massima di 4.5G
- in realtà l'output che vediamo significa: il dataset ha ancora a disposizione NN bytes
- quinti i dataset usano la risorsa pool per interno secondo le regole che gli diamo (un massimo fisso o variabile)
- unica semi-eccezzione è il dataset compresso: l'algoritmo riduce lo spazio effetivo usato dai file in base alla loro riduzione per comprensione, ma questo significa che ogni accesso necessita di un tempo di compressione-decompressione.
Questo primo passo ci porta a concetti più complessi:
- felessibilità: molto dipende dalle conoscenze dell'amministratore e delle logiche che implementa
- in ZFS astrarci dal dispositivo fisico significa che il POOL divenda l'equivalente del dispositivo fisico
- ZFS offre una gestione molto flessibile e, per questo, non sempre immediata nella compeìrensione.
Montare il dataset
Lo stato raggiunto dal passo precedente è rappresentabile da questi due comandi;
```
$ mount
[...]
test1/fix on /opt/zfs/test1/fix type zfs (rw,relatime,xattr,noacl,casesensitive)
test1/var on /opt/zfs/test1/var type zfs (rw,relatime,xattr,noacl,casesensitive)
test1/comp on /opt/zfs/test1/comp type zfs (rw,relatime,xattr,noacl,casesensitive)
$ ls -lh /opt/zfs/test1/
total 1.5K
drwxr-xr-x 2 root root 2 Sep 18 20:05 comp
drwxr-xr-x 2 root root 2 Sep 18 19:59 fix
drwxr-xr-x 2 root root 2 Sep 18 20:02 var
```
i dataset sono già montati, ma in ``/etc/fstab`` non c'è nessuna riga. Questo accade perché il kernel legge direttamente dal file-system il montaggio.
Vogliamo ora rimuove "var" dai montaggi automatici e modificare il punto di montaggio ``comp`` in ``compresso``:
- togliamo il mountpoint in ZFS per il dataset ``var``. Il comando smonta automaticamente il dataset
```
$ sudo zfs set mountpoint=none test1/var
```
- creiamo il nuovo mount-point per il dataset "comp". Il comando automaticamente smonta il dataset e lo rimonta sempre automaticamente:
```
$ sudo zfs set mountpoint=/opt/zfs/test1/compresso test1/comp
```
Monitorare
Per vedere lo stato dei pool e dei dataset abbiamo alcuni comandi:
- iniziamo chiedendo l'elenco dei pool
```
$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
test1 5.50G 476K 5.50G - - 0% 0% 1.00x ONLINE -
```
- chiediamo ora l'elenco dei dataset
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 395K 4.42G 36.5K none
test1/comp 36.5K 4.42G 36.5K /opt/zfs/test1/compresso
test1/fix 36.5K 1024M 36.5K /opt/zfs/test1/fix
test1/var 36.5K 4.42G 36.5K none
```
- a questo punto abbiamo l'elenco dei pool e dei dataset. Vediamo lo stato del nostro pool
```
$ zpool status
pool: test1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
test1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
vdb ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
errors: No known data errors
```
- per vedere le proprietà del pool e dei dataset abbiamo il comando ``get``
```
$ zfs get all
NAME PROPERTY VALUE SOURCE
test1 type filesystem -
test1 creation Fri Sep 18 19:44 2026 -
test1 used 395K -
test1 available 4.42G -
test1 referenced 36.5K -
test1 compressratio 1.00x -
test1 mounted no -
test1 quota none default
[...]
test1/comp type filesystem -
test1/comp creation Fri Sep 18 20:05 2026 -
test1/comp used 36.5K -
test1/comp available 4.42G -
test1/comp referenced 36.5K -
test1/comp compressratio 1.00x -
test1/comp mounted no -
test1/comp quota none default
[...]
test1/fix type filesystem -
test1/fix creation Fri Sep 18 19:59 2026 -
test1/fix used 36.5K -
test1/fix available 1024M -
test1/fix referenced 36.5K -
test1/fix compressratio 1.00x -
test1/fix mounted yes -
test1/fix quota 1G local
[...]
test1/var type filesystem -
test1/var creation Fri Sep 18 20:02 2026 -
test1/var used 36.5K -
test1/var available 4.42G -
test1/var referenced 36.5K -
test1/var compressratio 1.00x -
test1/var mounted no -
test1/var quota none default
[...]
```
- possiamo avere le proprietà del singolo pool e del singolo dataset:
+ per vedere le proprietà di un singolo pool
```
$ zfs get all test1
NAME PROPERTY VALUE SOURCE
test1 type filesystem -
test1 creation Fri Sep 18 19:44 2026 -
test1 used 395K -
test1 available 4.42G -
test1 referenced 36.5K -
test1 compressratio 1.00x -
test1 mounted no -
test1 quota none default
test1 reservation none default
test1 recordsize 128K default
test1 mountpoint none local
[...]
```
+ per vedere le proprietà di un singolo dataset
```
$ zfs get all test1/fix
NAME PROPERTY VALUE SOURCE
test1/fix type filesystem -
test1/fix creation Fri Sep 18 19:59 2026 -
test1/fix used 36.5K -
test1/fix available 1024M -
test1/fix referenced 36.5K -
test1/fix compressratio 1.00x -
test1/fix mounted yes -
test1/fix quota 1G local
test1/fix reservation none default
test1/fix recordsize 128K default
test1/fix mountpoint /opt/zfs/test1/fix local
[...]
```
L'output degli ultimi tre esempi riportano oltre allo stato delle proprietà anche alcuni dati di stato.
A questo punto creiamo un secondo pool per vedere come monitorare singolarmente i pool e i dataset
- creiamo un nuovo pool ed un paio di dataset
```
$ sudo zpool create test2 raidz vdh vdi vdj vdk
$ sudo zfs set mountpoint=none test2
$ sudo zfs create -o mountpoint=none test2/docs1
$ sudo zfs create -o mountpoint=none test2/docs2
$ sudo zfs create -o mountpoint=none test2/docs3
$ sudo zfs create -o mountpoint=none test2/docs4
```
- vediamo l'elenco dei pool e dei dataset disponibili
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 395K 4.42G 36.5K none
test1/comp 36.5K 4.42G 36.5K /opt/zfs/test1/compresso
test1/fix 36.5K 1024M 36.5K /opt/zfs/test1/fix
test1/var 36.5K 4.42G 36.5K none
test2 411K 2.68G 32.9K none
test2/docs1 32.9K 2.68G 32.9K none
test2/docs2 32.9K 2.68G 32.9K none
test2/docs3 32.9K 2.68G 32.9K none
test2/docs4 32.9K 2.68G 32.9K none
```
- vediamo lo stato del solo pool "test2"
```
$ zpool status test2
pool: test2
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
test2 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
vdh ONLINE 0 0 0
vdi ONLINE 0 0 0
vdj ONLINE 0 0 0
vdk ONLINE 0 0 0
errors: No known data errors
```
- chiediamo le proprietà del solo pool "test2"
```
$ zfs get all test2
NAME PROPERTY VALUE SOURCE
test2 type filesystem -
test2 creation Sat Sep 19 8:49 2026 -
test2 used 411K -
test2 available 2.68G -
test2 referenced 32.9K -
test2 compressratio 1.00x -
test2 mounted no -
test2 quota none default
test2 reservation none default
test2 recordsize 128K default
test2 mountpoint none local
[...]
```
- e, infine, chiediamo le proprietà del solo dataset "docs2"
```
$ zfs get all test2/docs2
NAME PROPERTY VALUE SOURCE
test2/docs2 type filesystem -
test2/docs2 creation Sat Sep 19 8:49 2026 -
test2/docs2 used 32.9K -
test2/docs2 available 2.68G -
test2/docs2 referenced 32.9K -
test2/docs2 compressratio 1.00x -
test2/docs2 mounted no -
test2/docs2 quota none default
test2/docs2 reservation none default
test2/docs2 recordsize 128K default
test2/docs2 mountpoint none local
[...]
```
Quota ad un Pool
Un comportamento saggio è porre una quota globale al pool; quando lo spazio verrà saturato si aggiunge spazio in un momento modificando o togliendo la quota in attesa che arrivino i nuovi harddisk aggiuntivi. Operiamo sul pool "test1":
- iniziamo prendendo visione della capacità totale del pool de della quota impostata
```
zpool list test1
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
test1 5.50G 212K 5.50G - - 0% 0% 1.00x ONLINE -
```
```
$ zfs get quota test1
NAME PROPERTY VALUE SOURCE
test1 quota none local
```
- il nostro pool demo2 ha una capacità di 2,8G e non ci sono quote.
Impostiamo una quota a 2G in modo da avere 0.8G disponibili nelle urgenze di "spazio esaurito"
```
$ sudo zfs set quota=2G test1
```
- verifichiamo lo stato dello spazio disponibile
```
$ zpool list test1
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
test1 5.50G 452K 5.50G - - 0% 0% 1.00x ONLINE -
```
```
$ zfs get quota test1
NAME PROPERTY VALUE SOURCE
test1 quota 2G local
```
Abbiamo posto in limite di spazio usabile a 2G tenedo 3.5G di scorta per le emergenze.
Quota ad un Dataset
La quota ai dataset va pensata come il size di una partizione di un disco con la differenza che in disco è un impostazione rigida e il cambio comporta la distruzione dello spazio, mentre in un dataset è flessibile, non distrittivo e funziona in un istante.
- vediamo i nostri dataset del pool "demo2"
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 375K 2.00G 36.5K /test1
test1/comp 36.5K 2.00G 36.5K /opt/zfs/test1/comp
test1/fix 36.5K 1024M 36.5K /opt/zfs/test1/fix
test1/var 36.5K 2.00G 36.5K /opt/zfs/test1/var
```
- impostiamo una quota a 1G per il dataset comp
```
$ sudo zfs set quota=1G test1/comp
```
- verifichiamo i dataset
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 385K 2.00G 36.5K /test1
test1/comp 36.5K 1024M 36.5K /opt/zfs/test1/comp
test1/fix 36.5K 1024M 36.5K /opt/zfs/test1/fix
test1/var 36.5K 2.00G 36.5K /opt/zfs/test1/var
```
Resize Quota di un Dataset
Vogliamo ridurre la quota del dataset "comp" da 1G a 512M. Soccessivamente la poetremo a 1.5G:
- verifichiamo lo stato atrtuale di "comp"
```
$ zfs list test1/comp
NAME USED AVAIL REFER MOUNTPOINT
test1/comp 36.5K 1024M 36.5K /opt/zfs/test1/comp
```
- portiamo la quota a 512M
```
$ sudo zfs set quota=512M test1/comp
```
- e verifichiamo lo stato
```
$ zfs list test1/comp
NAME USED AVAIL REFER MOUNTPOINT
test1/comp 36.5K 512M 36.5K /opt/zfs/test1/comp
```
- e, infine, portiamo a 1.5G
```
$ sudo zfs set quota=1.5G test1/comp
```
- vediamo lo statu del dataset
```
$ zfs list test1/comp
NAME USED AVAIL REFER MOUNTPOINT
test1/comp 36.5K 1.50G 36.5K /opt/zfs/test1/comp
```
In tutti questi ridimensionamenti il dataset resta sempore usabile e online.
Unica eccezzio se tentiamo di ridurlo portandolo sotto lo spazio usato (es.: ridurlo a 512M quando lo spazio occupato è di 1024M).
Group Quota
Passiamo a gesrtire le quote sugli utenti. Iniziamo impostando una quota di 512M al gruppo "Test1_Comp" sul dataset "test1/comp". Il gruppo deve esistere tra quelli di sistema:
- verifichiamo le quote-gruppo per test1/comp
```
$ sudo zfs groupspace test1/comp
TYPE NAME USED QUOTA OBJUSED OBJQUOTA
POSIX Group root 512B none 1 none
```
- impostiamo la quota
```
$ sudo zfs set groupquota@Test1_Comp=512M test1/comp
```
- e verifichiamo l'aggiornamento delle quote
```
$ sudo zfs groupspace test1/comp
TYPE NAME USED QUOTA OBJUSED OBJQUOTA
POSIX Group Test1_Comp 0B 512M - -
POSIX Group root 512B none 1 none
```
User Quota
Sempre operando su "test1/comp" applichiamo una quota di 1256K per l'utente "minni":
- verifichiamo le quote-utente per test1/comp
```
$ sudo zfs userspace test1/comp
TYPE NAME USED QUOTA OBJUSED OBJQUOTA
POSIX User root 512B none 1 none
```
- impostiamo la quota per "minni"
```
$ sudo zfs set userquota@minni=1256K test1/comp
```
- e verifichiamo l'aggiornamento delle quote
```
$ sudo zfs userspace test1/comp
TYPE NAME USED QUOTA OBJUSED OBJQUOTA
POSIX User minni 0B 1.23M - -
POSIX User root 512B none 1 none
```
Sostituire un Disco
Procediamo sostituenbo un disco nel nostro pool RAID-Z:
- aggiungiamo il dico vdh al pool come disco spare
```
$ sudo zpool add test1 spare /dev/vdh
```
- verifichiamo lo stato del pool
```
$ zpool status -v
pool: test1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
test1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
vdb ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
spares
vdh AVAIL
errors: No known data errors
```
- a questo punto sostituiamo vdb con vdh
```
$ sudo zpool replace test1 /dev/vdb /dev/vdh
$ sudo zpool detach test1 /dev/vdb
```
- verifichiamo lo stato del pool
```
$ zpool status
pool: test1
state: ONLINE
scan: resilvered 172K in 00:00:00 with 0 errors on Sat Sep 19 14:24:37 2026
config:
NAME STATE READ WRITE CKSUM
test1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
vdh ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
errors: No known data errors
```
Aggiungere un Disco
**NB**: la funzione ``attach`` ad un pool RAID-Z è di recente introduzione al momento in cui scrivo. Questo significa che non è disponibile in tutte le distribuzioni Linux che prevedono i pacchetti ZFS e che l'implmentazioneha tutti i limiti del caso come nuova future.
- Aggiungiamo il dico vdi al pool
```
$ sudo zpool attach test1 raidz1-0 /dev/vdi
```
- verifichiamo lo stato del pool
```
$ zpool status
pool: test1
state: ONLINE
scan: resilvered 172K in 00:00:00 with 0 errors on Sat Sep 19 14:24:37 2026
config:
NAME STATE READ WRITE CKSUM
test1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
vdh ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
vdi ONLINE 0 0 0
errors: No known data errors
```
Togliere un Disco
La rimozione di un disco non comporta problemi se si tratta di uno spare.
Se si tratta di un disco del RAID-Z **non è possibile**. RAID-Z è progettato per crescere, non per risursi.
Questa è una delle rigidità che vengono superate dai pool ZFS non RAID.
Per rimuove un disco spare:
- iniziamo vedendo lo stato del pool RAID-Z
```
$ zpool status
pool: test1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
test1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
vdh ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
vdi ONLINE 0 0 0
spares
vdj AVAIL
errors: No known data errors
```
- rimuoviamo il disco spare vdj
```
sudo zpool remove test1 /dev/vdj
```
- e rivediamo lo stato
```
$ zpool status
pool: test1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
test1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
vdh ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
vdi ONLINE 0 0 0
errors: No known data errors
```
Rimuovere un dataset
- Iniziamo vedendo i dataset sul nostro pool RAID-Z
```
$ sudo zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 343K 4.42G 36.5K /test1
test1/comp 36.5K 4.42G 36.5K /opt/zfs/test1/compresso
test1/fix 36.5K 1024M 36.5K /opt/zfs/test1/fix
test1/var 36.5K 4.42G 36.5K none
```
- eliminiamo il dataset "var"
```
$ sudo zfs destroy test1/var
```
- e rivediamo lo stato
```
$ sudo zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 289K 4.42G 36.5K /test1
test1/comp 36.5K 4.42G 36.5K /opt/zfs/test1/compresso
test1/fix 36.5K 1024M 36.5K /opt/zfs/test1/fix
```
Rinominare un dataset
- Iniziamo vedendo i dataset sul nostro pool RAID-Z
```
$ sudo zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 289K 4.42G 36.5K /test1
test1/comp 36.5K 4.42G 36.5K /opt/zfs/test1/compresso
test1/fix 36.5K 1024M 36.5K /opt/zfs/test1/fix
```
- rinominiamo il dataset "fix" in "fisso"
```
$ sudo zfs rename test1/fix test1/fisso
```
- e sediamo lo stato aggiornato
```
$ sudo zfs list
NAME USED AVAIL REFER MOUNTPOINT
test1 291K 4.42G 36.5K /test1
test1/comp 36.5K 4.42G 36.5K /opt/zfs/test1/compresso
test1/fisso 36.5K 1024M 36.5K /opt/zfs/test1/fix
```
Prima conclusione
I pool RAID-Z offrono un alto livello di ridondanza, bassa complessità di creazione-manutenzione e non richiede costoso hardware dedicato.
Parte da un livello RAID 5 e permette anche il RADI 6 con tutte le proprietà aggiuntive offerte da ZFS (come la compressione dei dati).
Il RAID-Z, però, si porta dietro la necessità di una adeguata quantità di RAM e, soprattutto, la rigidità delle soluzioni RAID come l'impossibilità di rimozione di dischi da un array.
Pool
ZFS offre una seconda tipologia di pool. Si tratta di una tecnologia nativa ZFS, offre tutti i vantaggi del RAID-Z, ma è più flessibile. La ridondanza è di default. Inserendo dischi di log viene aggiunta una raccolta di metadati per ricostruire dati in caso di fault dell'hardware o di particolari errori. Aggiungendo dischi di cache si ottengono prestazioni di IO di alto livello (in questo caso, però, si dovono usare dichi particolarmente veloci, come gli NVME, e bus hardware molto veloci, specifiche hardware che possono esserte costose come l'hardware dedicato).
Creazione di un Pool
Criamo il pool "demo1" con due dischi di log. Inseriamo anche un disco di cache a titolo didattico. Infatti questo disco non apporterà nessun beneficio né in termini di velocità, né in termini di sicurezza.
- Creazione del pool
```
$ sudo zpool create -m none demo1 vdb vdc vdd vde log mirror vdf vdg cache vdh
```
- verifica dello stato
```
$ zpool status
pool: demo1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
demo1 ONLINE 0 0 0
vdb ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
logs
mirror-4 ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
cache
vdh ONLINE 0 0 0
errors: No known data errors
```
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
demo1 147K 3.62G 24K none
```
Creare un dataset
Creiamo ora 3 dataset, ovvero 3 partizioni che si possono montare e usare.
Li monteremo path ``/opt/zfs/demo1/film``, ``/opt/zfs/demo1/musica`` e ``/opt/zfs/demo1/doc``.
- Creiamo il dataset ``film`` con una quota di 1G:
```
$ sudo zfs create -o quota=1G -o mountpoint=/opt/zfs/demo1/film demo1/film
```
- creiamo ora il dataset ``musica`` senza nessuna quota:
```
$ sudo zfs create -o mountpoint=/opt/zfs/demo1/musica demo1/musica
```
- creiamo anche un dataset compresso senza quota:
```
$ sudo zfs create -o compression=on -o mountpoint=/opt/zfs/demo1/doc demo1/doc
```
- vediamo il lavoro fatto
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
demo1 336K 3.62G 24K none
demo1/doc 24K 3.62G 24K /opt/zfs/demo1/doc
demo1/film 24K 1024M 24K /opt/zfs/demo1/film
demo1/musica 24K 3.62G 24K /opt/zfs/demo1/musica
```
- e il dettaglio di ogni dataset (output omesso per eccesso di lungaggine)
```
$ zfs get all demo1/film
[...]
$ zfs get all demo1/musica
[...]
$ zfs get all demo1/doc
[...]
```
- e, infine, l'antico ``df`` per avere un semplice e sorprendente report
```
$ df -h
NAME USED AVAIL REFER MOUNTPOINT
[...]
demo1/film 1.0G 128K 1.0G 1% /opt/zfs/demo1/film
demo1/musica 3.7G 128K 3.7G 1% /opt/zfs/demo1/musica
demo1/doc 3.7G 128K 3.7G 1% /opt/zfs/demo1/doc
```
Facciamo due considerazioni finali per questa parte:
- secondo ``df`` dal nostro pool demo1 abbiamo a disposizione 1G+4.5G+4.5G (in totale 10G)
- il pool demo1 ha una capienza massima di 4.5G
- in realtà l'output che vediamo significa: il dataset ha ancora a disposizione NN bytes
- quinti i dataset usano la risorsa pool condividendo per intero lo spazio secondo i limiti di quota che gli diamo (un massimo fisso o variabile)
- unica semi-eccezzione è il dataset compresso: l'algoritmo riduce lo spazio effetivo usato dai file in base alla loro riduzione per comprensione, ma non si può predidire in termini precisi perché la compressione varia da dati a dati (file compressi non vengono ulteriormente ridotti, file grezzi possono essere ridotti anche oltre il 90%).
Questo primo passo ci porta a concetti più avanzati:
- il pool ZFS non RAID-Z è più felessibile
- ZFS si astrae dal device fisico permettendo di cambiare dischi, usare tipologie diverse di dischi, permette di aggiungere-togliere dischi a caldo, il tutto senza perdere dati e in continuità di servizio, il tutto, però, entro limiti fisici e software (es.: non posso togliere un disco pieno di dati)
- ZFS offre una gestione molto flessibile e, per questo, non sempre immediata nella comprensione e\o nell'uso.
Montare il dataset
Alla creazione i dataset vengono automaticamente montati. ZFS non scrive in ``/etc/fstab`` il punto di montaggio, ma è scritto all'interno dei metadati del pool e del dataset. Quando il kernel legge queste informazioni le attua.
Lato amministratore non si deve operare sul tradizionale ``/etc/fstab``, ma si opera tramite i comandi ``zpool``, ``zfs``, ``zfs umount`` e ``zfs mount``.
Procediamo togliendo il mount point a "demo1/doc" e poi ri-impostando il montaggio automatico:
- smontiamo il dataset "doc"
```
$ sudo zfs umount demo1/doc
```
- verifichiamo
```
mount |grep "demo1/"
demo1/film on /opt/zfs/demo1/film type zfs (rw,relatime,xattr,noacl,casesensitive)
demo1/musica on /opt/zfs/demo1/musica type zfs (rw,relatime,xattr,noacl,casesensitive)
```
- togliamo il punto di montaggio a "demo1/doc"
```
$ sudo zfs set mountpoint=none demo1/doc
```
- verifichiamo l'avvenuto cambio
```
zfs get mountpoint demo1/doc
NAME PROPERTY VALUE SOURCE
demo1/doc mountpoint none local
```
- proviamo ora a fare il montaggio standard di "demo1/doc"
```
$ sudo zfs mount demo1/doc
cannot mount 'demo1/doc': no mountpoint set
```
- l'output restituisce un errore (non errore) perché non è definito nessun punto di montaggio. Procediamo, quindi, inserendo il mount point e ZFS provvederà a montarlo subito
```
$ sudo zfs set mountpoint=/opt/zfs/demo1/documenti demo1/doc
```
- verifichiamo il montaggio
```
mount |grep "demo1/"
demo1/film on /opt/zfs/demo1/film type zfs (rw,relatime,xattr,noacl,casesensitive)
demo1/musica on /opt/zfs/demo1/musica type zfs (rw,relatime,xattr,noacl,casesensitive)
demo1/doc on /opt/zfs/demo1/documenti type zfs (rw,relatime,xattr,noacl,casesensitive)
```
Monitorare
Per vedere lo stato dei pool e dei dataset abbiamo gli stessi strumenti visti sopra:
- iniziamo chiedendo l'elenco dei pool
```
$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
demo1 3.75G 342K 3.75G - - 0% 0% 1.00x ONLINE -
```
- chiediamo ora l'elenco dei dataset
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
demo1 342K 3.62G 24K none
demo1/doc 24K 3.62G 24K /opt/zfs/demo1/documenti
demo1/film 24K 1024M 24K /opt/zfs/demo1/film
demo1/musica 24K 3.62G 24K /opt/zfs/demo1/musica
```
- a questo punto abbiamo l'elenco dei pool e dei dataset. Vediamo lo stato del nostro pool
```
$ zpool status
pool: demo1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
demo1 ONLINE 0 0 0
vdb ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
logs
mirror-4 ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
cache
vdh ONLINE 0 0 0
errors: No known data errors
```
- per vedere le proprietà del pool e dei dataset abbiamo il comando ``get``
```
$ zfs get all
NAME PROPERTY VALUE SOURCE
demo1 type filesystem -
demo1 creation Sun Sep 20 8:08 2026 -
demo1 used 342K -
demo1 available 3.62G -
demo1 referenced 24K -
demo1 compressratio 1.00x -
demo1 mounted no -
demo1 quota none default
[...]
demo1/doc type filesystem -
demo1/doc creation Sun Sep 20 8:22 2026 -
demo1/doc used 24K -
demo1/doc available 3.62G -
demo1/doc referenced 24K -
demo1/doc compressratio 1.00x -
demo1/doc mounted yes -
demo1/doc quota none default
[...]
demo1/film type filesystem -
demo1/film creation Sun Sep 20 8:22 2026 -
demo1/film used 24K -
demo1/film available 1024M -
demo1/film referenced 24K -
demo1/film compressratio 1.00x -
demo1/film mounted yes -
demo1/film quota 1G local
[...]
demo1/musica type filesystem -
demo1/musica creation Sun Sep 20 8:22 2026 -
demo1/musica used 24K -
demo1/musica available 3.62G -
demo1/musica referenced 24K -
demo1/musica compressratio 1.00x -
demo1/musica mounted yes -
demo1/musica quota none default
[...]
```
- possiamo avere le proprietà del singolo pool e del singolo dataset come segue:
+ per vedere le proprietà del singolo pool
```
$ zfs get all demo1
NAME PROPERTY VALUE SOURCE
demo1 type filesystem -
demo1 creation Sun Sep 20 8:08 2026 -
demo1 used 342K -
demo1 available 3.62G -
demo1 referenced 24K -
demo1 compressratio 1.00x -
demo1 mounted no -
demo1 quota none default
[...]
```
+ per vedere le proprietà del singolo dataset
```
$ zfs get all demo1/doc
NAME PROPERTY VALUE SOURCE
demo1/doc type filesystem -
demo1/doc creation Sun Sep 20 8:22 2026 -
demo1/doc used 24K -
demo1/doc available 3.62G -
demo1/doc referenced 24K -
demo1/doc compressratio 1.00x -
demo1/doc mounted yes -
demo1/doc quota none default
[...]
```
L'output degli ultimi tre esempi riportano oltre allo stato delle proprietà anche alcuni dati di stato.
A questo punto creiamo un secondo pool per vedere come monitorare singolarmente i pool e i dataset
- creiamo un nuovo pool e qualche dataset
```
$ sudo zpool create -m none demo2 vdi vdj vdk
$ sudo zfs create -o mountpoint=none demo2/docs1
$ sudo zfs create -o mountpoint=none demo2/docs2
$ sudo zfs create -o mountpoint=none demo2/docs3
$ sudo zfs create -o mountpoint=none demo2/docs4
```
- vediamo l'elenco dei pool e dei dataset disponibili
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
demo1 345K 3.62G 24K none
demo1/doc 24K 3.62G 24K /opt/zfs/demo1/documenti
demo1/film 24K 1024M 24K /opt/zfs/demo1/film
demo1/musica 24K 3.62G 24K /opt/zfs/demo1/musica
demo2 334K 2.69G 24K none
demo2/docs1 24K 2.69G 24K none
demo2/docs2 24K 2.69G 24K none
demo2/docs3 24K 2.69G 24K none
demo2/docs4 24K 2.69G 24K none
```
- vediamo lo stato del solo pool "test2"
```
$ zpool status demo2
pool: demo2
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
demo2 ONLINE 0 0 0
vdi ONLINE 0 0 0
vdj ONLINE 0 0 0
vdk ONLINE 0 0 0
errors: No known data errors
```
- chiediamo le proprietà del solo pool "demo2"
```
$ zfs get all demo2
NAME PROPERTY VALUE SOURCE
demo2 type filesystem -
demo2 creation Sun Sep 20 19:02 2026 -
demo2 used 334K -
demo2 available 2.69G -
demo2 referenced 24K -
demo2 compressratio 1.00x -
demo2 mounted no -
demo2 quota none default
demo2 reservation none default
demo2 recordsize 128K default
demo2 mountpoint none local
[...]
```
- e, infine, chiediamo le proprietà del solo dataset "docs2"
```
$ zfs get all demo2/docs2
NAME PROPERTY VALUE SOURCE
demo2/docs2 type filesystem -
demo2/docs2 creation Sun Sep 20 19:02 2026 -
demo2/docs2 used 24K -
demo2/docs2 available 2.69G -
demo2/docs2 referenced 24K -
demo2/docs2 compressratio 1.00x -
demo2/docs2 mounted no -
demo2/docs2 quota none default
demo2/docs2 reservation none default
demo2/docs2 recordsize 128K default
demo2/docs2 mountpoint none local
[...]
```
Quote
Quota ad un Pool
Un comportamento saggio è porre una quota globale al pool; quando lo spazio verrà saturato si potrà aggiunge spazio in un istante modificando o togliendo la quota in attesa che arrivino i nuovi dischi aggiuntivi. Operiamo sul pool "demo2":
- iniziamo prendendo visione della capacità totale del pool de della quota impostata
```
$ zpool list demo2
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
demo2 2.81G 348K 2.81G - - 0% 0% 1.00x ONLINE -
```
```
$ zfs get quota demo2
NAME PROPERTY VALUE SOURCE
demo2 quota none local
```
- il nostro pool demo2 ha una capacità di 2,8G e non ci sono quote.
Impostiamo una quota a 2G in modo da avere 0.8G disponibili per urgenze di "spazio esaurito"
```
$ sudo zfs set quota=2G demo2
```
- verifichiamo lo stato dello spazio disponibile
```
$ zpool list demo2
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
demo2 2.81G 348K 2.81G - - 0% 0% 1.00x ONLINE -
```
```
$ zfs get quota demo2
NAME PROPERTY VALUE SOURCE
demo2 quota 2G local
```
Abbiamo posto in limite di spazio usabile a 2G tenedo 0.8G di scorta per le emergenze.
Quota ad un Dataset
La quota ai dataset va pensata come il size di una partizione di un disco con la differenza che per un disco rigido è una impostazione rigida e il cambio comporta la distruzione dello spazio, mentre in un dataset è flessibile, non distrittiva e funziona in un istante.
- vediamo i nostri dataset del pool "demo2"
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
demo1 345K 3.62G 24K none
demo1/doc 24K 3.62G 24K /opt/zfs/demo1/documenti
demo1/film 24K 1024M 24K /opt/zfs/demo1/film
demo1/musica 24K 3.62G 24K /opt/zfs/demo1/musica
demo2 348K 2.00G 24K none
demo2/docs1 24K 2.00G 24K none
demo2/docs2 24K 2.00G 24K none
demo2/docs3 24K 2.00G 24K none
demo2/docs4 24K 2.00G 24K none
```
- impostiamo una quota a 1G per il dataset docs2
```
$ sudo zfs set quota=1G demo2/docs2
```
- verifichiamo i dataset
```
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
demo1 345K 3.62G 24K none
demo1/doc 24K 3.62G 24K /opt/zfs/demo1/documenti
demo1/film 24K 1024M 24K /opt/zfs/demo1/film
demo1/musica 24K 3.62G 24K /opt/zfs/demo1/musica
demo2 350K 2.00G 24K none
demo2/docs1 24K 2.00G 24K none
demo2/docs2 24K 1024M 24K none
demo2/docs3 24K 2.00G 24K none
demo2/docs4 24K 2.00G 24K none
```
Resize Quota di un Dataset
Vogliamo ridurre la quota del dataset "docs2" da 1G a 512M. Soccessivamente la porteremo a 1.5G:
- verifichiamo lo stato attuale di "docs2"
```
$ zfs list demo2/docs2
NAME USED AVAIL REFER MOUNTPOINT
demo2/docs2 24K 1024M 24K none
```
- portiamo la quota a 512M
```
$ sudo zfs set quota=512M demo2/docs2
```
- e verifichiamo lo stato
```
$ zfs list demo2/docs2
NAME USED AVAIL REFER MOUNTPOINT
demo2/docs2 24K 512M 24K none
```
- e, infine, portiamo la quota a 1.5G
```
$ sudo zfs set quota=1.5G demo2/docs2
```
- vediamo lo status del dataset
```
$ zfs list demo2/docs2
NAME USED AVAIL REFER MOUNTPOINT
demo2/docs2 24K 1.50G 24K none
```
In tutti questi ridimensionamenti il dataset resta sempore usabile e online.
L'unica eccezzio a questo comportamento è il tentativo di ridurre lo spazio portandolo ad una dimensione dello spazio usato (es.: ridurlo a 512M quando lo spazio occupato è di 1024M).
Group Quota
Passiamo a gesrtire le quote sugli utenti. Iniziamo impostando una quota di 512M al gruppo "Demo2_Docs2" sul dataset "demo2/docs2". **Attenzione: il gruppo deve esistere tra quelli di sistema**:
- verifichiamo le quote-gruppo per demo2/docs2
```
$ sudo zfs groupspace demo2/docs2
TYPE NAME USED QUOTA OBJUSED OBJQUOTA
POSIX Group root 512B none 1 none
```
- impostiamo la quota
```
$ sudo zfs set groupquota@Demo2_Docs2=512M demo2/docs2
```
- e verifichiamo l'aggiornamento delle quote
```
$ sudo zfs groupspace demo2/docs2
TYPE NAME USED QUOTA OBJUSED OBJQUOTA
POSIX Group Demo2_Docs2 0B 512M - -
POSIX Group root 512B none 1 none
```
User Quota
Sempre operando su "demo2/docs2" applichiamo una quota di 1256K all'utente "minni":
- verifichiamo le quote-utente per demo2/docs2
```
$ sudo zfs userspace demo2/docs2
TYPE NAME USED QUOTA OBJUSED OBJQUOTA
POSIX User root 512B none 1 none
```
- impostiamo la quota per "minni"
```
$ sudo zfs set userquota@minni=1256K demo2/docs2
```
- e verifichiamo l'aggiornamento delle quote
```
$ sudo zfs userspace demo2/docs2
TYPE NAME USED QUOTA OBJUSED OBJQUOTA
POSIX User minni 0B 1.23M - -
POSIX User root 512B none 1 none
```
Rinominare un dataset
Rinominiamo il dataset "demo2/docs1" in "demo2/documenti1":
- iniziamo vedendo i dataset del pool "demo2"
```
$ zfs list|grep demo2
demo2 324K 2.00G 24K none
demo2/docs1 24K 2.00G 24K none
demo2/docs3 24K 2.00G 24K none
demo2/docs4 24K 2.00G 24K none
```
- rinominiamo il dataset "demo2/docs1"
```
$ sudo zfs rename demo2/docs1 demo2/documenti1
```
- e ri-vediamo i dataset del pool "demo2"
```
$ zfs list|grep demo2
demo2 344K 2.00G 24K none
demo2/docs3 24K 2.00G 24K none
demo2/docs4 24K 2.00G 24K none
demo2/documenti1 24K 2.00G 24K none
```
Rimuovere un dataset
La cancellazione di un dataset comporta la perdita irreversibile dei dati contenuti nel dataset.
**Se si hanno dei dati assicurarsi di aver fatto una copia prima di procedere!**
- Vediamo i dataset del pool "demo2"
```
$ zfs list|grep demo2
demo2 356K 2.00G 24K none
demo2/docs1 24K 2.00G 24K none
demo2/docs2 24K 1.50G 24K none
demo2/docs3 24K 2.00G 24K none
demo2/docs4 24K 2.00G 24K none
```
- cancelliamo il dataset "demo2/docs2"
```
$ sudo zfs destroy demo2/docs2
```
- e ri-vediamo i dataset del pool "demo2"
```
$ zfs list|grep demo2
demo2 324K 2.00G 24K none
demo2/docs1 24K 2.00G 24K none
demo2/docs3 24K 2.00G 24K none
demo2/docs4 24K 2.00G 24K none
```
Rimuovere un Pool
La cancellazione di un pool comporta la perdita irreversibile dei dati contenuti.
**Se si hanno dei dati, dei dataset assicurarsi di avere una copia prima di procedere!**
- Vediamo l'elenco dei pool disponibili
```
$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
demo1 3.75G 345K 3.75G - - 0% 0% 1.00x ONLINE -
demo2 2.81G 344K 2.81G - - 0% 0% 1.00x ONLINE -
```
- eliminiamo il pool "demo2"
```
$ sudo zpool destroy demo2
```
- ri-vediamo l'elenco dei pool disponibili
```
$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
demo1 3.75G 345K 3.75G - - 0% 0% 1.00x ONLINE -
```
Sostituire un Disco
- Vediamo lo stato dello stack di dischi ZFS
```
$ zpool status
pool: demo1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
demo1 ONLINE 0 0 0
vdb ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
logs
mirror-4 ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
cache
vdh ONLINE 0 0 0
errors: No known data errors
```
- vogliamo sostituire il disco "vdb" con il disco, fuori pool, "vdi"
```
$ sudo zpool replace demo1 /dev/vdb /dev/vdi
```
- rivediamo lo stato del pool demo1
```
$ zpool status
pool: demo1
state: ONLINE
scan: resilvered 198K in 00:00:00 with 0 errors on Sun Sep 20 21:43:59 2026
config:
NAME STATE READ WRITE CKSUM
demo1 ONLINE 0 0 0
vdi ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
logs
mirror-4 ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
cache
vdh ONLINE 0 0 0
errors: No known data errors
```
Aggiungere un Disco
Aggiungiamo il disco "vdk" al pool
- verifichiamo lo stato di partenza
```
$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
demo1 3.75G 370K 3.75G - - 0% 0% 1.00x ONLINE -
```
```
$ zpool status
pool: demo1
state: ONLINE
scan: resilvered 198K in 00:00:00 with 0 errors on Sun Sep 20 21:43:59 2026
config:
NAME STATE READ WRITE CKSUM
demo1 ONLINE 0 0 0
vdi ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
logs
mirror-4 ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
cache
vdh ONLINE 0 0 0
errors: No known data errors
```
- procediamo per aggiungere il disco "vdk" al pool "demo1"
```
$ sudo zpool add demo1 /dev/vdk
```
- verifichiamo l'attuale stato del pool "demo1"
```
$ zpool status
pool: demo1
state: ONLINE
scan: resilvered 198K in 00:00:00 with 0 errors on Sun Sep 20 21:43:59 2026
config:
NAME STATE READ WRITE CKSUM
demo1 ONLINE 0 0 0
vdi ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
vdk ONLINE 0 0 0
logs
mirror-4 ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
cache
vdh ONLINE 0 0 0
errors: No known data errors
```
Togliere un Disco
Vogliamo togliere il disco "vdk" dal pool "demo1":
- iniziamo chiedendo lo stato del pool
```
$ zpool status
pool: demo1
state: ONLINE
scan: resilvered 198K in 00:00:00 with 0 errors on Sun Sep 20 21:43:59 2026
config:
NAME STATE READ WRITE CKSUM
demo1 ONLINE 0 0 0
vdi ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
vdk ONLINE 0 0 0
logs
mirror-4 ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
cache
vdh ONLINE 0 0 0
errors: No known data errors
```
- diamo l'istruzione di rimozione del disco "vdk"
```
$ sudo zpool remove demo1 vdk
```
- ri-vediamo lo stato del pool
```
$ zpool status
pool: demo1
state: ONLINE
scan: resilvered 198K in 00:00:00 with 0 errors on Sun Sep 20 21:43:59 2026
remove: Removal of vdev 5 copied 0 in 0h0m, completed on Sun Sep 20 21:58:55 2026
config:
NAME STATE READ WRITE CKSUM
demo1 ONLINE 0 0 0
vdi ONLINE 0 0 0
vdc ONLINE 0 0 0
vdd ONLINE 0 0 0
vde ONLINE 0 0 0
logs
mirror-4 ONLINE 0 0 0
vdf ONLINE 0 0 0
vdg ONLINE 0 0 0
cache
vdh ONLINE 0 0 0
errors: No known data errors
```
**Attenzione**: come negli altri casi di ridimensionamento sotto il tetto dello spazio occupato, anche la rimozione di un disco è possibile solo se i dati non lo occupano o possono essere ricollocati su altri dischi del pool. Qualora non sia possibile ZFS ci informa con un messaggio esplicito.
Seconda conclusione
Il pool nativo di ZFS è molto flessibile e, a differenza dei RAID-Z, scala.
Supporta tutte le futures ZFS (come la compressione dei dati, ad esempio). Con un congruo numero di dischi offre una notevole sicurezza.
Tutto questo, comunque, non è miracoloso, ha un costo:
- serve una adeguata quantità di RAM
- se il controller non è adeguato molto calcolo viene fatto dalla CPU
- se abbiamo un intensivo IO è necessario hardware specializzato
- nell'open non abbiamo tool grafici che semplificano la gestione, anche se, a onor del vero, la gestione da CLI ha una bassa complessità.
SnapShot
Prima di procedere capiamo cosa è uno "snapshot".
Letteralmente è l'"istantanea" nel mondo della fotografia. Effettivamente l'idea è proprio questa:
- faccio una istantanea del mio disco o del dataset
- procedo con i lavori
- se il risultato non mi piace e qualcosa va storto possso fare rollback.
I punti di forza sono:
- snabshot e rollback sono velocissimi (istantanei)
- occupa pochissimo spazio
- non è necessario un supporto di memoria esterno come con i backup.
Ecco: lo snapshot è un backup velocissimo, senza una memoria esterna adatto per creare copie per brevi tempi.
Lo snapshot è una tecnologia inserita nel filesystem pertanto non tutti i filesystem lo supportano e, a seconda dello specifico filesystem, cambiano sintassi e tool che lo gestiscono.
**Non è un backup**: da ricordare sempre che gli snapshot non sono un backup, ma si possono usare per fare un backup.
Creare lo snapshot
Lo snapshot si applica a un dataset per intero.
Prima di agire:
- procediamo allo snapshot del dataset "doc"
- i nomi degli snapshot sono migliori se riportano, come nome, il momento in cui sono stati fatti.
Procediamo:
```
$ sudo zfs snapshot demo1/doc@20260922-2200_training />```
Vedere elenco degli snapshot
- Vediamo l'lenco dei set ZFS
```
$ zfs list -t all
NAME USED AVAIL REFER MOUNTPOINT
demo1 480K 3.62G 24K none
demo1/doc 24K 3.62G 24K /opt/zfs/demo1/documentidemo1/doc@20260922-2200_training 0B - 24K -
demo1/film 24K 1024M 24K /opt/zfs/demo1/film
demo1/musica 24K 3.62G 24K /opt/zfs/demo1/musica
```
- se preferiamo vedere i soli snapshot basta fare come segue
```
$ zfs list -t snapshot
NAME USED AVAIL REFER MOUNTPOINT
demo1/doc@20260922-2200_training 0B - 24K -
```
Rinominare uno snapshot
Vogliamo rinominare lo snapshot "20260922-2200_training" in "20260922-2200_example":
- diamo il comando di rinomina
```
$ sudo zfs rename -r demo1/doc@20260922-2200_training @20260922-2200_example
```
- controlliamo i nostri snapshot
```
$ zfs list -t snapshot
NAME USED AVAIL REFER MOUNTPOINT
demo1/doc@20260922-2200_example 0B - 24K -
```
Montare uno snapshot
Possiamo gestire uno snapshot quasi come un dataset di sola lettura. Con una sintassi appropriata lo possiamo montare (come un dataset) per prendere un singolo file o fare un backup dell'istantanea. Naturalmente lo snapshot è in sola lettura:
- montiamo lo snapshot in ``/mnt``
```
$ sudo mount -t zfs demo1/doc@20260922-2200_example /mnt -o ro
```
- verifichiamo il montaggio
```
$ mount |grep "/mnt"
demo1/doc@20260922-2200_example on /mnt type zfs (ro,relatime,xattr,noacl,casesensitive)
```
- e diamo una sbirciatina all'interno
```
$ ls -lh /mnt/
total 1.5K
-rw-r--r-- 1 root root 0 Sep 22 21:13 file1-ORG.doc
-rw-r--r-- 1 root root 0 Sep 22 21:13 file2-ORG.doc
-rw-r--r-- 1 root root 0 Sep 22 21:13 file3-ORG.doc
```
Smontare uno snapshot
Per smontare lo snapshot prima montato è sufficiente:
- smontiamo
```
$ sudo umount /mnt
```
- e verifichiamo
```
$ mount |grep "/mnt"
```
Ripristino di uno snapshot
**NB**: il ripristino resetta l'intero dataset che ripristiniamo.
- A scopo didattico facciamo una attività preliminare:
+ creiamo due file
```
$ sudo touch /opt/zfs/demo1/documenti/file4-NEW.doc
$ sudo touch /opt/zfs/demo1/documenti/file5-NEW.doc
```
+ e cancelliamo un file
```
$ sudo rm /opt/zfs/demo1/documenti/file1-ORG.doc
```
+ e vediamo il contenuto del dataset "doc"
```
$ ls -lh /opt/zfs/demo1/documenti/
total 2.0K
-rw-r--r-- 1 root root 0 Sep 22 21:13 file2-ORG.doc
-rw-r--r-- 1 root root 0 Sep 22 21:13 file3-ORG.doc
-rw-r--r-- 1 root root 0 Sep 22 21:17 file4-NEW.doc
-rw-r--r-- 1 root root 0 Sep 22 21:17 file5-NEW.doc
```
- procediamo con il roleback dello snapshot
```
$ sudo zfs rollback demo1/doc@20260922-2200_example />```
- e vediamo il contenuto del dataset "doc"
```
$ ls -lh /opt/zfs/demo1/documenti/
total 1.5K
-rw-r--r-- 1 root root 0 Sep 22 21:13 file1-ORG.doc
-rw-r--r-- 1 root root 0 Sep 22 21:13 file2-ORG.doc
-rw-r--r-- 1 root root 0 Sep 22 21:13 file3-ORG.doc
```
Cancellare gli snapshot
**NB**: lo snapshot è uno strumento pensato per vivere poco tempo. Se non si cancella:
- cresce occupando sempre più spazio
- impiega calcolo progressivamente sempre maggiore
- aumenta l'IO ai dischi.
- Vediamo gli snapshot presenti
```
$ zfs list -t snapshot
NAME USED AVAIL REFER MOUNTPOINTdemo1/doc@20260922-2200_example 13K - 26K -
```
- cancelliamo "20260922-2200_example"
```
$ sudo zfs destroy demo1/doc@20260922-2200_example />```
- e rivediamo l'elenco degli snapshot presenti
```
$ zfs list -t snapshot
no datasets available
```
Conclusione
Probabilmente si è capito che ZFS ha caratteristiche eccellenti anche con hardware modesto. In particole spicca per la flessibilità e la scalabilità e l'intrinseca robustezza dimostrata da ormai decenni di uso reale a partire dagli antichi sistemi SUN agli attuali sistemi compresi i server Linux.
Questa piccola guida offre una panoramica per l'uso, ma non è completa. Manca, ad esempio, una trattazione dei "project", ovvero dataset per un gruppo creati a scopo.
ZFS supporta anche uno sharing nativo su protocollo NFS o SMB.
In merito agli snapshot c'è la funzione "clone" che non è stata illustrata e, sempre riguardo agli snapshot, non è stato citato "sanoid" per l'automazione di questi.
In ogni caso con questi paragrafi possiamo già fare molto, semplicemente.