Non avendo mai avuto un lettore di floppy per il mio amato Commodore 128, la prima occasione per lavorare seriamente coi filesystem è stata quella con l’Amiga (che tra l’altro ai tempi aveva già un comodissimo sistema di tipo plug & play per montare e smontare a piacimento nuovi filesystem “a caldo”, senza mai riavviare la macchina).
Da lì in poi è venuto fuori il tipico problema dovuto al classico black-out o sbalzo di tensione (verificatisi immancabilmente proprio mentre stavo scrivendo un file su disco): la corruzione o, peggio ancora, la perdita dei dati.
E’ fuor di dubbio che di fronte a fenomeni come questi e senza un gruppo di continuità è praticamente impossibile aspettarsi che non sia successo qualcosa ai dati. Anche se abbiamo superato il tempo dei floppy e abbiamo gli hard disk, questi ultimi sono quasi sempre in movimento (mentre con AmigaOS lo erano soltanto “a comando”, a seguito di precise azioni dell’utente) e spesso in scrittura, dunque non è raro che capiti qualcosa di spiacevole, com’è avvenuto di recente con l’ultima versione del più diffuso filesystem di Linux, EXT, ma… senza blackout!
Ne ha parlato di recente un programmatore su un apposito bug track che è stato aperto per mettere a conoscenza la comunità dell’esistenza di questo problema che ha implicazioni molto importanti, visto che, appunto, provoca la perdita dei dati. E qui, come ho già detto, non possiamo dare la colpa alla solita società che ci fornisce l’energia elettrica, visto che si verifica anche con la macchina perennemente accesa, e magari ben protetta da un gruppo di continuità.
E’ evidente che la causa vada ricercata nella struttura del filesystem oppure nella sua implementazione. Nel primo caso questi potrebbe non integrare appositi meccanismi per la salvaguardia delle informazioni e/o il ripristino da condizioni nefaste come la mancanza di corrente. Ma non ricadiamo in tali condizioni estreme, quindi è l’implementazione a essere difettosa o, magari, proprio voluta così.
A quanto pare è esattamente in questo modo che sono andate le cose: gli implementatori hanno pensato bene di utilizzare una pratica che sembra comune ai filesystem più moderni, chiamata delayed allocation (allocazione posticipata), per cui i dati scritti dall’applicazione (per la precisione nella modalità di append, quindi scrivendo sempre alla fine del file) rimangono esclusivamente in memoria, e i blocchi (o cluster) da allocare vengono soltanto sottratti dal numero totale di blocchi liberi, senza riservarli immediatamente.
Quindi le informazioni rimaste in memoria lo rimarranno finché il sistema operativo non deciderà finalmente di scriverli effettuando ogni tanto il cosidetto flush dei dati, che consiste appunto nello scrivere quelli che finora erano rimasti in memoria ed essere in perfetta sincronia col dispositivo di massa. Il problema è che, con gli esempi evidenziati nel link, ciò provoca una perdita dei dati se non si forza manualmente il loro flush utilizzando un’apposita API (fsync) del s.o..
In buona sostanza l’autore dell’articolo ha deciso di scaricare la colpa ai programmatori che non sono abbastanza “attenti” nello scrivere i loro programmi. Ma subito dopo si lamenta che l’invocazione della fsync ha un forte impatto (negativo, ovviamente) sulle prestazioni (e ciò è indubbiamente vero)!
A questo punto rivolge le sue invettive sugli (sempre scarsi ovviamente) programmatori che scrivono miriadi di piccoli file, e che forzando l’fsync per ogni file metterebbero in ginocchio il sistema. A parte lo scenario improbabile (scrivere centinaia di piccoli file nello stesso momento mi pare poco realistico), ho l’impressione che si tratti di una persona che non è mai soddisfatta del lavoro degli altri, ma soprattutto che guarda soltanto al lavoro degli altri, ma non a quello dei programmatori di sistema.
Come programmatore ho un’opinione diversa dalla sua. Per quanto mi riguarda io ho “stipulato un contratto” col s.o., e tale contratto è rappresentato dalle API. Una volta chiuso il file, anche senza aver mai usato la fsync, e senza che il s.o. abbia sollevato eccezioni (dandomi, quindi, l’OK), il mio lavoro è finito e il s.o. ha in mano tutte le informazioni necessarie per gestire correttamente anche questi casi.
Questo perché io non posso sapere in alcun modo che fine farà il file e i dati che conteneva, una volta che l’ho chiuso. In nessun modo. E nemmeno mi deve interessare saperlo: il mio lavoro l’ho portato a termine e non me ne devo più preoccupare.
A questo punto, visto che i problemi dovuti all’allocazione posticipata sono ben noti e, soprattutto, ampiamente prevedibili, dev’essere il filesystem (mi riferisco all’implementazione, cioé al codice) a intercettarli e a prendere le dovute iniziative atte a garantire la giusta sequenziazione delle scritture dei dati.
Per me non ha senso né che un filesystem adotti politiche che possono provocare perdite di dati a fronte di incrementi prestazionali, ma nemmeno costringere gli sviluppatori a utilizzare sempre la fsync che le fa decadere troppo e sempre. I conflitti vengano risolti da chi di competenza, ma soprattutto dall’unico ente che è in grado di rilevarli e risolverli, azzerando le perdite dei dati e limitando le prestazioni esclusivamente nel momento in cui si verificano (cosa impossibile per una normale applicazione).
Questo ovviamente complicherebbe l’implementazione, ma garantirebbe il miglior compromesso prestazionale possibile, salvaguardando sempre e comunque l’integrità dei dati, che ricordo essere l’obiettivo più importante per questo delicatissimo componente del s.o. (infatti è fra i software che richiedono più tempo e risorse per andare in produzione, a causa del numero di attenzioni e test notevolmente più elevato rispetto alle altre componenti; probabilmente il solo kernel richiede molte più attenzioni).
Altra cosa, nel link, come già detto, si afferma che tutti i filesystem moderni fanno uso dell’allocazione ritardata e, quindi, sono soggetti agli stessi problemi. Da una rapida ricerca sembra, invece, che siano soltanto cinque: HFS+, XFS, Reiser4, ZFS ed ext4.
Questo, lo ribadisco se non fosse chiaro, è il mio personalissimo punto di vista sulla faccenda e sull’argomento filesystem e integrità dei dati. E vale ovviamente anche per i database, che hanno problematiche simili, anche se a scala più ridotta (si occupano di singoli archivi/file; i filesystem, invece, di tutti i file in esso contenuti, quindi anche di eventuali database).
Visto che oggi c’è una varietà di filesystem a disposizione e sufficiente libertà di scelta, il mio consiglio è di vagliare attentamente quale soluzione adottare per l’archiviazione dei nostri contenuti. Ricordate: gli stiamo affidando i nostri dati. E io ci tengo a che non si perdano.