Analisi comparativa dei Journal File System per GNU/Linux

Introduzione

Il Journal Filesystem

Il filesystem è una componente chiave per assicurare prestazioni ed affidabilità in un ambiente per applicazioni critiche e perché no anche didattiche: siano esse per server che per client.

I requisiti per un filesystem di moderna concezione sono: capacità di supportare grossi volumi fisici (oramai centinaia di gigabyte), integrità dei dati, riduzione della frammentazione interna ed esterna, recovery veloce in caso di crash e manipolazione in modo veloce ed efficiente sia dei file voluminosi che piccoli.

Il vecchio filesystem UFS come lo ext2 non garantisce un adeguato supporto alle nuove tecnologie, e nelle esigenze di scalabilità in un server generalmente si avverte un calo di performance. Aziende come IBM e SGI hanno sviluppato per GNU/Linux i loro filesystem e le nuove distribuzioni già li supportano durante il processo di installazione.

Perché Journal?

La sostanziale differenza tra un filesystem journal (come lo JFS) ed uno non journal (come lo ext2) sta nella capacità di recuperare lo stato consistente dell'hard disk in pochi secondi. La tecnica di recovery, ereditata dai database, si basa sulle transazioni. In caso di “crash” del sistema, lo stato consistente del disco viene recuperato leggendo i log e riapplicando le modifiche: quindi lo stato precedente. Contrariamente in un filesystem non journal lo stato consistente del disco passa attraverso l'analisi dei meta-data (i-node, directory, i-node map...) che richiede la scansione completa (blocco per blocco) del volume logico.

Questo avviene in quanto la ricerca dei blocchi liberi in un filesystem tipo ext2 avviene mappandoli in una sequenza di bit (detta comunemente “struttura a bitmap”); più il filesystem cresce in dimensioni, più lo spazio occupato cresce conseguentemente: l'algoritmo di ricerca utilizzato è sequenziale. Sia chiaro che per filesystem di piccole dimensioni il sistema è decisamente efficiente, e non penalizza le prestazioni del server.

Gli i-node rappresentano oltre che i file e le directory anche qualsiasi altro oggetto del filesystem, e sono fondamentali per la ricerca degli stessi. Nei filesystem “tradizionali” (come lo ext2) devono necessariamente essere fissati a priori in base alla quantità di oggetti che si suppone saranno presenti. Una volta raggiunto il limite, non sarà più possibile creare oggetti anche se lo spazio sul disco è fisicamente presente (intendo i gigabyte disponibili e non ancora utilizzati). Nei filesystem journal questo non accade: la tecnica di allocazione dinamica degli i-node (dynamic i-node allocation) permette tuttavia di superare il limite con disinvoltura, anche a scapito di una complessità interna nella gestione.

Un extent è una sequenza di blocchi contigui allocati da un file come unità base, al loro interno contengono una sequenza composta da: physical, logical offset, length. In buona sostanza: l'ultimo termine indica l'inizio del blocco, il secondo la sua lunghezza ed il terzo l'offset rispetto al primo byte. Esempio: un file può contenere come extent le terne: <30, 60, 1> e <500, 20, 61> (il secondo extent incomincia laddove termina il primo).

Gli extent sono inseriti negli i-node per mappare gli oggetti del filesystem. L'uso di extent riduce il tempo di ricerca dei blocchi e la frammentazione del disco fisso. Congiunti alla tecnica B+Tree, ereditata anch'essa dai database, incrementa notevolmente le performance sia per la ricerca dei blocchi liberi, sia per la ricerca dei file nei directory. La gestione dei file sparse e dei file large o dense, cambia invece per ogni filesystem in esame.

Filesystem ext3

ext3 è il filesystem ufficialmente supportato da Red Hat Linux per la nuova versione 7.2. Non si tratta di una vera e propria evoluzione dello ext2, bensì di un “add-on” per dotarlo di caratteristiche journal: ossia accomapgna i pregi e non migliora i difetti. Non è indispensabile riformattare la partizione, è sufficiente convertirla e la compatibilità è garantita: con i nuovi efstools è altresì possibile montare una partizione ext3 come una comunissima ext2.

L'operazione per rendere journal un “antidiluviano” ext2 è molto semplice:

[root@localhost /root]# tune2fs -j /dev/hdaX

La partizione non deve essere smontata. Verrà creato un file '.journal' nella radice root. La seconda operazione è di disabilitare il check del disco ad intervalli regolari (ogni centottanta giorni o ad ogni venti riavvi o mount):

[root@localhost /root]# tune2fs -c 0 -i 0 /dev/hdaX

Nel file '/etc/fstab' si dovrà porre al posto di ext2 lo ext3 oppure auto se si usa 'e2fsprogs' alla versione almeno 1.23.

La peculiarità dello ext3 risiede nel poter scegliere tre modi diversi di journaling: “ordered”, “journal” e “writeback”.

Il modo “journal” viene effettuato sia sui dati che su i metadati. Negli altri due casi il journaling è limitato solamente ai metadati.

Il metodo più rischioso è lo “writeback” dove il sistema potrebbe apparire in uno stato consistente, mentre potrebbero essere presenti dati vecchi.

Nel metodo “ordered” i dati vengono scritti prima dei metadati e garantisce che il filesystem sia in uno stato consistente.

Per il journal sfrutta uno strato layer generico 'jbd' che gli consente di lavorare con un il journal esterno al filesystem, come un device creato in RAM.

Rimangono invariate le dimensione massime del filesystem a 4Tb e la dimensione massima di un file a 2Gb.

Rimane la struttura a bitmap di ricerca dei blocchi liberi: efficiente per filesystem di piccole dimensioni, ma del tutto inadeguata per i filesystem di grosse dimensioni. Per questi ultimi è più efficiente una struttura ad albero, B+Tree, HTree, ... (usata anche per organizzare le directory) con l'uso congiunto degli extent. Questi ultimi consentono di raggruppare i blocchi liberi in modo più efficiente della struttura a bitmap (che assegna ad ogni blocco del disco un bit). L'algoritmo di scansione modificato ad albero è più efficiente di quello sequenziale.

Filesystem JFS

Il filesystem JFS (Journal File System) sviluppato da IBM per i suoi server AIX è stato ora rilasciato con licenza GPL e messo a disposizione per la comunità GNU/Linux.

Subito si distingue per la gestione delle directory.

Le directory vengono organizzate in due modi differenti in base alle dimensioni stesse: nel primo caso ne contengono fino ad otto (“.” e “..” escluse), e la struttura viene immagazzinata nello i-node stesso, nel secondo caso, con più di otto directory, il tutto viene affidato all'algoritmo B+Tree.

La struttura interna è a 64 bit come lo XFS di Silicon Graphics.

I limiti del filesystem sono : minimo 16 Mbyte, 512 Terabyte (con blocchi da 512K) e 4 petabytes con blocchi di 4 Kb.

Ricordiamo che il kernel 2.4 presenta questi limiti: 16 Terabyte (con blocchi di 4Kb) per i file e 2 Terabyte per il filesystem.

La massima dimensione dei file è legata al virtual file system e comunque ha gli stessi limiti del kernel.

Le utility per creare e gestire le partizioni si trovano nel pacchetto 'jfsprogs'.

Per creare un filesystem è sufficiente digitare:

[root@localhost /root]# mkfs.jfs /dev/hdbX

[root@localhost /root]# mount -t jfs /dev/hdbX /mnt/jfs_root

Non è possibile convertire la partizione ext2 in una JFS, peraltro operazione possibile solo passando da ext2 a ext3. Noi sugeriamo di:

  1. Ridimensionare una partizione precedente oppure utilizzare un altro disco.

  2. Creare la partizione con il nuovo filesystem.

  3. Montarla in un directory del root filesystem.

[root@localhost /root]# find / -mount -print | cpio -dpm /mnt/root_jfs

Farlo per tutte le vecchie partizioni del vostro disco: tipo se avete separata una parzione di home:

[root@localhost /root]# find /home -mount -print | cpio -dpm /mnt/root_jfs

e così via... L'operazione di copia richiede molto tempo soprattutto con dischi fissi particolarmente lenti e partizioni con molti dati.

Al termine dell'operazione riavviare la macchina magari con un dischetto di boot oppure modificando le informazioni del lilo o boot loader che sia.

