# Ext4

ext4 o fourth extended filesystem è un file system journaled sviluppato come successore di ext3, incluso nel kernel Linux.

## Storia

ext4 nasce come una serie di estensioni retrocompatibili e aventi lo scopo di aumentare i limiti di immagazzinamento a 64 bit di ext3 e di migliorarne alcune prestazioni, ma per motivi di stabilità alcuni sviluppatori di Linux si opposero all'ingresso di tali estensioni nel kernel e proposero di effettuare un fork del codice di ext3 allo scopo di condurre lo sviluppo senza impattare sugli utenti di ext3; la proposta fu accettata e, il 28 giugno 2006 il responsabile (maintainer) di ext3, Theodore Ts'o, annunciò il nuovo piano di sviluppo di ext4.
Una release preliminare di ext4 fu inclusa in fase di sviluppo e sotto il nome ext4dev nella versione 2.6.19 del kernel Linux, distribuita il 29 novembre 2006; l'11 ottobre 2008 le patch che rendevano ext4 codice stabile furono inserite nei repository del codice sorgente di Linux 2.6.28, indicando la fine della fase di sviluppo e raccomandando l'adozione di ext4. Il kernel 2.6.28 fu distribuito il 25 dicembre 2008.

## Caratteristiche
### Volumi grandi

ext3 supporta file grandi al massimo 2 TiB, e file system grandi complessivamente 16 TiB. ext4 usa 48 bit per l'indirizzamento dei blocchi, quindi i limiti aumentano: si potranno avere file grandi fino a 16 TiB, ed i file system potranno essere grandi fino 1 EiB. Il motivo dell'utilizzo di 48 bit è dettato da alcune limitazioni che dovrebbero essere superate prima di poter portare l'indirizzamento dei blocchi di ext4 a 64 bit; tali correzioni tuttavia non rientrano nella pianificazione di ext4. Le strutture di ext4 sono state progettate tenendo a mente tale fatto, quindi un futuro aggiornamento di ext4 implementerà il completo supporto all'indirizzamento a 64 bit. 1 EiB è tuttavia sufficiente finché questo non accadrà.

### Extent

I file system di Unix tradizionali, come ext3, usano uno schema di mapping dei blocchi indiretto per tenere traccia di ogni blocco usato per memorizzare i dati di un file. Questa scelta è inefficiente per file molto grandi, specialmente per quanto riguarda le operazioni di cancellazione e di troncamento, perché tale mapping tiene una voce per ogni singolo blocco; questo significa che per file che utilizzano molti blocchi si ha un mapping enorme, lento da gestire. I file system moderni usano un approccio differente chiamato "extent". Un extent è un gruppo di blocchi fisicamente contigui. In pratica si dice "I dati del file sono nei prossimi N blocchi". Per esempio, un file grande 100 MB può essere allocato in un unico extent di tale dimensione (la massima dimensione di un extent è 128 MB), invece di creare il mapping indiretto per 25600 blocchi (un blocco contiene 4 KB di dati). File ancora più grandi sono divisi in più extent. Gli extent migliorano le performance dal momento che un extent incoraggia allocazioni di blocchi contigue sul disco ma aumentano la frammentazione esterna.

### Allocazione multiblocco

Quando ext3 deve scrivere nuovi dati su un disco, è l'allocatore di blocchi a decidere quali blocchi liberi saranno usati per scrivere i nuovi dati. Ma l'allocatore di blocchi di ext3 può allocare solamente un blocco (4 KB) alla volta. Questo significa che se il sistema necessita di allocare i 100 MB menzionati precedentemente, dovrà chiamare l'allocatore di blocchi 25600 volte. Questo non solo è inefficiente, ma non permette all'allocatore di blocchi di ottimizzare la politica di allocazione perché esso non sa quanti blocchi il sistema vuole allocare, sa solamente che gli è stato chiesto di allocare un blocco.
ext4 usa un allocatore multiblocco (mballoc) che può allocare più blocchi per ogni singola chiamata, invece di uno solo; questo limita molto l'overhead. Inoltre tale caratteristica migliora le performance, ed è particolarmente utile con l'allocazione ritardata e gli extent. Questa caratteristica non influenza il formato dei dati sul disco. Infine si noti che l'allocatore di blocchi di ext4 ha altri miglioramenti.

### Allocazione ritardata

