La lliçó anterior va acabar amb una dada que mereix explicació. filefrag ens va dir que els 4.219 blocs de 2026-08-31.dat són en un sol extent, perfectament contigus del bloc 8.394.271 al 8.398.489. I tanmateix aquell fitxer es va escriure 24 bytes cada 125 mil·lisegons durant 24 hores, mentre meteo-api, l'agregador, els registres del sistema i mitja dotzena de serveis més escrivien al mateix volum. Com acaba contigu un fitxer escrit així?
Aquesta és la primera meitat d'aquesta lliçó: com decideix un sistema de fitxers quins blocs ocupa un fitxer, com porta el compte dels que estan lliures, i com representa aquella llista dins d'un inode que només té 60 bytes per a punters. Recorrerem les quatre estratègies històriques —contigua, enllaçada, indexada i per extents— amb els números concrets de Meteora, i entendràs de passada per què FAT32 és lenta amb fitxers grans i per què desfragmentar ja no té sentit.
La segona meitat és més greu. Afegir un bloc a un fitxer no és una operació, en són tres: escriure la dada, marcar el bloc com a ocupat al mapa de bits, i actualitzar l'inode amb la seva adreça nova i la mida. Si es talla la llum entre aquelles tres escriptures, el sistema de fitxers queda en un estat incoherent que pot anar des d'una pèrdua d'espai innòcua fins a la corrupció creuada de dos fitxers. Veurem com el diari (journal) converteix tres operacions en una transacció atòmica, què garanteix exactament cadascun dels tres modes d'ext4, i per què la consistència de metadades no és el mateix que la integritat de les dades: un bit que es corromp al plat passa desapercebut per a ext4, per a XFS i per al RAID 1 de Meteora.
Contingut
- Assignació contigua: ràpida i fràgil
- Assignació enllaçada i la taula FAT
- Assignació indexada: l'inode i els seus punters indirectes
- Extents: la solució moderna, mesurada sobre Meteora
- Gestió de l'espai lliure
- Fragmentació: per què ext4 i XFS fragmenten poc
- El problema de la consistència: tres escriptures i un tall de llum
fscki per què el seu cost és inacceptable- El diari: transacció, confirmació, aplicació i recuperació
- Els tres modes d'ext4 i quin tria Meteora
- Alternatives al diari: còpia en escriure i log-structured
- Integritat de dades: sumes de verificació i corrupció silenciosa
- Barreres d'escriptura i discos que menteixen
- Instantànies i còpies de seguretat: una altra capa
Assignació contigua: ràpida i fràgil
La idea més simple: cada fitxer ocupa un conjunt de blocs consecutius. L'inode només necessita guardar dos números, el bloc inicial i la longitud.
Els seus avantatges són notables. La lectura seqüencial és òptima: una sola petició d'E/S porta el fitxer sencer, sense buscar res. L'accés aleatori és trivial: el bloc del byte N és a inici + N/4096, una divisió. I les metadades són mínimes: vuit bytes descriuen un fitxer de qualsevol mida.
Però té dos problemes que la descarten per a ús general:
Fragmentació externa. En crear i esborrar fitxers de mides diferents, l'espai lliure queda trossejat en forats petits. Pots tenir 40 GB lliures i no poder crear un fitxer de 100 MB perquè el forat contigu més gran són 60 MB. És exactament la fragmentació externa que vam veure a Gestió de Memòria amb l'assignació per particions variables, i la solució seria igual de cara: compactar, és a dir, moure físicament gigabytes de dades.
No pot créixer. L'ingestor comença el dia amb un fitxer buit i li afegeix 17 MB al llarg de 24 hores. Amb assignació contigua caldria declarar la mida final per endavant, i si et quedes curt, l'única sortida és copiar el fitxer sencer a un forat més gran.
Per això l'assignació contigua sobreviu només on el contingut és immutable i es coneix per endavant: CD-ROM i DVD (ISO 9660), i els extents moderns, que són «contigüitat per trossos» i recuperen els seus avantatges sense els seus problemes.
Assignació enllaçada i la taula FAT
L'alternativa oposada: cada bloc guarda un punter al següent, i l'inode només apunta al primer. Els blocs poden ser on sigui.
Resol de cop els dos problemes anteriors: no hi ha fragmentació externa —qualsevol bloc lliure serveix— i créixer és trivial: s'agafa un bloc lliure i s'enllaça. Però n'introdueix dos altres, pitjors:
- L'accés aleatori és O(n). Per llegir el bloc 4.000 cal llegir els 4.000 anteriors, perquè el punter al següent és dins de cada bloc. Un
lseekdeixa de ser gratis. - El punter roba espai al bloc. Si el punter ocupa 4 bytes, un bloc de 4.096 només emmagatzema 4.092 de dades, i les lectures deixen d'estar alineades amb les pàgines.
La solució de FAT. El sistema de fitxers d'MS-DOS va resoldre el segon punt traient tots els punters fora dels blocs, a una taula única: la File Allocation Table. És un array amb una entrada per cada bloc —anomenat cluster en la terminologia FAT— el valor del qual és el número del següent cluster del fitxer, o un valor especial:
| Valor de l'entrada | Significat |
|---|---|
0x00000000 |
Cluster lliure |
2 … 0x0FFFFFEF |
Número del següent cluster de la cadena |
0x0FFFFFF7 |
Cluster defectuós |
0x0FFFFFF8-0x0FFFFFFF |
Fi de la cadena (EOF) |
Un fitxer que comença al cluster 100 se segueix llegint FAT[100] = 250, FAT[250] = 251, FAT[251] = 999, FAT[999] = EOF. L'entrada de directori només guarda el primer cluster.
Les millores sobre la llista enllaçada pura són reals: els blocs de dades queden sencers per a dades, i si la FAT cap a la memòria, recórrer la cadena no costa accessos a disc. Però els problemes de fons continuen:
L'accés aleatori continua sent O(n) a la taula. Per arribar al cluster 4.000 cal recórrer 4.000 entrades. Si la FAT és a la RAM són 4.000 accessos a memòria —ràpid però no gratis—; si no hi cap, són milers d'accessos a disc.
La FAT creix amb el volum i cal tenir-la a la RAM. Amb clusters de 4 KiB, un volum d'1 TB té 268.435.456 clusters, i a 4 bytes per entrada la taula fa 1 GiB. Aquest és el motiu real pel qual FAT32 no es fa servir en volums grans: no és el límit de 4 GiB per fitxer, és que la taula d'assignació es torna impossible de manejar.
La FAT és un punt únic de fallada. Si es corromp, es perden totes les cadenes de tots els fitxers. Per això FAT en guarda dues còpies i per això chkdsk existeix.
I no hi ha diari. Un tall de llum mentre s'actualitza la FAT deixa cadenes trencades, clusters perduts i enllaços creuats: dos fitxers les cadenes dels quals conflueixen i comparteixen clusters, de manera que escriure en un corromp l'altre.
Assignació indexada: l'inode i els seus punters indirectes
La solució d'UNIX: reunir tots els punters d'un fitxer al seu propi inode, en lloc d'en una taula global. Cada fitxer té el seu índex, i només es llegeix l'índex del fitxer que estàs fent servir.
El problema immediat és la mida. L'inode fa 256 bytes i reserva 60 bytes per a punters: amb punters de 4 bytes, n'hi caben 15. Amb blocs de 4 KiB, això són 60 KiB. Ridícul.
La solució clàssica d'UNIX és elegant: els quinze punters no són tots iguals.
| Punter | Tipus | A què apunta | Blocs que adreça | Mida acumulada |
|---|---|---|---|---|
| 0-11 | Directes | Blocs de dades | 12 | 48 KiB |
| 12 | Indirecte simple | Un bloc de punters | 1.024 | +4 MiB |
| 13 | Indirecte doble | Un bloc de punters a blocs de punters | 1.024² = 1.048.576 | +4 GiB |
| 14 | Indirecte triple | Tres nivells | 1.024³ = 1.073.741.824 | +4 TiB |
El càlcul, amb blocs de 4 KiB i punters de 4 bytes, és el que cal saber fer:
Punters per bloc = 4096 B / 4 B = 1.024
Directes: 12 × 4 KiB = 48 KiB
Indirecte simple: 1.024 × 4 KiB = 4 MiB
Indirecte doble: 1.024 × 1.024 × 4 KiB = 4 GiB
Indirecte triple: 1.024 × 1.024 × 1.024 × 4 KiB = 4 TiB
─────────────
Mida màxima de fitxer ≈ 4 TiB + 4 GiB + 4 MiB + 48 KiB ≈ 4,004 TiBLa bellesa de l'esquema és que el cost és proporcional a la mida. Un fitxer de 40 KiB fa servir només punters directes: llegir qualsevol dels seus blocs costa un accés, perquè l'adreça és a l'inode que ja has llegit. Només els fitxers enormes paguen els tres nivells d'indirecció:
| Mida del fitxer | Accessos extra per llegir un bloc qualsevol |
|---|---|
| ≤ 48 KiB | 0 (punter a l'inode) |
| ≤ 4 MiB | 1 |
| ≤ 4 GiB | 2 |
| ≤ 4 TiB | 3 |
Ara, 2026-08-31.dat amb aquest esquema. Necessita 4.219 blocs:
- Els 12 primers van als punters directes.
- Els 1.024 següents, a l'indirecte simple: acumulat 1.036.
- Els 3.183 restants van a l'indirecte doble, que necessita ⌈3.183 / 1.024⌉ = 4 blocs de segon nivell.
Total de blocs de metadades: 1 (indirecte simple) + 1 (arrel del doble) + 4 (segon nivell) = 6 blocs, 24 KiB. I llegir el bloc 4.000 del fitxer costa 3 accessos: arrel del doble, bloc de segon nivell i, per fi, la dada.
Un detall important d'implementació: el bloc de punters amb tot zeros representa un forat. Així és com ext2/ext3 implementen els fitxers dispersos de 04-04 sense cap estructura addicional.
Extents: la solució moderna, mesurada sobre Meteora
Els punters indirectes tenen un defecte de fons: emmagatzemen una adreça per bloc, encara que els blocs siguin consecutius. Per a un fitxer de 17 MB contigu, guarden 4.219 números que van del 8.394.271 al 8.398.489, un darrere l'altre. És una llista redundant.
Un extent és un rang contigu descrit amb tres números: bloc lògic d'inici, bloc físic d'inici i longitud. A ext4 ocupa 12 bytes:
struct ext4_extent {
__le32 ee_block; /* primer bloc LÒGIC que cobreix aquest extent */
__le16 ee_len; /* quants blocs: fins a 32.768 = 128 MiB */
__le16 ee_start_hi; /* bloc FÍSIC, 16 bits alts */
__le32 ee_start_lo; /* bloc FÍSIC, 32 bits baixos */
};Els 60 bytes de l'inode allotgen una capçalera de 12 bytes més 4 extents. Si un fitxer en necessita més de 4, aquells 60 bytes passen a descriure l'arrel d'un arbre d'extents, amb nodes interns en blocs a part.
La comparació, sobre 2026-08-31.dat:
| Punters indirectes (ext2/ext3) | Extents (ext4) | |
|---|---|---|
| Estructures per descriure 4.219 blocs | 4.219 punters | 1 extent |
| Blocs de metadades extra | 6 (24 KiB) | 0 |
| Bytes de descripció | 16.876 | 12 |
| Accessos per llegir el bloc 4.000 | 3 | 0 |
| Accessos per llegir el fitxer sencer | 4.219 + 6 | 1 petició seqüencial |
De 16.876 bytes de metadades a 12: una reducció de 1.400×. I ho vam verificar a 04-04:
$ sudo filefrag -v /var/lib/meteora/lectures/2026-08-31.dat File size of ...2026-08-31.dat is 17280000 (4219 blocks of 4096 bytes) ext: logical_offset: physical_offset: length: expected: flags: 0: 0.. 4218: 8394271.. 8398489: 4219: last,eof /var/lib/meteora/lectures/2026-08-31.dat: 1 extent found
Un extent per a tot el fitxer. Compara-ho amb un fitxer fragmentat, que és el que veuries en un volum ple:
3.847 extents signifiquen 3.847 salts: en un HDD, 3.847 cerques de 8 ms cadascuna, més de 30 segons només a posicionar el capçal.
XFS fa servir la mateixa idea amb arbres B+ des del 1994, i els seus extents arriben a 2 milions de blocs (8 GiB) cadascun. La taula comparativa de les quatre estratègies:
| Contigua | Enllaçada / FAT | Indexada (inodes) | Extents | |
|---|---|---|---|---|
| Fragmentació externa | Sí, greu | No | No | Poca |
| Pot créixer | No | Sí | Sí | Sí |
| Accés aleatori | O(1) | O(n) | O(1) amb 0-3 accessos | O(1) o O(log n) |
| Metadades per a 17 MB | 8 bytes | 16.876 B a la FAT global | 16.876 B + 6 blocs | 12 bytes |
| Fitxers dispersos | No | No | Sí | Sí |
| Fet servir avui a | ISO 9660 | FAT32, exFAT | ext2, ext3 | ext4, XFS, Btrfs, NTFS |
Gestió de l'espai lliure
L'altra meitat del problema: saber quins blocs estan lliures. Hi ha quatre enfocaments.
Mapa de bits. Un bit per bloc: 1 ocupat, 0 lliure. És el que fa servir ext4, i ho vam veure a 04-01.
- Mida: 1 bit per bloc de 4 KiB = 32 KiB de mapa per cada GiB, o 6,25 MiB per a 200 GiB.
- Buscar un bloc lliure: recórrer bits, accelerat amb instruccions de la CPU que n'examinen 64 alhora.
- Avantatge decisiu: trobar un rang contigu és trivial —buscar N zeros seguits—, i això és justament el que cal per assignar extents.
Llista enllaçada de blocs lliures. Cada bloc lliure apunta al següent. Ocupa zero espai addicional, però no permet trobar rangs contigus: els blocs surten en l'ordre en què es van alliberar, que és aleatori. És la raó que un sistema amb llista enllaçada fragmenti sense remei.
Agrupació (grouping). Un bloc lliure conté les adreces dels N blocs lliures següents. Redueix els accessos a disc enfront de la llista simple, però continua sense ajudar amb la contigüitat.
Comptadors / arbres. Guardar parells (primer bloc lliure, quants de consecutius). Molt compacte quan l'espai lliure està poc fragmentat, i si s'organitza en un arbre B+ indexat per longitud permet respondre «dona'm 4.219 blocs seguits» en O(log n). És el que fa XFS, amb dos arbres B+ per grup d'assignació: un ordenat per adreça i un altre per mida.
| Mètode | Espai | Buscar 1 bloc | Buscar N contigus | Fet servir a |
|---|---|---|---|---|
| Mapa de bits | 32 KiB/GiB | O(n/64) | Bo | ext4, NTFS |
| Llista enllaçada | 0 | O(1) | Impossible | Sistemes antics |
| Agrupació | Baixa | O(1) | Dolent | Variants d'UNIX |
| Arbres B+ | Variable | O(log n) | Òptim | XFS, Btrfs |
Fragmentació: per què ext4 i XFS fragmenten poc
Torna la pregunta del principi: com acaba contigu un fitxer escrit 24 bytes cada 125 mil·lisegons durant un dia? La resposta són tres mecanismes que treballen junts.
1. Assignació diferida (delayed allocation). És el més important i el més contraintuïtiu. Quan l'ingestor fa write(), ext4 no assigna cap bloc: només marca la pàgina com a bruta a la memòria cau (04-04) i anota quant espai caldrà. L'assignació real es posposa fins que el nucli va a abocar de debò.
La conseqüència és enorme: quan arriba el moment d'assignar, el sistema ja sap quants blocs necessita el conjunt, en lloc d'haver de decidir un a un sense saber si n'hi haurà més. En lloc de 4.219 decisions aïllades, pren unes poques decisions informades i demana rangs grans.
2. Assignació multibloc (multiblock allocation). Amb aquella informació, ext4 demana a l'assignador un rang contigu de la mida necessària d'una sola vegada. El mapa de bits, que és bo buscant zeros consecutius, l'hi dona. D'aquí surt l'extent únic.
3. Grups de blocs i preassignació. Els grups de 128 MiB de 04-01 mantenen junts l'inode i les seves dades, i ext4 a més preassigna especulativament un marge darrere d'un fitxer que està creixent, i l'hi reserva. Si el fitxer continua creixent, s'estén sobre la seva pròpia reserva en lloc de saltar a un altre lloc; si no, la reserva s'allibera en tancar.
Els tres junts expliquen el resultat: l'ingestor escriu durant 24 hores i ext4 va estenent un únic extent, perquè cada vegada que necessita més espai ja el tenia reservat just darrere.
Es comprova l'estat global d'un volum amb:
$ sudo e2fsck -fn /dev/md0 | tail -3 /dev/md0: 1834/200000 files (0.4% non-contiguous), 10736521/52428800 blocks
0,4 % de fitxers no contigus. Compara-ho amb FAT32 després d'un any d'ús, on el 30-40 % és normal.
Per què desfragmentar amb prou feines té sentit avui
Tres raons acumulatives:
- Els sistemes de fitxers moderns no fragmenten gaire, pels tres mecanismes anteriors. Un ext4 amb menys del 85 % d'ocupació es manté per sota del 2 % de fitxers no contigus indefinidament.
- En un SSD la fragmentació és gairebé irrellevant. No hi ha capçal per moure: l'accés a qualsevol pàgina costa el mateix (02-05). El que sí que importa és el nombre de peticions, i allà un fitxer amb 3.847 extents continua sent pitjor que un amb 1, però la diferència és d'un factor 2 o 3, no de 100.
- Desfragmentar un SSD el desgasta. Moure 200 GB són 200 GB de cicles d'escriptura consumits per a un benefici marginal. És activament perjudicial.
L'únic cas en què continua tenint sentit és un HDD molt ple amb fitxers grans molt fragmentats. Per a això existeixen e4defrag a ext4 i xfs_fsr a XFS, sempre en calent i per fitxers concrets:
sudo filefrag /srv/backup/imatge-vm.qcow2 # 3847 extents
sudo e4defrag /srv/backup/imatge-vm.qcow2
sudo filefrag /srv/backup/imatge-vm.qcow2 # 12 extentsRegla pràctica: mantén els volums per sota del 85 % d'ocupació. És infinitament més eficaç que desfragmentar, perquè un assignador que no troba forats grans fragmenta necessàriament. La fragmentació és un símptoma de volum ple, no una malaltia pròpia.
El problema de la consistència: tres escriptures i un tall de llum
Canviem de tema i de gravetat. Quan l'ingestor afegeix un bloc a 2026-08-31.dat, el sistema de fitxers ha de fer tres escriptures en tres llocs diferents del disc:
- El bloc de dades, a la zona de dades.
- El mapa de bits de blocs, marcant aquell bloc com a ocupat.
- L'inode, amb la nova adreça (o l'extent estès) i la mida actualitzada.
Aquestes tres escriptures no poden ser atòmiques: són en llocs diferents del dispositiu, i el disc només garanteix atomicitat a nivell de sector. Un tall de llum pot passar en qualsevol punt intermedi, i cada combinació deixa un estat diferent:
| Escriptures completades | Estat resultant | Gravetat |
|---|---|---|
| Cap | Coherent: l'operació no va passar | Cap |
| Només dades | Coherent: bloc orfe amb brossa, marcat lliure | Cap |
| Dades + mapa de bits | Bloc marcat ocupat que no pertany a ningú | Lleu: espai perdut |
| Dades + inode | L'inode apunta a un bloc marcat com a lliure | GREU |
| Mapa de bits + inode | El fitxer «té» un bloc amb dades antigues o brossa | Mitjana |
| Només inode | Apunta a un bloc lliure i sense dades | GREU |
| Les tres | Coherent i correcte | Cap |
Les dues files marcades com a GREU ho són per la mateixa raó, i val la pena entendre-la bé: si l'inode apunta a un bloc que el mapa de bits considera lliure, l'assignador el donarà al fitxer següent que demani espai. A partir d'aquell moment dos fitxers comparteixen un bloc físic, i escriure en un corromp l'altre. És l'enllaç creuat, la pitjor corrupció possible en un sistema de fitxers, perquè és silenciosa i es propaga.
La fila «mitjana» és també instructiva: el fitxer creix de mida i el seu bloc nou conté el que hi hagués abans en aquell lloc del disc. Si aquell bloc va pertànyer a /etc/shadow o a un fitxer d'un altre usuari, acabes de filtrar dades alienes dins del teu fitxer. És un problema de seguretat, no només de consistència, i tornarà a aparèixer en triar el mode del diari.
fsck i per què el seu cost és inacceptable
La solució tradicional era reparar després. En arrencar, si el superbloc estava marcat com a «brut», s'executava fsck (file system check), que recorre tot el sistema de fitxers comprovant invariants:
Fase d'e2fsck |
Què comprova |
|---|---|
| 1. Inodes i blocs | Que cada bloc referenciat estigui marcat ocupat i no pertanyi a dos inodes |
| 2. Estructura de directoris | Que cada entrada apunti a un inode vàlid |
| 3. Connectivitat | Que tot inode en ús sigui accessible des de /; els orfes van a lost+found |
| 4. Comptadors d'enllaços | Que i_nlink coincideixi amb el nombre real d'entrades |
| 5. Mapes de bits i resums | Que els mapes i els comptadors del superbloc quadrin |
Funciona, i la seva capacitat de reparació és real. El problema és el cost, que creix amb la mida del volum:
| Mida | Inodes típics | Durada aproximada de fsck |
|---|---|---|
| 10 GiB | 655.000 | ~10 segons |
200 GiB (/dev/md0) |
13.100.000 | 3-8 minuts |
| 2 TiB | 131.000.000 | 30-90 minuts |
| 20 TiB | 1.310.000.000 | 6-12 hores |
Un servidor que triga vuit hores a arrencar després d'un tall de llum no és acceptable. I hi ha un problema afegit: fsck no pot recuperar la informació perduda, només tornar el sistema a un estat coherent. Davant d'un enllaç creuat el seu remei és duplicar el bloc o descartar-lo: el sistema queda coherent, però un dels dos fitxers està corrupte sense remei. Coherència no és correcció.
Aquell cost és el que va motivar el diari. Amb ell, la recuperació després d'un tall passa de recórrer 13 milions d'inodes a rellegir uns quants megabytes de diari: de minuts o hores a menys d'un segon.
El diari: transacció, confirmació, aplicació i recuperació
La idea ve de les bases de dades i es diu write-ahead logging: abans de modificar res, anota en un registre seqüencial el que faràs. Si el sistema cau, es rellegeix aquell registre i es completa o es descarta el pendent.
A ext4, el diari és una àrea reservada del mateix sistema de fitxers —típicament 128 MiB— que es fa servir com a memòria intermèdia circular, gestionada per un subsistema anomenat JBD2.
Els quatre passos d'una transacció:
graph TB
A["<b>1. INICI</b><br/>S'agrupen les escriptures de metadades<br/>relacionades en UNA transacció"] --> B
B["<b>2. ESCRIPTURA AL DIARI</b><br/>Els blocs modificats s'escriuen<br/>a l'àrea del diari, seqüencialment"] --> C
C["<b>3. CONFIRMACIÓ (commit)</b><br/>S'escriu el bloc de commit<br/>amb la seva suma de verificació<br/>← AQUEST ÉS EL PUNT SENSE RETORN"] --> D
D["<b>4. APLICACIÓ (checkpoint)</b><br/>Els blocs s'escriuen a la seva<br/>posició DEFINITIVA, sense pressa"] --> E
E["<b>5. ALLIBERAMENT</b><br/>L'espai del diari es reutilitza"]
I ara el que passa si es talla la llum a cada punt:
| Moment del tall | Hi ha bloc de commit? | Què fa la recuperació | Resultat |
|---|---|---|---|
| Durant el pas 2 | No | Descartar la transacció incompleta | Com si no hagués passat |
| Just abans del commit | No | Descartar | Com si no hagués passat |
| Just després del commit | Sí | Repetir (replay): copiar del diari al seu lloc | Operació completada |
| Durant el pas 4 | Sí | Repetir; escriure dues vegades el mateix és innocu | Operació completada |
| Després del pas 5 | — | Res a fer | Ja hi era |
La clau de tot és el bloc de commit i la seva suma de verificació:
El bloc de commit és atòmic: s'escriu sencer o no s'escriu. La seva presència i la seva suma correcta signifiquen «aquesta transacció està completa al diari». La seva absència significa «això no va arribar a passar».
Amb això, el sistema no pot quedar mai a mitges. Les tres escriptures del nostre exemple —dada, mapa de bits, inode— s'agrupen en una transacció, i després de la recuperació o hi són les tres o no n'hi ha cap. L'atomicitat que el disc no dona es construeix per programari.
La recuperació a la pràctica:
$ sudo dmesg | grep -i ext4 EXT4-fs (md0): recovery complete EXT4-fs (md0): mounted filesystem with ordered data mode. Opts: noatime
Aquell recovery complete és la línia que apareix després d'un tall, i apareix en menys d'un segon, perquè només cal rellegir el diari. Es pot forçar la lectura del diari amb sudo dumpe2fs /dev/md0 | grep -i journal, que en confirma la mida i l'estat.
Dues precisions necessàries per no sobrevalorar el mecanisme:
- Escriure dues vegades costa. Cada metadada s'escriu al diari i després al seu lloc, cosa que amplifica les escriptures. Per això el diari s'agrupa per lots —moltes operacions en una transacció— i es confirma cada pocs segons (
commit=5per defecte), no a cada operació. - El diari protegeix l'estructura, no necessàriament les teves dades. Quines són exactament les seves garanties depèn del mode, que és l'apartat següent.
Els tres modes d'ext4 i quin tria Meteora
ext4 ofereix tres polítiques sobre què va al diari, i la diferència entre elles és molt real:
| Mode | Al diari hi van... | Ordre garantit | Cost | Risc després d'un tall |
|---|---|---|---|---|
data=journal |
Metadades i dades | Total | Alt: tot s'escriu dues vegades | Cap: dades i metadades consistents |
data=ordered |
Només metadades, però les dades s'escriuen ABANS del commit | Dades abans que metadades | Baix | Es perden dades no confirmades, però mai no apareixen dades alienes |
data=writeback |
Només metadades, sense ordenar | Cap | El més baix | El fitxer pot contenir brossa o dades d'un altre fitxer |
El cas que separa ordered de writeback mereix detall, perquè és exactament la fila «mitjana» de la taula d'estats de l'apartat 7.
Amb writeback, el diari garanteix que l'inode quedarà coherent: dirà que el fitxer fa 17.280.024 bytes i apuntarà al bloc nou. Però no garanteix que les dades d'aquell bloc s'hagin escrit. Després d'un tall pots trobar-te un fitxer la mida del qual ha crescut i el bloc final del qual conté el que hi hagués abans en aquell lloc del disc: restes d'un fitxer esborrat, potser d'un altre usuari. El sistema de fitxers està perfectament coherent i fsck no hi veu res estrany, però has llegit dades que no eren teves. És un problema de seguretat, no només d'integritat.
Amb ordered, ext4 imposa una regla simple: els blocs de dades nous s'escriuen al disc abans de confirmar la transacció que els referencia. Així, si el commit hi és, les dades hi són. Si el commit no hi és, el fitxer conserva la seva mida anterior i el bloc mai no va ser seu. Mai no pot aparèixer contingut aliè dins d'un fitxer. I tot això sense escriure les dades dues vegades: només s'ordenen.
Amb data=journal les dades també passen pel diari, cosa que dona la garantia més forta —el contingut d'un write() confirmat sobreviu íntegre— a costa d'escriure cada byte dues vegades, amb una penalització del 30-50 % en escriptura. Curiosament, pot ser més ràpid en càrregues d'escriptures petites i aleatòries, perquè el diari és seqüencial; però per a escriptura contínua és clarament pitjor.
Es consulta i es canvia així:
sudo dumpe2fs -h /dev/md0 | grep -i "default mount" # el mode per defecte
sudo tune2fs -o journal_data_ordered /dev/md0 # fixar-lo al superbloc
# o per muntatge, a /etc/fstab: UUID=... /var/lib/meteora ext4 noatime,data=ordered 0 2Què tria Meteora: data=ordered. El raonament complet:
writebackqueda descartat per seguretat./var/lib/meteoraés un volum compartit amb l'arxiu històric; que un tall pugui deixar restes de blocs aliens dins d'un fitxer de lectures és inacceptable, i a més arruïnaria el format:meteo-apiinterpretaria aquella brossa com a estructuresLecturaamb temperatures absurdes. Les dades meteorològiques corruptes són pitjors que les dades absents, perquè ningú no se n'adona.data=journalno compensa. La seva garantia addicional és que sobreviuen les dades ja confirmades, però això ja ho controlem des de l'aplicació amb elfdatasynccada 5 segons de 04-04. Pagar un 30-50 % de rendiment i el doble de desgast de l'SSD per duplicar una garantia que ja tenim no té sentit.ordereddona exactament el que necessitem: mai no apareixerà contingut aliè, l'estructura sempre queda coherent, la recuperació triga menys d'un segon, i el cost sobrewritebackés d'un petit percentatge.
I una nota que tanca el cercle amb 04-04: el format de Meteora hi ajuda molt. Com que el fitxer és una seqüència de registres de 24 bytes afegits al final, un tall de llum deixa com a molt un registre incomplet al final, que el lector detecta amb mida % 24 != 0 i descarta. Un format amb estructura global —un índex al principi, o comprimit— no tindria aquella propietat. L'elecció del format de dades és part de l'estratègia d'integritat.
Alternatives al diari: còpia en escriure i log-structured
El diari no és l'única manera de sobreviure a un tall.
Còpia en escriure (copy-on-write, CoW), a Btrfs i ZFS. La idea és radical: mai no se sobreescriu un bloc viu. Modificar un bloc significa escriure'n una còpia nova en un lloc lliure, i després actualitzar el punter que apuntava al vell. Però aquell punter és en un altre bloc, que tampoc no se sobreescriu: també es copia, i així fins a l'arrel de l'arbre. Al final, una sola escriptura atòmica del superbloc arrel fa visible tot el canvi de cop.
| Diari (ext4, XFS) | Còpia en escriure (Btrfs, ZFS) | |
|---|---|---|
| Sobreescriu dades vives | Sí | Mai |
| Escriptures dobles | Sí, de metadades | No |
| Recuperació després d'un tall | Rellegir el diari (< 1 s) | Instantània: l'estat anterior continua allà |
| Instantànies | Externes (LVM, 04-03) | Natives i gairebé de franc |
| Sumes de verificació de dades | No | Sí |
| Fragmentació amb reescriptures aleatòries | Baixa | Alta: cada canvi va a un altre lloc |
| Maduresa a Linux | Molt alta | Alta (Btrfs) / fora del nucli (ZFS) |
La fila de la fragmentació és l'inconvenient real de CoW i la raó que no sigui automàticament la millor opció: una base de dades que reescriu registres a l'atzar fragmenta un sistema CoW molt més que un amb diari. Per això Btrfs ofereix chattr +C per desactivar el CoW en fitxers concrets.
Sistemes estructurats en registre (log-structured), com F2FS. Porten la idea a l'extrem: tot el sistema de fitxers és un registre seqüencial. Cada escriptura, sigui de dades o de metadades, s'afegeix al final; res no es modifica al seu lloc. Les escriptures aleatòries es converteixen en seqüencials, que és exactament el que li convé a la memòria flaix (02-05), on esborrar és per blocs grans i el desgast es reparteix millor així. El preu és que cal un recol·lector d'escombraries que compacti els blocs amb dades obsoletes, i aquell procés competeix amb la càrrega real. És la raó que F2FS domini en mòbils i targetes SD i amb prou feines es faci servir en servidors.
Integritat de dades: sumes de verificació i corrupció silenciosa
Aquí arribem a la distinció que dona nom a l'últim terç de la lliçó, i que molta gent no té clara:
El diari garanteix que l'estructura del sistema de fitxers sigui coherent després d'un tall. No garanteix que les dades que llegeixes siguin les que vas escriure.
Són problemes diferents amb causes diferents. La corrupció silenciosa (silent data corruption, bit rot) és un bit que canvia de valor sense que ningú ho demani, per causes físiques:
| Causa | On passa | Freqüència orientativa |
|---|---|---|
| Degradació del mitjà | Plat magnètic, cel·la NAND | Augmenta amb l'edat |
| Raigs còsmics i radiació | RAM sense ECC, busos | Contínua, baixa |
| Fallades del microprogramari del disc | Controladora | Rara però real |
| Escriptures mal dirigides | El disc escriu a l'LBA equivocat | Rara, molt danyina |
| Escriptures perdudes | El disc confirma i no escriu | Rara, molt danyina |
| Cables o alimentació defectuosos | Bus SATA/SAS | Variable |
Les dues pitjors són les mal dirigides i les perdudes, perquè el disc creu que tot ha anat bé i no reporta cap error. Els estudis clàssics del CERN i de NetApp sobre milions de discos van trobar taxes de l'ordre d'un sector corrupte per cada 10¹⁴-10¹⁵ bits llegits: amb 200 GiB rellegits diàriament, això és un esdeveniment cada uns quants anys per volum. Poc, però no zero, i sobre dades irrecuperables importa.
Què protegeix cada capa:
| Capa | Detecta corrupció de... | Pot corregir-la |
|---|---|---|
| ECC del disc | Errors dins d'un sector | Sí, fins a cert punt |
| ECC de la RAM | Bits capgirats a la memòria | Sí (1 bit), en detecta 2 |
metadata_csum d'ext4 |
Metadades i inodes | No, però avisa |
| Diari d'ext4 | Transaccions incompletes | Sí (repeteix o descarta) |
| RAID 1 | Discrepàncies entre les dues còpies | Detecta, però vegeu a sota |
| Sumes de ZFS/Btrfs | Dades i metadades | Sí, si hi ha redundància |
El punt cec del RAID 1
Aquest és l'apartat que més sorprèn, i afecta directament Meteora, el /var/lib/meteora de la qual és sobre RAID 1 des de 02-05.
RAID 1 manté dues còpies idèntiques. Si un disc falla de manera visible —no respon, retorna error de lectura— el sistema fa servir l'altre i tot funciona: per a això hi és. Però si un disc retorna dades corruptes sense reportar error:
RAID 1 pot detectar que les dues còpies difereixen, però no sap quina és la bona. No té cap informació per decidir-ho, perquè no guarda sumes de verificació de les dades.
Pitjor encara: en funcionament normal, md llegeix d'un sol disc per rendiment —repartint peticions entre tots dos—, així que ni tan sols compara. La discrepància només es descobreix si es fa un scrub explícit:
# Verificació setmanal: llegeix tots dos discos i compara cada bloc
echo check | sudo tee /sys/block/md0/md/sync_action
cat /proc/mdstat # progrés
cat /sys/block/md0/md/mismatch_cnt # discrepàncies trobadesUn mismatch_cnt diferent de zero significa que les còpies difereixen. I aleshores arriba el moment incòmode: el sistema no et pot dir quina és la correcta. repair sincronitza copiant el primer disc sobre el segon, cosa que arregla la discrepància... triant a l'atzar. Si el bo era el segon, acabes de propagar la corrupció a tots dos.
El que aporten ZFS o Btrfs és precisament això: guarden una suma de verificació de cada bloc de dades al node pare de l'arbre. Quan llegeixen un bloc, en comproven la suma; si no quadra, saben que aquell bloc està malament, van a la còpia redundant, en verifiquen la seva suma, i si és correcta la retornen i reparen l'original. És el self-healing, i és qualitativament diferent del que pot fer RAID 1.
Com compensa Meteora aquest punt cec, ja que va triar ext4 a 04-01:
metadata_csumactivat, que protegeix inodes, descriptors de grup, mapes de bits i el diari. L'estructura no es corromprà en silenci.- Scrub setmanal del RAID amb
check, i alerta simismatch_cntno és zero. No repara sol, però avisa, que és el mínim. - CRC32 per registre en el mateix format. L'
ingestorguarda una suma amb cada lectura, i l'agregadorla verifica. És la capa que de debò tanca el forat: encara que el sistema de fitxers i el RAID no hi vegin res, l'aplicació detecta la lectura corrupta i la descarta. - Còpies de seguretat verificades, que són l'última xarxa.
El punt 3 és la lliçó general: quan l'emmagatzematge no et pot donar la garantia que necessites, l'aplicació sí que pot. Un CRC de 4 bytes per registre de 24 encareix un 17 % l'emmagatzematge i converteix una corrupció silenciosa en un error detectat.
Barreres d'escriptura i discos que menteixen
Queda una baula, i és la que pot invalidar tot l'anterior.
Tot el mecanisme del diari descansa en un ordre: els blocs del diari han d'arribar al mitjà abans que el bloc de commit, i aquest abans que els blocs definitius. Però entre el sistema de fitxers i el plat hi ha una memòria cau volàtil al mateix disc: uns quants centenars de megabytes de DRAM on el dispositiu acumula escriptures i les reordena per ser més eficient.
Si el disc reordena i confirma abans d'escriure, el commit pot arribar al mitjà abans que les dades que avala. Un tall de llum en aquell instant deixa una transacció marcada com a completa les dades de la qual no existeixen, i la recuperació l'aplicarà amb confiança. El diari hauria empitjorat les coses.
La solució són les barreres d'escriptura (write barriers), ordres explícites al dispositiu:
| Mecanisme | Què demana al disc |
|---|---|
| FLUSH CACHE | «Escriu al mitjà tot el que tinguis a la memòria cau abans de confirmar-me» |
| FUA (Force Unit Access) | «Aquesta escriptura concreta va al mitjà directament, sense passar per la memòria cau» |
ext4 les fa servir per defecte (barrier=1). El cost és real —una barrera pot costar mil·lisegons— i per això existeix l'opció barrier=0, que les desactiva.
No muntis mai amb
barrier=0llevat que tinguis una controladora RAID amb bateria o supercondensador que garanteixi el buidatge de la seva memòria cau davant d'un tall. Sense això, desactivar les barreres converteix el diari en un adorn.
I el problema final, que no té solució per programari: hi ha discos que menteixen. Alguns dispositius de consum —i molts llapis de memòria i targetes SD barates— ignoren l'ordre de buidatge i confirmen immediatament, perquè així puntuen millor als bancs de proves. Amb un d'aquests, totes les garanties s'evaporen: el sistema de fitxers creu haver imposat un ordre que el maquinari no ha respectat.
sudo hdparm -W /dev/sda # està activa la memòria cau d'escriptura del disc?
sudo hdparm -W0 /dev/sda # desactivar-la (més segur, més lent)Que un disc respecti les barreres no es pot comprovar des del sistema operatiu; requereix un banc de proves amb tall d'alimentació real. La conseqüència pràctica és de compres i no de configuració: per a dades que importen, fes servir discos amb protecció de pèrdua d'alimentació (power loss protection), que porten condensadors per buidar la seva memòria cau al mitjà quan se'n va la llum. És la diferència principal entre un SSD de consum i un de servidor, i explica bona part del seu preu.
Instantànies i còpies de seguretat: una altra capa
Per tancar, una distinció que es confon constantment i que convé deixar clara:
| Mecanisme | Protegeix de... | No protegeix de... |
|---|---|---|
| Diari | Tall de llum, penjada | Fallada de disc, esborrat, corrupció de dades |
| RAID 1 | Fallada completa d'un disc | Esborrat, corrupció silenciosa, incendi, rm -rf |
| Sumes de verificació | Corrupció silenciosa (la detecten) | Fallada de disc, esborrat |
| Instantànies (04-03) | Esborrat accidental, mala actualització | Fallada del volum que les conté, incendi |
| Còpies de seguretat | Gairebé tot, si són fora de la màquina | Res, si mai no s'han restaurat |
Les tres idees que cal endur-se:
El RAID no és una còpia de seguretat. És alta disponibilitat: manté el servei davant de la fallada d'un disc. Un rm -rf es replica als dos discos instantàniament, i un incendi se'ls emporta tots dos.
Una instantània no és una còpia de seguretat. Viu al mateix volum —o al mateix grup de volums— que les dades originals. Si el volum mor, moren totes dues. El seu valor és un altre: donar un punt consistent des del qual fer la còpia sense aturar el servei, que és exactament per al que la vam fer servir a 04-03.
Una còpia de seguretat no verificada no és una còpia de seguretat. Restaurar de debò, en una altra màquina, cada cert temps, és l'única manera de saber que funciona. L'estadística de còpies que van fallar el dia que van caldre és depriment.
L'esquema complet de Meteora, amb cada capa cobrint el que l'anterior no pot:
| Capa | Mecanisme | Què cobreix |
|---|---|---|
| 1 | ext4 data=ordered + metadata_csum |
Talls de llum i penjades |
| 2 | RAID 1 sobre dos NVMe | Fallada d'un disc, sense interrupció |
| 3 | Scrub setmanal + mismatch_cnt |
Detecció de discrepàncies |
| 4 | CRC32 per registre al format | Corrupció silenciosa, a nivell d'aplicació |
| 5 | Instantània LVM nocturna (04-03) | Punt consistent per copiar |
| 6 | Còpia xifrada fora de la màquina | Esborrat, incendi, xifratge per ransomware |
| 7 | Restauració de prova trimestral | Que la capa 6 serveixi d'alguna cosa |
Cap de les set no és redundant, i cap no substitueix una altra.
Errors Habituals i Consells
Creure que el diari protegeix les teves dades. A data=ordered, que és el normal, el diari protegeix les metadades. Un write() no confirmat amb fsync es perd igualment en un tall, encara que el sistema de fitxers quedi impecable.
Muntar amb barrier=0 per guanyar rendiment. Sense una controladora amb bateria, això desactiva la garantia d'ordre i converteix el diari en decoració. El rendiment que guanyes el pagues la primera vegada que se'n va la llum.
Confiar en writeback per ser el més ràpid. El seu risc no és només perdre dades: és que aparegui contingut d'altres fitxers dins dels teus, amb la implicació de seguretat que això té.
Creure que RAID 1 protegeix de la corrupció silenciosa. Detecta discrepàncies només si fas scrub, i tot i així no sap quina còpia és la bona. Si necessites aquella garantia, necessites sumes de verificació de dades: ZFS, Btrfs o la teva pròpia aplicació.
Desfragmentar un SSD. No aporta res mesurable i consumeix cicles d'escriptura. Si tens fragmentació en un ext4, el problema gairebé sempre és que el volum està per sobre del 85 % ple.
Omplir un volum per sobre del 90 %. L'assignador deixa de trobar rangs contigus, la fragmentació es dispara i el rendiment cau en picat. Vigila el 85 % com a llindar d'avís.
Confondre instantània amb còpia de seguretat. Comparteixen destinació amb les dades originals. Si el volum mor, no tens res.
Consell: activa metadata_csum i fes scrub setmanal del RAID. Són dues mesures de cost gairebé nul que converteixen una corrupció invisible en una alerta.
Consell: dissenya el format de dades pensant en el tall. Un fitxer de registres de mida fixa afegits al final es recupera descartant l'últim registre incomplet. Un format amb índex global o comprimit, no. I un CRC per registre tanca el forat que el sistema de fitxers no cobreix.
Exercicis
Exercici 1: calcular metadades i mida màxima
Per a un sistema de fitxers amb blocs de 8 KiB i punters de 4 bytes, calcula: (a) quants punters caben en un bloc; (b) la mida màxima de fitxer amb l'esquema de 12 punters directes, un indirecte simple, un de doble i un de triple, mostrant l'aportació de cada nivell; (c) quants blocs de metadades i quants accessos extra necessita un fitxer de 17.280.000 bytes amb aquell esquema; (d) el mateix amb extents d'ext4, suposant que el fitxer és en un sol tram contigu. Comenta què canvia respecte al càlcul amb blocs de 4 KiB de la lliçó.
Exercici 2: analitzar la fragmentació real del teu sistema
A la teva màquina, fes servir filefrag per analitzar almenys deu fitxers de mides molt diferents —des d'uns pocs KB fins a diversos GB si en tens—, i construeix una taula amb mida, nombre d'extents i extents per GiB. Després executa sudo e2fsck -fn sobre un sistema de fitxers desmuntat (o interpreta la línia non-contiguous d'un df/dumpe2fs) i valora si el teu volum està fragmentat. Explica quina relació observes entre mida de fitxer, ocupació del volum i fragmentació, i decideix raonadament si desfragmentaries alguna cosa.
Exercici 3: triar el mode del diari per a tres càrregues
Per a cadascuna d'aquestes tres càrregues, tria entre data=journal, data=ordered i data=writeback, i justifica la decisió analitzant què es perd i què s'arrisca en un tall de llum: (A) el volum /var/lib/meteora de les lectures; (B) un volum de memòria cau d'imatges regenerables, on el rendiment d'escriptura és l'única cosa que importa; (C) un volum d'una base de dades financera amb transaccions. Per a cadascun, indica a més quines altres mesures de les vistes a la lliçó hi afegiries i per què.
Solucions
Solució 1
(a) Punters per bloc = 8.192 / 4 = 2.048.
(b) Mida màxima:
| Nivell | Blocs adreçats | Espai |
|---|---|---|
| 12 directes | 12 | 12 × 8 KiB = 96 KiB |
| Indirecte simple | 2.048 | 16 MiB |
| Indirecte doble | 2.048² = 4.194.304 | 32 GiB |
| Indirecte triple | 2.048³ = 8.589.934.592 | 64 TiB |
| Total ≈ 64,03 TiB |
Duplicar la mida de bloc multiplica el màxim per 16, no per 2: cada nivell d'indirecció aporta un factor 2 per la mida del bloc i un altre factor 2 per cabre-hi el doble de punters, i amb tres nivells això és 2⁴ = 16. És un exemple bonic de creixement no lineal.
(c) 17.280.000 / 8.192 = 2.109,375 → 2.110 blocs. Els 12 primers són directes; en queden 2.098, que caben sencers a l'indirecte simple (2.048)... no del tot: 2.098 > 2.048, així que 2.048 van a l'indirecte simple i 50 al doble.
Blocs de metadades: 1 (indirecte simple) + 1 (arrel del doble) + 1 (un bloc de segon nivell per als 50) = 3 blocs = 24 KiB. Accessos extra: 1 per als blocs de l'indirecte simple, 2 per als 50 del doble.
Amb blocs de 4 KiB eren 6 blocs de metadades i fins a 3 accessos extra: el bloc més gran redueix a la meitat les metadades i estalvia un nivell d'indirecció, a costa de més fragmentació interna (04-01). Recorda que a Linux això és teòric, perquè el bloc no pot superar la mida de pàgina.
(d) Amb extents i un sol tram contigu: 1 extent de 12 bytes dins de l'inode, 0 blocs de metadades i 0 accessos extra. Tant se val que el bloc sigui de 4 o de 8 KiB: la contigüitat és el que elimina el problema, no la mida del bloc.
Solució 2
for f in $(find ~ /var/log /usr/lib -maxdepth 3 -type f -size +1M 2>/dev/null | head -20); do
mida=$(stat -c %s "$f")
ext=$(filefrag "$f" 2>/dev/null | grep -o '[0-9]* extent' | cut -d' ' -f1)
[ -n "$ext" ] && printf "%12d %6s %s\n" "$mida" "$ext" "$f"
done | sort -rnResultats típics en un ext4 sa al 60 % d'ocupació:
| Mida | Extents | Extents per GiB | Comentari |
|---|---|---|---|
| 4,2 GB | 38 | 9 | Excel·lent per a la seva mida |
| 1,1 GB | 12 | 11 | Excel·lent |
| 340 MB | 4 | 12 | Bé |
| 17 MB | 1 | 59 | Òptim |
| 2 MB | 1 | — | Òptim |
I en un volum al 94 % d'ocupació, el mateix fitxer de 4,2 GB pot sortir amb 900 extents.
Relacions observades. Els fitxers petits (< 128 MiB) gairebé sempre surten en un sol extent, perquè un extent d'ext4 arriba a 128 MiB i l'assignació diferida veu el fitxer complet abans d'assignar. Els grans en tenen uns quants, però pocs: la fragmentació creix molt més a poc a poc que la mida. I la variable determinant no és la mida sinó l'ocupació del volum: per sobre del 90 % l'assignador deixa de trobar forats grans i la fragmentació es multiplica.
Desfragmentaria? Gairebé amb seguretat no. En un SSD, mai: no hi ha guany mesurable i sí desgast. En un HDD, només un fitxer concret molt fragmentat (milers d'extents) que es llegeixi seqüencialment sovint, amb e4defrag sobre aquell fitxer. I l'acció realment útil seria alliberar espai fins a baixar del 85 %, que ataca la causa en lloc del símptoma.
Solució 3
(A) /var/lib/meteora → data=ordered. És la decisió de la lliçó. writeback queda descartat perquè un tall podria deixar blocs amb contingut aliè dins d'un fitxer de lectures, i meteo-api els interpretaria com a estructures Lectura vàlides amb valors absurds: dades corruptes indetectables són pitjors que dades absents. data=journal duplicaria les escriptures amb un 30-50 % de penalització per donar una garantia que ja es cobreix des de l'aplicació amb fdatasync cada 5 segons. Mesures addicionals: metadata_csum, scrub setmanal del RAID, CRC32 per registre, i el format de registres de mida fixa que permet descartar l'últim incomplet.
(B) Memòria cau d'imatges regenerables → data=writeback. Aquí sí. El raonament de seguretat que descartava writeback a (A) s'aplica només perquè a (A) el contingut importa; si un fitxer de memòria cau queda amb brossa, es detecta en fer-lo servir i es regenera, que és la definició de memòria cau. Es guanya el màxim rendiment d'escriptura. Mesures addicionals, coherents amb la naturalesa de la dada: no fer còpia de seguretat d'aquest volum; muntar-lo noatime,nosuid,nodev,noexec (04-03); considerar directament tmpfs si cap a la RAM; i validar cada entrada en llegir-la —amb una suma o un identificador de versió—, descartant i regenerant la que no quadri. Una opció encara més agressiva seria mkfs.ext4 -O ^has_journal, sense diari: després d'un tall caldria executar fsck o simplement reformatar, cosa que en una memòria cau és perfectament acceptable.
(C) Base de dades financera → data=ordered, no data=journal. Aquest és el cas que més enganya. La intuïció diu «el més segur possible, data=journal», i és la resposta equivocada per dos motius. Primer, una base de dades seriosa ja té el seu propi diari —el WAL de PostgreSQL, el redo log d'Oracle— i sincronitza amb fsync a cada confirmació de transacció: el diari de dades del sistema de fitxers duplicaria exactament la mateixa feina, escrivint cada byte quatre vegades en total. Segon, aquella duplicació costa un 30-50 % de rendiment a la part del sistema més sensible a la latència. data=ordered dona la garantia estructural necessària i deixa la durabilitat transaccional on ha d'estar: a la capa que entén què és una transacció.
Mesures addicionals per a (C), que són on de debò es juga l'assumpte: barreres activades i discos amb protecció de pèrdua d'alimentació, perquè un disc que menteix invalida el fsync en què s'apuntala el WAL; RAM amb ECC, ja que un bit capgirat a la memòria corromp la dada abans d'escriure-la i cap suma del sistema de fitxers no ho detecta; RAID amb scrub; sumes de verificació a nivell de pàgina, que PostgreSQL ofereix amb data_checksums; i còpies amb restauració verificada, a més d'arxivament continu del WAL per poder recuperar a un instant concret.
La lliçó transversal dels tres casos: la garantia es posa a la capa que té la informació per donar-la, i duplicar-la en diverses capes costa rendiment sense afegir seguretat.
Conclusió
Les quatre estratègies d'assignació responen a la mateixa pregunta amb compromisos diferents. La contigua és òptima en lectura i en metadades —vuit bytes descriuen qualsevol fitxer— però mor per fragmentació externa i per no poder créixer, així que només sobreviu en mitjans de només lectura. L'enllaçada i la seva variant amb taula, FAT, eliminen la fragmentació externa a canvi d'un accés aleatori O(n) i d'una taula que creix amb el volum: 1 GiB de FAT per a 1 TB amb clusters de 4 KiB, més un punt únic de fallada i cap diari. La indexada d'UNIX reuneix els punters a l'inode i resol el problema de la mida amb indirecció esglaonada —12 directes, simple, doble i triple—, que amb blocs de 4 KiB arriba a 4,004 TiB i fa que el cost creixi amb la mida: 0 accessos extra fins a 48 KiB, 3 per als fitxers més grans. I els extents descriuen rangs contigus amb 12 bytes: els 4.219 blocs de 2026-08-31.dat passen de 16.876 bytes de punters i 6 blocs de metadades a un sol extent, verificat amb filefrag.
Que aquell fitxer acabi contigu tot i escriure's 24 bytes cada 125 ms durant un dia es deu a tres mecanismes: assignació diferida, que no reserva res fins a l'abocament i per tant decideix sabent quant cal; assignació multibloc, que demana el rang sencer de cop a un mapa de bits bo buscant zeros consecutius; i grups de blocs amb preassignació, que reserven marge darrere d'un fitxer que creix. El resultat és un 0,4 % de fitxers no contigus, i explica per què desfragmentar amb prou feines té sentit: no cal en un ext4 sa, és irrellevant en SSD i a més el desgasta. La fragmentació és un símptoma de volum ple: mantén l'ocupació per sota del 85 %.
La segona meitat ha estat sobre supervivència. Afegir un bloc són tres escriptures —dada, mapa de bits, inode— que el maquinari no pot fer atòmiques, i de les seves set combinacions dues són greus: quan l'inode apunta a un bloc marcat com a lliure, l'assignador el donarà a un altre fitxer i apareixerà un enllaç creuat, la pitjor corrupció possible. fsck sap reparar, però 8 hores en un volum de 20 TiB és inacceptable, i a més només retorna la coherència, no la correcció. El diari resol totes dues coses: transacció, escriptura al diari, bloc de commit atòmic amb suma de verificació —el punt sense retorn— i aplicació diferida; després d'un tall, la recuperació repeteix el confirmat i descarta la resta en menys d'un segon.
Dels tres modes, writeback deixa que aparegui contingut aliè dins dels teus fitxers —un problema de seguretat, no només d'integritat—, data=journal escriu tot dues vegades per un 30-50 % de cost, i data=ordered garanteix que les dades arriben al disc abans del commit que les referencia, sense duplicar res. Meteora tria ordered, i el seu format de registres de 24 bytes afegits al final completa l'estratègia: un tall deixa com a molt un registre incomplet que el lector descarta amb mida % 24. L'elecció del format de dades és part de l'estratègia d'integritat. Les alternatives al diari són la còpia en escriure de Btrfs i ZFS —sense sobreescriptures, amb instantànies natives i sumes de dades, a costa de fragmentar amb reescriptures aleatòries— i els sistemes estructurats en registre com F2FS, que converteixen tota escriptura en seqüencial a canvi d'un recol·lector d'escombraries.
I la distinció final, la més important de la lliçó: el diari garanteix la coherència de l'estructura, no la integritat de les dades. La corrupció silenciosa existeix, i ext4 no la veu. RAID 1 pot detectar que les dues còpies difereixen però no sap quina és la bona —i ni tan sols compara llevat que facis scrub—, mentre que ZFS i Btrfs sí, perquè guarden una suma per bloc de dades i es poden reparar sols. Meteora tanca aquell forat amb metadata_csum, scrub setmanal i, sobretot, un CRC32 per registre en el seu propi format: quan l'emmagatzematge no et pot donar la garantia que necessites, l'aplicació sí que pot. Tot això descansa en les barreres d'escriptura, que imposen l'ordre que el diari necessita, i que un disc que ignori el buidatge de la seva memòria cau converteix en ficció: per això els SSD de servidor porten protecció de pèrdua d'alimentació. I les set capes de Meteora —diari, RAID, scrub, CRC, instantània, còpia externa i restauració de prova— cobreixen cadascuna el que l'anterior no pot: el RAID no és una còpia de seguretat, la instantània tampoc, i una còpia sense restaurar no és res.
Ens queda l'última pregunta del mòdul, i és d'una altra naturalesa. Hem protegit /var/lib/meteora/lectures/2026-08-31.dat del tall de llum, de la fallada d'un disc i fins i tot d'un bit que es capgira al plat. Però portem cinc lliçons veient -rw-r----- a cada ls -l i Uid: (990/meteora) a cada stat, i no hem explicat què signifiquen. Qui pot llegir aquell fitxer, i qui el pot esborrar? Per què es pot esborrar un fitxer que no es pot llegir? Què comprova exactament el nucli, i en quin moment? I com aconsegueix passwd modificar /etc/shadow, que només root pot escriure, quan l'executa un usuari normal?
És el que veurem a Seguretat i Permisos de Fitxers.
Fonaments de Sistemes Operatius
Mòdul 1: Introducció als Sistemes Operatius
- Conceptes Bàsics de Sistemes Operatius
- Història i Evolució dels Sistemes Operatius
- Tipus de Sistemes Operatius
- Funcions Principals d'un Sistema Operatiu
- Arquitectura del Nucli: Monolític, Microkernel i Híbrid
- Mode Usuari, Mode Nucli i Crides al Sistema
Mòdul 2: Gestió de Recursos
- Gestió de Processos
- Planificació de la CPU
- Gestió de Memòria
- Memòria Virtual i Paginació
- Gestió d'Emmagatzematge
- Gestió de Dispositius
- Controladors, Interrupcions i Operacions d'E/S
Mòdul 3: Concurrència
- Conceptes de Concurrència
- Fils i Processos
- Comunicació entre Processos (IPC)
- Sincronització i Exclusió Mútua
- Problemes Clàssics de Concurrència
- Interbloquejos: Prevenció, Detecció i Recuperació
Mòdul 4: Estructures de Fitxers
- Sistemes de Fitxers
- Estructures de Directoris
- Particions, Muntatge i Sistema de Fitxers Virtual
- Gestió de Fitxers
- Assignació d'Espai, Journaling i Integritat
- Seguretat i Permisos de Fitxers
Mòdul 5: Protecció i Seguretat del Sistema
- Principis de Protecció i Control d'Accés
- Usuaris, Autenticació i Escalada de Privilegis
- Amenaces Habituals i Enfortiment del Sistema
- Auditoria, Registres i Resposta a Incidents
Mòdul 6: Virtualització i Contenidors
- Virtualització: Hipervisors i Màquines Virtuals
- Contenidors: Namespaces i cgroups
- El Sistema Operatiu al Núvol
- Sistemes Operatius Mòbils i de Temps Real