Nel sito Internet sono presenti le patch sia per il kernel 2.2.x che per il kernel 2.4.x, l'ultima release è la 1.0.10. E' limitato per il momento a blocchi di 4kb, non ha ancora una utility di defrag funzionante, non permette di aumentare le partizioni, non supporta le quota ed i log non possono risiedere in partizioni dedicate. Nelle distribuzioni SuSE 7.3 e Mandrake 8.1 l'installazione utilizzando il suddetto filesystem porta all'inutilizzo della macchina, in quanto la versione di sviluppo presente nei kernel (1.0.5) non è stabile.




Al lavoro nel laboratorio del "Besta"

Filesystem XFS

Il filesystem XFS è stato sviluppato dalla Silicon Graphics per il sistema operativo proprietario IRIX e ora è disponibile per piattaforma GNU/Linux con licenza GPL.

Le caratteristiche sono notevoli: 18 mila Petabyte per le dimensioni del filesystem e 9 mila Petabyte per i file. Supporta l'allocazione dinamica degli i-node e sfrutta gli extent sia per la ricerca dei blocchi liberi (unico per ora), sia per l'organizzazione dei file. Non è possibile convertire una partizione ext2 ad XFS, tuttavia con un procedimento analogo a quello precedente si arriva al medesimo risultato.

Nel sito Internet sono presenti le patch per il kernel 2.4 e le utility necessarie, attualmente l'ultima release è la 1.0.2. Rispetto allo JFS supporta le quota, e dimensione dei blocchi variabile e fino a 64kb, oltre ad una utility per ridimensionare le partizioni.

La dotazione comprende gli 'xfsprogs' come pacchetto base.

Filesystem ReiserFS

Il filesystem ReiserFS è stato sviluppato dalla namesys società indipendente e inserito da molto tempo nella distribuzione SuSE.

I limiti del filesystem sono: 16 Terabyte per il filesystem e 4 Gigabyte per i file. La dimensioni dei blocchi è fissata a 4kb.

Supporta l'allocazione dinamica degli i-node mentre non fa uso degli extents previsti comunque per la versione 4 in uscita nel 2002.

Caratteristo di questo filesystem è che invece di usare la struttura a B+Tree usa una versione estesa nominata B*Tree, dove ogni oggetto nel filesystem è una struttura B*Tree.

Il codice sorgente è disponibile nel kernel 2.4. E' presente una utility per ridimensionare le partizioni.

Conclusioni

Un po' di numeri non guastano. Poiché sono appena stati implementati nel laboratorio dell'IPC Fabio Besta non ho ancora dati reali sul campo, ma è possibile con qualche benchmark giudicare indicativamente le prestazioni dei filesystem studiati. Le condizioni di prova sono una workstation “Dell Precision 220” con 256Mb di RAM RIMM, Red Hat Linux 7.1 con tutti gli upgrade e kernel 2.4.14 installata su un HD QUANTUM ATLAS 10K2 (9Gb/10000rpm) pilotato da un controller Adaptec 29160N, il disco per le prove è un QUANTUM VIKING II (4.5Gb/7200 rpm) pilotato da un controller Adaptec 29240UW. La partizione di root è gestita dallo JFS versione 1.0.10.

Per completare la compilazione del kernel senza problemi prima è necessario installare le patch dello XFS, poi dello JFS. Le prove sullo ext3 sono state effettuate con lo stesso hardware però con kernel 2.4.9-12.

I software utilizzati sono 'bonnie++' e 'postmark'. Il primo simula il comportmanento in presenza di accessi a file singoli e di piccole dimensioni. L'utilizzo avviene per input in linea di comando. Per completare i test ho eseguito le seguenti procedure:

[root@localhost /root]# bonnie++ -d /mnt/rootfs -s 20 -r 4 -u 0 >bonnie.ext2.20M.csv

Il secondo è più adatto per testare il filesystem in presenza di applicazioni squisitamente Internet orientate: come un server di posta. L'utilizzo avviene con 'bash' integrata:

[root@localhost /root]# postmark

Postmark v1.5: 3/27/01

pm>set number 1000

pm>set transactions 10000

pm>run



Di seguito sono riportati i risultati delle prove.

Bonnie++