L'allocazione ritardata è una caratteristica il cui effetto interessa "solo" le prestazioni (infatti non cambia il formato dei dati sul disco). Tale caratteristica, che si trova in molti file system moderni come XFS, ZFS, Btrfs o Reiser4, consiste nel ritardare l'allocazione di blocchi il più possibile; contrariamente a quanto fanno i file system tradizionali (come ext3, ReiserFS, ecc): allocare i blocchi il prima possibile. Per esempio, se un processo compie un'operazione di scrittura, il file system alloca immediatamente i blocchi dove i dati saranno memorizzati, anche se i dati poi non verranno scritti immediatamente ma finiranno in cache per un po' di tempo. Questo approccio ha degli svantaggi. Per esempio quando un processo scrive continuamente su un file che cresce, le scritture successive allocano i blocchi per i dati, ma non sanno se il file continuerà a crescere. L'allocazione ritardata, invece, non alloca i blocchi immediatamente quando il processo scrive, ma piuttosto ritarda l'allocazione fintanto che il file è tenuto in cache, cioè fino a quando il file non sarà effettivamente scritto sul disco. Questa caratteristica dà all'allocatore di blocchi l'opportunità di ottimizzare l'allocazione in situazioni in cui un vecchio file system non avrebbe potuto. L'allocazione ritardata funziona veramente bene con le due caratteristiche elencate precedentemente: gli extent e l'allocazione multiblocco, perché in molti processi di scrittura quando un file è scritto effettivamente sul disco, sarà allocato in extent i cui blocchi saranno allocati più di uno alla volta. Le performance sono migliori, e la frammentazione è migliorata in alcuni processi di scrittura. Un altro vantaggio è che i file temporanei, che spesso hanno vita breve, non vengono neppure scritti sul disco, risparmiando in tal modo cicli di scrittura e di cancellazione. Tuttavia l'allocazione ritardata fa sì che i dati rimangano in RAM per un tempo maggiore, prima di essere scritti sul supporto fisico, quindi una accidentale caduta di tensione o spegnimento del dispositivo, faranno cancellare tutti i dati non ancora salvati. Per forzare una scrittura dei dati su supporto fisico vedere il comando sync.

### Retrocompatibilità

Il filesystem ext4 è retrocompatibile con ext3 ed ext2, rendendo così possibile montare un filesystem ext3 o ext2 come ext4.

### Compatibilità in avanti

Il filesystem ext4 è parzialmente compatibile in avanti con ext3. Questo significa che una partizione ext4 può essere montata come ext3 (usando "ext3" come tipo di filesystem). Tuttavia, se la partizione ext4 usa gli extent (una delle principali caratteristiche introdotte in ext4), si perde la compatibilità in avanti.
Gli extent vengono abilitati di default a partire dal kernel 2.6.23. Precedentemente l'opzione "extents" andava attivata esplicitamente (es. mount /dev/sda1 /mnt/point -t ext4dev -o extents).

### Preallocazione persistente

Questa caratteristica, disponibile in ext4 nelle versioni di kernel più recenti, ed emulata dalla glibc nei file system che non la supportano, permette alle applicazioni di preallocare spazio su disco: le applicazioni dicono al file system di preallocare lo spazio, ed il file system prealloca i blocchi e le strutture dati necessarie, ma non ci sono dati memorizzati in essi fino a che l'applicazione non avrà realmente bisogno di scrivere dati. In realtà è ciò che fanno i programmi di P2P per conto loro: "preallocano" lo spazio necessario per un file che verrà scaricato dopo ore o giorni, ma implementato molto più efficientemente dal file system e con un'API generica. Tutto ciò ha molti usi: in primo luogo, evitare che le applicazioni (come quelle di P2P sopra citate) compiano quest'azione da soli in maniera inefficiente (riempiendo cioè il file di zeri). In secondo luogo, per migliorare la frammentazione, dato che i blocchi saranno allocati tutti insieme, più contigui possibile. Terzo, per assicurarsi che le applicazioni abbiano sempre lo spazio che sanno che servirà loro, il che è molto importante per applicazioni Real Time (infatti senza la preallocazioni il file system potrebbe risultare pieno nel bel mezzo di un'operazione importante).

### Rimozione del limite di 32000 sottodirectory

In ext3 il massimo numero possibile di sottodirectory contenute in una singola cartella è 32000. ext4 supera questo limite permettendo un numero illimitato di sottodirectory. Per non portare ad un degrado delle prestazioni in caso di directory di grandi dimensioni, ext4 introduce per default l'indicizzazione tramite H-tree (una versione di B-Tree). Questa caratteristica è presente a partire dal kernel 2.6.23. H-tree è presente anche nei file system ext3 con dir_index abilitato.

### Deframmentazione in linea