EXT2 – 20 Mb

Sequential Output

Sequential Input

Random Seeks

Per Chr

Block

Rewrite

Per Chr

Block


K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

sec

%CPU

9980,0

86,0

----

---

----

---

8741,0

80,0

----

---

1581,6

3,0



EXT2 -16 File

Sequential Create

Random Create

Create

Read

Delete

Create

Read

Delete

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

711,0

84,0

----

---

----

---

719,0

79,0

----

---

2393,0

85,0



EXT3 – 20 Mb

Sequential Output

Sequential Input

Random Seeks

Per Chr

Block

Rewrite

Per Chr

Block


K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

sec

%CPU

8876,0

83,0

----

---

----

---

9194,0

83,0

----

---

1567,6

4,0



EXT3 -16 File

Sequential Create

Random Create

Create

Read

Delete

Create

Read

Delete

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

487,0

82,0

----

---

23643

64

503,0

83,0

----

---

1695,0

79,0



ReiserFS – 20 Mb

Sequential Output

Sequential Input

Random Seeks

Per Chr

Block

Rewrite

Per Chr

Block


K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

sec

%CPU

9206,0

83,0

----

---

----

---

9292,0

76,0

----

---

1573

3,0



ReiserFS -16 File

Sequential Create

Random Create

Create

Read

Delete

Create

Read

Delete

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

10642

80,0

----

---

11496

84

8850,0

72

----

---

9735,0

84,0



JFS – 20 Mb

Sequential Output

Sequential Input

Random Seeks

Per Chr

Block

Rewrite

Per Chr

Block


K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

sec

%CPU

4703,0

41,0

----

---

----

---

9940,0

85,0

----

---

1581,0

3,0

JFS -16 File

Sequential Create

Random Create

Create

Read

Delete

Create

Read

Delete

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

3748,0

16,0

----

---

526,0

2,0

1573,0

16,0

----

---

285,0

2,0



XFS – 20 Mb

Sequential Output

Sequential Input

Random Seeks

Per Chr

Block

Rewrite

Per Chr

Block


K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

K/sec

%CPU

sec

%CPU

9889,0

85,0

----

---

----

---

9835,0

85,0

----

---

1578,0

3,0



XFS -16 File

Sequential Create

Random Create

Create

Read

Delete

Create

Read

Delete

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

/sec

%CPU

829,0

20,0

----

---

864,0'

18,0

822,0

21,0

----

---

248,0

5,0



Postmark

EXT2

Time:

2 seconds total

2 seconds of transactions (5000 per second)

Files:

5994 created (2997 per second)

4999 read (2499 per second)

4968 appended (2484 per second)

5994 deleted (2997 per second)

Data:

31.93 Mb read (15.97 Mb per second)

37.88 Mb written (18.94 Mb per second)



EXT3



Time:

11 seconds total

7 seconds of transactions (1428 per second)

Files:

5994 created (544 per second)

4999 read (714 per second)

4968 appended (709 per second)

5994 deleted (544 per second)

Data:

31.93 Mb read (2.90 Mb per second)

37.88 Mb written (3.44 Mb per second)



ReiserFS

Time:

9 seconds total

8 seconds of transactions (1250 per second)

Files:

5994 created (666 per second)

4999 read (624 per second)

4968 appended (621 per second)

5994 deleted (666 per second)

Data:

31.93 Mb read (3.55 Mb per second)

37.88 Mb written (4.21 Mb per second)



JFS

Time:

127 seconds total

106 seconds of transactions (94 per second)

Files:

5994 created (47 per second)

4999 read (47 per second)

4968 appended (46 per second)

5994 deleted (47 per second)

Data:

31.93 Mb read (257.47 kb per second)

37.88 Mb written (305.46 kb per second)



XFS



Time:

19 seconds total

16 seconds of transactions (625 per second)

Files:

5994 created (315 per second)

4999 read (312 per second)

4968 appended (310 per second)

5994 deleted (315 per second)

Data:

31.93 Mb read (1.68 Mb per second)

37.88 Mb written (1.99 Mb per second)



Links

http://www-124.ibm.com/developerworks/oss/jfs

http://oss.sgi.com/projects/xfs

http://www.namesys.com