Nonostante l'allocazione ritardata, gli extent e l'allocazione multiblocco aiutino a ridurre la frammentazione del file system, è inevitabile che con l'utilizzo questa compaia. Per esempio, se si salvano tre file in una directory e conseguentemente sul disco e qualche giorno dopo si modifica il file centrale in maniera da fare aumentare la sua dimensione, le uniche opzioni sono frammentare la parte in eccesso (che causerebbe un seek), oppure spostare il file in una zona più grande (che causerebbe un seek ad un'ipotetica applicazione che voglia leggere tutti i file della cartella, come ad esempio un file manager che vuole creare le anteprime di tutte le immagini di una cartella). D'altra parte, il file system può occuparsi solo di certi tipi di frammentazione: non può sapere, per esempio, che deve tenere contigui tutti i file relativi al boot, perché non sa quali sono i file relativi al boot. Per risolvere questo problema, ext4 supporta la deframmentazione in linea. In più esiste un tool (e4defrag) che può deframmentare file singoli oppure l'intero file system.

### Controllo dell'integrità più rapido

Il controllo dell'integrità del file system (fsck) è molto lento, specialmente per quanto riguarda il primo passo: il controllo di tutti gli inode del file system. In ext4, alla fine di ogni tabella di gruppo di inode, è salvata una lista dei blocchi inutilizzati (con un checksum, per sicurezza), quindi fsck non controllerà tali nodi. Il risultato è che il tempo complessivo impiegato da fsck migliora da 2 a 20 volte, a seconda del numero di inode usati. Si noti che è fsck, e non ext4, a costruire la lista degli inode inutilizzati. Ciò significa che è necessario eseguire fsck per creare le liste degli inode inutilizzati, e solo dalla successiva esecuzione fsck sarà più rapido (in particolare è necessario eseguire fsck per convertire un file system ext3 in ext4). C'è un'altra caratteristica che prende parte nella velocizzazione di fsck, e si tratta dei "gruppi flessibili di blocchi", che contribuiscono a velocizzare le operazioni del file system.

### Caratteristiche relative agli inode

Inode più larghi, timestamp in nanosecondi, attributi estesi, prenotazione inode.
* Inode più larghi: ext3 permette di configurare la dimensione degli inode (tramite il parametro -I di mkfs), ma la dimensione di default è 128 byte. ext4 invece usa 256 byte come valore di default. Questo è reso necessario per permettere di usare dei campi extra (come il timestamp in nanosecondi o la versione di inode): lo spazio rimanente dell'inode sarà usato per memorizzare attributi estesi che sono piccoli a sufficienza per entrare in quello spazio. Questo rende l'accesso a tali attributi molto più veloce, e migliora le performance delle applicazioni che usano gli attributi estesi (di un fattore da 3 a 7).
* Prenotazione inode: consiste nel riservare alcuni inode quando viene creata una directory, immaginando che tali inode saranno usati in futuro. Questa scelta migliora le performance, perché quando nuovi file sono creati in tale directory, essi saranno memorizzati negli inode riservati. Ne consegue che la creazione e la cancellazione di tali file sono più efficienti.
* Timestamp in nanosecondi: dato che i computer diventano sempre più veloci, e Linux è usato in molte applicazioni mission critical, esprimere i timestamp in secondi diventa insufficiente. ext4 quindi memorizza i timestamp in nanosecondi (miliardesimi di secondo).
Questa caratteristica è presente a partire dal kernel 2.6.23.

### Barriere attive di default

Questa opzione incrementa l'affidabilità del file system a costo di un po' di performance (si può disabilitare con "mount -o barrier=0"). Il file system, prima di scrivere la commit del journaling, deve assicurarsi che tutte le informazioni della transazione siano salvate nel journal. Fare semplicemente le scritture nell'ordine corretto non è sufficiente; i dispositivi attuali sono dotati di molta cache, e riordinano le operazioni per migliorare le performance. Quindi il file system deve esplicitamente richiedere al disco di scrivere concretamente tutti i dati del journal prima di scrivere il record di commit; se il record di commit fosse scritto per primo, il journal potrebbe risultare corrotto. Il sottosistema dell'I/O a blocchi rende possibile tutto ciò tramite l'uso delle barriere; in sostanza, una barriera impedisce la scrittura di blocchi dopo la barriera fino a che tutti i blocchi scritti prima della barriera siano scritti concretamente sul mezzo. Usare le barriere permette al file system di garantire la consistenza della propria struttura in ogni momento.

### Modalità "No Journaling"

Il journaling assicura l'integrità del file system mantenendo un log dei cambiamenti che stanno per essere apportati al disco. Comunque, è ovvio che causi un piccolo overhead. Alcuni sistemi con requisiti speciali possono usare ext4 disabilitando il journaling, ed ottenere così un lieve incremento delle prestazioni al costo di un maggiore rischio di danni causati da problemi hardware come i cali di tensione.