Certaines pannes ne font pas de bruit. Le service reste opérationnel, les graphiques ont l’air normaux et tout le monde félicite l’autoscaler. Puis un court instant de coupure électrique survient, ou un nœud redémarre, et soudain votre base de données est « correctement » privée de ce qui avait été écrit hier après-midi.
Ceci est le mode de défaillance du stockage Linux que personne ne veut expliquer au postmortem : votre application a fait exactement ce qu’elle devait faire, mais vos options de montage ont discrètement modifié ce que « écriture terminée » signifie. Les données ne sont pas corrompues de manière spectaculaire. Vos attentes, elles, le sont.
L’option de montage qui corrompt les attentes : async (et ses compagnes)
Si vous me forcez à choisir une option de montage qui transforme régulièrement la production en théâtre d’improvisation, c’est async.
async modifie le moment où le système rapporte le succès. Il permet au noyau (ou au serveur, dans le cas NFS) d’accuser réception des écritures avant qu’elles ne soient engagées sur un stockage stable. Cela peut convenir pour de l’espace temporaire, des caches, des artefacts de build ou des choses régénérables. Ce n’est pas acceptable pour votre base de données, votre file d’attente, votre service d’identité, votre « source unique de vérité », ni pour tout ce pour quoi vous pourriez vous auto-convoquer devant des auditeurs plus tard.
Sur les systèmes de fichiers locaux, on ne monte pas souvent explicitement avec async parce que c’est généralement le comportement par défaut du cache de pages : les écritures sont tamponnées et flushées plus tard. La partie dangereuse, c’est quand les gens combinent des hypothèses d’E/S tamponnée avec des options qui affaiblissent l’ordonnancement et la durabilité, puis supposent que fsync() les protège. Parfois oui. Parfois il vous protège « artistiquement ».
L’attente qui est corrompue
La plupart des ingénieurs — raisonnables et employés — supposent qu’une de ces affirmations est vraie :
- « Si mon appli reçoit un code de retour réussi de
write(), les données sont en sécurité. » - « Si mon appli appelle
fsync(), les données sont définitivement en sécurité. » - « Si le système de fichiers journalise, il ne peut pas perdre les données engagées. »
Sur Linux, la seule qui soit parfois défendable est la deuxième, et encore elle dépend des options de montage, de la sémantique du système de fichiers, du comportement du cache d’écriture du périphérique, du firmware du contrôleur, et du fait que votre « disque » soit réellement un service réseau déguisé en bloc.
Le petit ensemble de réglages qui causent le plus de regrets
Voici les suspects habituels :
- NFS
asynccôté serveur (et parfois choix côté client) accusant réception avant commit. - ext4
data=writebackaffaiblissant l’ordonnancement entre le journal des métadonnées et les données des fichiers. barrier=0/nobarriersupprimant le comportement flush/FUA qui impose l’ordre via les caches volatiles.- Désactiver les barrières via les politiques du périphérique/contrôleur (« c’est plus rapide ») tout en faisant confiance à
fsync()(« c’est sûr »). commit=augmenter le délai maximal pendant lequel les métadonnées peuvent rester en RAM avant d’être engagées dans le journal (fenêtre de douleur plus grande en cas de perte de courant).
Individuellement, chacun peut être justifié dans des contextes spécifiques. Ensemble, ils forment un projet de groupe où la note est « irrécupérable ».
Blague 1 : Le système de stockage le plus « rapide » est celui qui n’écrit jamais rien. Il est aussi très durable, parce qu’il n’y a rien à perdre.
Durabilité : ce que vous attendez vs ce que le noyau garantit réellement
Les E/S Linux ont des couches, et chaque couche a ses opinions.
À un niveau élevé : les applications écrivent dans le cache de pages ; le noyau planifie le writeback ; le système de fichiers met à jour les métadonnées et peut-être les journalise ; la couche bloc met en file les requêtes ; le périphérique peut mentir avec un cache volatile ; puis la physique intervient. Ou pas. Les mauvaises surprises se trouvent presque toujours dans le « peut-être ».
Trois affirmations qui sonnent similaires mais ne le sont pas
- Les données sont visibles : un autre processus peut les lire (depuis le cache), même si elles ne sont pas sur disque.
- Les données sont persistantes : elles survivront à un crash/perte d’alimentation.
- Le système de fichiers est cohérent : après un crash, les métadonnées sont récupérables et les structures sont saines.
La journalisation concerne d’abord la cohérence des métadonnées. Certains modes ajoutent des garanties plus fortes sur les données fichiers. Mais « cohérent » ne signifie pas « contient les écritures réussies les plus récentes ». Cela signifie « montable sans passer le week-end dans fsck ».
Où se place fsync() — et où il ne suffit pas
fsync(fd) demande au noyau de vider les pages sales et les métadonnées associées à ce fichier vers un stockage stable. Voilà le contrat. Le problème est : que signifie « stockage stable » quand :
- un disque a un cache d’écriture volatile et ignore les flush,
- un contrôleur RAID réordonne les écritures et ment sur l’état de la batterie,
- un hyperviseur traduit les flush en « best effort »,
- un système en réseau accuse réception avant commit.
De plus, il faut l’appeler correctement. Beaucoup de systèmes exigent un fsync() sur le répertoire après la création/renommage de fichiers pour garantir que l’entrée de répertoire est durable. Le fichier peut être sain alors que le nom qui y pointe ne l’est pas. C’est une façon très « Linux » de perdre des choses : les données existent, mais vous ne pouvez pas les retrouver.
Une citation à garder dans votre carnet d’astreinte
« L’espoir n’est pas une stratégie. » — Gen. Gordon R. Sullivan
Remplacez « espoir » par « options de montage par défaut », et vous aurez fait la moitié du chemin vers une meilleure posture de stockage.
Modes de journalisation qui changent votre réalité : ext4 data=ordered, writeback, journal
ext4 est toujours partout parce que c’est ennuyeux, rapide et prévisible — jusqu’à ce que vous changiez les réglages qui le rendent ennuyeux.
Ce que ces modes font réellement
data=ordered(défaut sur beaucoup de distributions) : les métadonnées sont journalisées. Les données de fichier ne le sont pas, mais ext4 tente de s’assurer que les blocs de données du fichier sont écrits sur disque avant que les métadonnées qui les pointent ne soient engagées. Après un crash, vous ne devriez pas voir de vieilles ordures dans des blocs de fichier nouvellement écrits (dans la plupart des cas). Vous pouvez toujours perdre des écritures récentes, mais de façon plus raisonnable.data=writeback: les métadonnées sont journalisées, mais ext4 n’applique pas l’ordonnancement entre les écritures de données et les commits de métadonnées. Après un crash, les métadonnées peuvent pointer vers des blocs dont le contenu est ancien. C’est le mode « le système de fichiers est cohérent mais vos fichiers sont surprenants ».data=journal: données et métadonnées sont journalisées. C’est plus solide pour la cohérence après un crash, généralement plus lent, et pas gratuit. Cela augmente aussi l’amplification d’écriture : vous écrivez d’abord les données dans le journal puis à leur emplacement final.
Pourquoi data=writeback corrompt les attentes
Parce qu’il passe souvent les tests informels. Votre appli écrit, vos tests passent, votre benchmark semble excellent, votre responsable hoche la tête. Puis vous subissez un arrêt non propre et découvrez que la dernière transaction « réussie » a écrit des métadonnées assez durables pour survivre au reboot, mais que les blocs de données en dessous correspondent à une version antérieure.
Cela est particulièrement brutal pour les charges de travail à écriture en append ou de type log où les utilisateurs supposent une croissance monotone. Avec writeback, après un crash vous pouvez obtenir des « trous » de contenu plus ancien à l’intérieur d’un fichier qui semble plus récent.
Faut-il donc ne jamais utiliser data=writeback ?
Pour des serveurs à usage général : oui, essentiellement jamais. Si vous avez une charge très ciblée qui ne relit jamais des données récemment écrites après un crash (scratch, caches), très bien. Pour tout ce qui nécessite des garanties de durabilité, vous achetez des performances avec un type de dette qui ne se refinance pas.
Barrières, cache d’écriture, et pourquoi le « stockage stable » est politique
Les barrières (et leurs équivalents modernes : flushs et FUA) sont les garde-fous qui disent aux périphériques « cet ordre importe ». Sans elles, la pile de stockage devient une boîte à suggestions.
Caches d’écriture : le grand accélérateur et le grand menteur
La plupart des disques (et de nombreux périphériques bloc virtuels) utilisent un cache en écriture. Les écritures se terminent rapidement parce qu’elles atterrissent d’abord en mémoire volatile. Si l’alimentation est perdue, ces écritures s’évaporent. Si votre périphérique accuse réception des écritures depuis le cache volatile comme « terminé » et ignore les requêtes de flush, l’OS ne peut pas garantir la durabilité, peu importe à quel point il appelle sincèrement fsync().
Ce que signifie vraiment barrier=0 / nobarrier
Désactiver les barrières peut améliorer le débit et la latence dans certains environnements, en particulier sur d’anciens noyaux et certaines piles de contrôleurs. Cela peut aussi créer le paradoxe post-crash classique : le journal rejoue, le système de fichiers monte proprement, et votre base de données découvre que hier a disparu alors que les logs affirment que c’était commité.
Les barrières ne sont pas une « sécurité supplémentaire ». Elles sont la façon dont le système de fichiers impose l’ordre qu’il supposait quand il vous a promis la cohérence. Les retirer, c’est comme enlever les écrous de roue parce que la roue tourne plus vite.
Faits intéressants et contexte historique (le stockage a des reçus)
- ext3 a rendu la journalisation courante sur Linux au début des années 2000 en prolongeant ext2, principalement pour réduire les longs temps de fsck après crash.
- La allocation différée d’ext4 a amélioré les performances mais aussi changé le comportement en cas de crash ; il est devenu plus important que les applis fassent correctement
fsync(). - Les barrières étaient autrefois optionnelles et coûteuses sur certaines piles ; les admins les désactivaient parfois après avoir lu des guides d’optimisation écrits pour un matériel différent.
- Certains premiers SSD grand public étaient célèbres pour ignorer les commandes de flush, rendant le comportement « sync » plus aspirational que réel.
- XFS a privilégié scalabilité et parallélisme et historiquement a recommandé « utiliser du matériel adapté avec protection perte de puissance » plutôt que de prétendre pouvoir corriger des périphériques qui mentent.
- Le débat NFS
syncvsasyncest ancien ; les admins échangent durabilité contre performance depuis avant que « cloud » soit un intitulé de poste. - POSIX autorise les écritures tamponnées ; un
write()réussi n’implique pas la persistance, ce qui surprend les gens exactement une fois par carrière. - Les bases de données ont ajouté des options de durabilité (comme désactiver fsync) parce que les utilisateurs exigeaient la vitesse — puis accusaient la base de données des conséquences.
Pièges spécifiques aux systèmes de fichiers (ext4, XFS, btrfs)
ext4 : défauts sûrs, réglages dangereux
ext4 avec des paramètres par défaut raisonnables (data=ordered, barrières activées) est généralement une bonne base pour des disques locaux. La plupart des histoires d’horreur commencent par « nous avons modifié les options de montage pour atteindre un objectif de latence ». Le second acte commence par « perte d’alimentation ».
Faites aussi attention à :
commit=: augmente l’intervalle entre les commits du journal. Des valeurs plus grandes augmentent la fenêtre de perte de métadonnées après un crash. Idéal pour les benchmarks de débit ; moins idéal pour les timelines d’incident.errors=remount-ro: défaut courant ; bon pour la sécurité, mais peut transformer un problème disque latent en un système de fichiers racine soudainement en lecture seule. C’est une fonctionnalité, pas une trahison.
XFS : robuste, mais vous devez toujours respecter la physique
XFS est excellent pour les charges parallèles et les grands systèmes de fichiers. Il utilise la journalisation pour les métadonnées ; les données ne sont pas journalisées. Il s’appuie sur l’ordonnancement des écritures et le comportement des flushs pour maintenir la cohérence.
Le « corruption d’attente » courant avec XFS concerne moins les flags de montage que l’hypothèse que le périphérique sous-jacent honore les flushs. Si vous exécutez XFS sur une pile qui ment sur les flushs du cache, vous pouvez obtenir des incohérences post-crash qui ressemblent à « XFS a mangé mes données » alors que le vrai coupable est « le contrôleur a accusé une écriture qu’il ne pouvait pas conserver ».
btrfs : sommes de contrôle, copy-on-write, et compromis différents
btrfs apporte des sommes de contrôle de bout en bout et une sémantique copy-on-write, ce qui change la façon dont la corruption se manifeste. Il peut détecter la corruption silencieuse, ce qui est excellent. Il peut aussi amplifier les écritures et se comporter différemment selon certaines charges de travail. Les échecs d’attente ici concernent généralement le tuning de performance (compression, CoW sur des bases de données) plutôt que la sémantique brute de durabilité. Toujours : les options de montage comptent.
Stockage en réseau : NFS et le mensonge séduisant de async
Si le stockage local est compliqué, le stockage en réseau est compliqué avec en plus la latence.
NFS serveur async : accusés rapides, regrets lents
Sur NFS, l’option de montage la plus dangereuse n’est souvent pas une option client — c’est l’option d’export côté serveur async. Avec async, le serveur peut répondre « OK » à une écriture client avant de l’engager sur un stockage stable. Si le serveur NFS plante, le client croit que l’écriture était durable parce qu’il a reçu une accusé de réception. La réalité n’est pas d’accord.
Parfois, les équipes justifient async par « mais le serveur a un onduleur ». Cool. Un onduleur est un plan d’alimentation, pas une preuve de correction. Kernel panic, bug firmware, défaillance d’alimentation redondante, erreur humaine : ils ne demandent pas la permission à votre UPS.
Blague 2 : « Nous l’avons monté async pour la performance » est l’équivalent stockage de « j’ai enlevé le détecteur de fumée parce qu’il faisait du bruit ».
NFS sync n’est pas gratuit, mais il est honnête
sync force le serveur à engager les écritures sur un stockage stable avant de répondre. C’est plus lent, oui. Mais cela aligne les accusés de réception avec la durabilité. C’est tout l’objectif d’un système de stockage : stocker les choses.
Trois mini-histoires d’entreprise depuis les tranchées du stockage
Mini-histoire 1 : L’incident causé par une mauvaise hypothèse
Une entreprise de taille moyenne gère un dépôt d’artefacts interne : binaires, logs de build et manifests de déploiement. Rien de « critique », jusqu’à ce que ça le devienne. L’équipe l’a migré vers un nouveau cluster de VM et a attaché un périphérique bloc réseau rapide. Le plan de migration incluait un ajustement rapide du système de fichiers : data=writeback sur ext4 parce qu’un benchmark montrait une amélioration notable lors d’uploads parallèles.
L’hypothèse était simple et très humaine : « Le dépôt est en append-only, donc la cohérence n’a pas beaucoup d’importance. » Leurs pipelines CI ont écrit des artefacts, reçu des HTTP 200 et continué. Le service a semblé stable pendant des mois.
Puis un hyperviseur a planté pendant une fenêtre de mise à jour. La VM a redémarré proprement. ext4 a rejoué le journal. Le système de fichiers a monté sans se plaindre. Le service d’artefacts a démarré. Tout le monde a soufflé.
Deux jours plus tard, une équipe a tenté de redéployer une version plus ancienne. Le manifest était présent, mais un binaire référencé était subtilement erroné : bon nom, bonne taille, contenu incorrect. Pas des ordures aléatoires — un chunk d’une build plus ancienne. Le débogage fut pénible parce que ça ressemblait à un cache mauvais ou une release foirée. Ils ont finalement retracé le problème à un fichier qui avait été écrasé lors d’une mise à jour de métadonnées sans ordonnancement appliqué entre données et métadonnées. Leur hypothèse « append-only » était fausse : le service faisait de la compaction périodique et des réécritures de métadonnées.
La correction n’a pas été héroïque. Ils ont remonté avec data=ordered, forcé un comportement correct de fsync dans le chemin applicatif, et ajouté une vérification d’intégrité post-crash pour les artefacts critiques. La leçon est restée : la sémantique du stockage n’est pas négociable simplement parce que votre service n’est pas « orienté client ».
Mini-histoire 2 : L’optimisation qui s’est retournée contre eux
Une plateforme d’analytics avait un chemin d’ingestion chaud écrivant sur XFS local sur NVMe. Pendant les heures de pointe, la latence devenait volatile. Quelqu’un a fait le mouvement classique : ajuster les options de montage et le scheduler d’E/S en production parce que les graphes hurlaient. Ils ont désactivé les barrières (le réglage exact variait selon le noyau et le système de fichiers) et ajusté le comportement de commit pour espacer les commits de métadonnées.
Ça a marché. La latence s’est améliorée. Les dashboards se sont calmés. Le changement a été codifié dans une image, parce que le succès est contagieux.
Des semaines plus tard, une armoire a perdu l’alimentation. Les hôtes sont revenus. La plupart des services ont récupéré. Un sous-ensemble de nœuds est remonté avec des messages de « journal replay » puis a servi silencieusement des données d’ingestion partielles. La plateforme n’a pas planté ; elle a dégradé d’une façon pire qu’un crash : elle a produit des analytics incomplets qui avaient l’air plausibles.
Le postmortem a été inconfortable parce que personne n’avait « cassé » quoi que ce soit. L’optimisation avait fait ce qu’on attendait : rendre le système plus rapide en affaiblissant les hypothèses d’ordonnancement. Le retour de bâton fut que leur pipeline de données comptait sur un comportement semblable à fsync d’un composant qui ne fsyncait pas aux bons endroits. Le tweak de montage a élargi la fenêtre où les flushs manquants importaient.
Ils ont rétabli les options de montage, ajouté des frontières de durabilité explicites dans les composants d’ingestion, et — ceci est important — introduit un test de chaos simulant une perte d’alimentation brutale pour un cluster de staging. Le tuning de performance n’a pas arrêté. Il a juste cessé d’être un saut de foi.
Mini-histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Un service adjacent aux paiements (ne traitant pas les cartes, mais suffisamment proche pour être audité) avait une politique terne : tous les volumes de base de données devaient être montés avec des paramètres sûrs, barrières activées, et toute déviation nécessitait une évaluation de risque écrite et un plan de rollback. Les ingénieurs se plaignaient car cela ralentissait les « simples » expériences de performance.
Ils avaient aussi une autre habitude : tests trimestriels de « tirer la prise » sur une réplique non production avec des paramètres de stockage similaires à la production. Pas glamour. Juste brutal. Ils exécutaient une charge représentative, provoquaient un arrêt non propre, redémarraient et vérifiaient que la base de données récupérait sans transactions reconnues manquantes.
Un trimestre, le test a échoué. La base est revenue, mais un petit ensemble de transactions récemment commises avait disparu. C’est le genre de bug qui se transforme en événement réglementaire si livré.
Ils ont tracé le problème jusqu’à une mise à jour firmware du stockage qui avait modifié le comportement de flush sous certaines profondeurs de file d’attente. Rien dans les logs OS n’alertait. Le système de fichiers semblait propre. Seul le test de durabilité l’a attrapé. Ils ont bloqué le déploiement du firmware, basculé vers des périphériques avec protection perte de puissance pour ce niveau, et gardé la politique ennuyeuse intacte.
Quand le vrai datacenter a ensuite connu un incident d’alimentation, leur service n’a pas eu besoin d’une salle de crise. Pas parce qu’ils étaient plus malins. Parce qu’ils étaient plus obstinés sur la sémantique.
Mode d’emploi pour un diagnostic rapide
Quand la durabilité ou la corruption est suspectée, il faut rapidité et discipline de triage. Voici la checklist « ne vous perdez pas dans les détails » que j’utilise.
Première étape : confirmez ce que vous avez réellement monté et exporté
- Vérifiez les options de montage actuelles (
findmnt,/proc/mounts). - Si NFS est impliqué, vérifiez les options d’export côté serveur (
exportfs -v) et les options de montage client (nfsstat -m).
Deuxième étape : validez la chaîne de durabilité (flushs et cache d’écriture)
- Le périphérique bloc a-t-il le cache d’écriture activé ? Est-il protégé ?
- Les flushs sont-ils supportés et respectés (autant que vous pouvez l’inférer) ?
- Les barrières/flushs sont-ils désactivés au niveau du système de fichiers ou du layer device-mapper ?
Troisième étape : identifiez si vous voyez des problèmes de cohérence des métadonnées ou d’ordonnancement des données
- Problèmes de métadonnées : échecs de montage, boucles de replay du journal, inodes orphelins, erreurs du système de fichiers.
- Problèmes d’ordonnancement : le système de fichiers monte proprement, mais les invariants applicatifs sont violés (transactions récentes manquantes, mauvais contenus de fichiers sous des noms corrects).
Quatrième étape : reproduisez avec un test de crash contrôlé (si possible)
- Exécutez une petite charge write+fsync.
- Forcez un arrêt non propre.
- Vérifiez ce qui a survécu et ce qui n’a pas survécu.
Tâches pratiques : commandes, sorties et décisions
Voici des commandes réelles à exécuter pendant un incident, une migration ou une semaine « pourquoi c’est lent ». Pour chacune : quoi lancer, ce que la sortie signifie, et quelle décision prendre.
Task 1: See what is actually mounted (not what you think is in fstab)
cr0x@server:~$ findmnt -no SOURCE,TARGET,FSTYPE,OPTIONS /var/lib/postgresql
/dev/nvme0n1p2 /var/lib/postgresql ext4 rw,relatime,errors=remount-ro,data=ordered
Signification : C’est la vérité pour le noyau en cours d’exécution. Ici, ext4 est en data=ordered, ce qui est généralement le défaut le plus sûr.
Décision : Si vous voyez data=writeback, nobarrier ou un commit= anormalement grand sur un chemin nécessitant de la durabilité, signalez-le et planifiez un changement.
Task 2: Cross-check with /proc to spot bind mounts and surprises
cr0x@server:~$ grep -E ' /var/lib/postgresql ' /proc/mounts
/dev/nvme0n1p2 /var/lib/postgresql ext4 rw,relatime,errors=remount-ro,data=ordered 0 0
Signification : Même chose ; utile aussi quand la sortie de findmnt est filtrée par des outils.
Décision : Si un chemin est monté de façon inattendue depuis overlayfs, tmpfs ou une couche de runtime de conteneur, arrêtez-vous et cartographiez la vraie frontière de persistance.
Task 3: Inspect ext4 superblock defaults and features (journal status, etc.)
cr0x@server:~$ sudo tune2fs -l /dev/nvme0n1p2 | egrep 'Filesystem features|Default mount options|Filesystem state|Journal'
Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Default mount options: user_xattr acl
Filesystem state: clean
Journal features: journal_incompat_revoke journal_64bit journal_checksum_v3
Signification : Confirme que la journalisation est présente (has_journal) et que les checksums de métadonnées sont activés (metadata_csum), ce qui aide à détecter certaines corruptions.
Décision : Si le système de fichiers n’est pas clean après un incident, prévoyez une fenêtre de fsck hors-ligne. Si la journalisation manque sur un volume que vous supposiez journalisé, considérez cela comme un défaut de conception.
Task 4: Check the kernel’s view of journal replays and ext4 warnings
cr0x@server:~$ dmesg -T | egrep -i 'ext4|jbd2|xfs|btrfs' | tail -n 20
[Tue Feb 4 10:42:12 2026] EXT4-fs (nvme0n1p2): mounted filesystem with ordered data mode. Quota mode: none.
[Tue Feb 4 10:42:12 2026] EXT4-fs (nvme0n1p2): re-mounted. Opts: (null)
Signification : Montre si le système de fichiers a rejoué un journal, monté en lecture seule, ou loggué des erreurs.
Décision : Si vous voyez des replays répétés du journal ou « Errors detected », supposez des problèmes d’E/S sous-jacents ou un cache non fiable. Escaladez vers l’équipe matériel/virtualisation et réduisez les options risquant l’écriture.
Task 5: Verify disk write cache settings (and don’t assume they’re safe)
cr0x@server:~$ sudo hdparm -W /dev/nvme0n1
/dev/nvme0n1:
write-caching = 1 (on)
Signification : Le cache d’écriture est activé. C’est normal, mais cela soulève la question : est-il protégé par une protection perte de puissance, une mémoire sur batterie ou un contrôleur qui honore les flushs ?
Décision : Si c’est du matériel grand public sans PLP et que la durabilité vous importe, assurez-vous que les barrières/flushs sont activés et envisagez des changements matériels pour les tiers critiques.
Task 6: Check for volatile cache and flush support at the block layer
cr0x@server:~$ lsblk -D -o NAME,ROTA,DISC-GRAN,DISC-MAX,DISC-ZERO
NAME ROTA DISC-GRAN DISC-MAX DISC-ZERO
nvme0n1 0 512B 2G 0
Signification : Support discard et granularité. Pas un signal direct de durabilité, mais aide à comprendre la classe de périphérique et son comportement.
Décision : Utilisez cela comme indice : SSD/NVMe implique typiquement du caching d’écriture et un comportement FTL ; ajustez et validez en conséquence, surtout autour des sémantiques de flush.
Task 7: Look for disabled barriers/flushes in mount options
cr0x@server:~$ findmnt -no TARGET,OPTIONS | egrep -i 'barrier|nobarrier|data=writeback|commit='
/mnt/fast rw,relatime,data=writeback,commit=60
Signification : Ce montage affaiblit explicitement l’ordonnancement (data=writeback) et augmente l’intervalle de commit.
Décision : Si /mnt/fast contient quelque chose d’irremplaçable, planifiez un remount avec des options plus sûres et une audit applicatif de durabilité.
Task 8: Confirm NFS client mount behavior (what the client thinks it’s doing)
cr0x@server:~$ nfsstat -m
/var/lib/shared from nfs01:/export/shared
Flags: rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.2.10,local_lock=none
Signification : Montre la version NFS et les options client. Note : les options client ne contournent pas les accusés de réception côté serveur async.
Décision : Si cela soutient une base de données ou une file, traitez NFS comme un item de revue d’architecture. Vérifiez les options d’export serveur et la compatibilité applicative.
Task 9: Check NFS server exports for async (the real footgun)
cr0x@server:~$ sudo exportfs -v | sed -n '1,120p'
/export/shared
10.0.0.0/16(rw,async,wdelay,hide,no_subtree_check,sec=sys,secure,root_squash)
Signification : L’export est async. Le serveur peut accuser réception des écritures avant commit.
Décision : Pour les charges durables, changez en sync, puis mesurez honnêtement l’impact sur les performances. Si l’impact est inacceptable, la réponse est architecturale, pas du déni.
Task 10: Validate actual writeback pressure and dirty limits (risk window sizing)
cr0x@server:~$ sysctl vm.dirty_background_ratio vm.dirty_ratio vm.dirty_expire_centisecs
vm.dirty_background_ratio = 10
vm.dirty_ratio = 20
vm.dirty_expire_centisecs = 3000
Signification : Des pages sales peuvent s’accumuler jusqu’à 20% de la RAM avant throttling ; l’expiration est ~30 secondes. Cela affecte la quantité de données que le système peut « accuser » tout en n’étant pas encore sur disque.
Décision : Pour les systèmes critiques, gardez ces valeurs raisonnables. Ne « optimisez » pas en laissant le système tamponner des minutes d’écritures à moins d’accepter la perte de ces minutes en cas de crash.
Task 11: Observe what your filesystem thinks about delayed allocation and writeback (ext4 example)
cr0x@server:~$ cat /proc/mounts | grep ' ext4 ' | head -n 2
/dev/nvme0n1p2 / ext4 rw,relatime,errors=remount-ro,data=ordered 0 0
/dev/nvme0n1p3 /var ext4 rw,relatime,data=ordered 0 0
Signification : Confirme le mode de données et la gestion des erreurs.
Décision : Si vous avez besoin de garanties plus fortes pour des chemins spécifiques, envisagez de les déplacer vers un système de fichiers séparé avec des réglages plus conservateurs, plutôt que de rendre le système globalement plus lent.
Task 12: Measure whether your app is actually issuing flushes (a reality check)
cr0x@server:~$ sudo strace -f -e trace=fdatasync,fsync,openat,rename -p 1423 -s 80
strace: Process 1423 attached
fsync(17) = 0
rename("tmpfile", "current") = 0
fsync(5) = 0
Signification : Le process appelle fsync() et sync un FD de répertoire (souvent nécessaire après un rename() pour des métadonnées durables). C’est ce à quoi ressemble le comportement « correct » pour beaucoup de charges.
Décision : Si vous ne voyez pas fsync/fdatasync là où vous en attendez (bases de données, writers WAL, files d’attente), votre durabilité est probablement du wishful thinking. Corrigez l’appli/config avant d’accuser le système de fichiers.
Task 13: Check IO errors and timeouts at the block layer (silent corruption’s cousin)
cr0x@server:~$ sudo journalctl -k -b | egrep -i 'I/O error|blk_update_request|nvme|reset|timed out' | tail -n 20
Feb 04 10:38:21 server kernel: nvme nvme0: I/O 42 QID 7 timeout, aborting
Feb 04 10:38:21 server kernel: nvme nvme0: Abort status: 0x371
Signification : Vous avez des timeouts au niveau périphérique. Cela peut provoquer des replays de journal, des remount-ro, et des écritures partielles selon la gestion des erreurs.
Décision : Traitez cela comme un problème de fiabilité matériel/disque virtuel. Arrêtez d’optimiser les options de montage et commencez à planifier le remplacement, des correctifs firmware ou des changements d’infrastructure.
Task 14: Inspect queue settings to understand latency spikes (not directly durability, but often adjacent)
cr0x@server:~$ cat /sys/block/nvme0n1/queue/scheduler
[mq-deadline] kyber none
Signification : Montre le scheduler en cours. Le tuning de latence pousse parfois à désactiver des comportements liés au flush ; ne confondez pas ces couches.
Décision : Réglez l’ordonnancement séparément des sémantiques de durabilité. Gardez les barrières/flushs corrects, puis optimisez le débit/la latence dans ces contraintes.
Erreurs courantes : symptômes → cause racine → correction
1) « Le système de fichiers monte proprement, mais ma base de données a perdu des transactions commises »
Symptômes : Après crash/reboot, la BD démarre ; les logs montrent des commits réussis ; les données manquent ou sont retournées au-delà de ce que la réplication/WAL attend.
Cause racine : Les écritures reconnues n’étaient pas durables : NFS serveur async, barrières désactivées, cache d’écriture menteur, ou application n’appelant pas fsync correctement pour le WAL/les données. ext4 data=writeback peut amplifier l’étrangeté.
Correction : Assurez-vous que les exports NFS sont en sync pour les charges durables ; gardez barrières/flush activés ; validez que le périphérique honore les flushs ; passez le système de fichiers en mode de journalisation plus sûr ; corrigez la configuration applicative pour fsync aux bons points.
2) « Après une coupure de courant, les fichiers existent mais contiennent un contenu plus ancien »
Symptômes : Noms et timestamps semblent corrects ; contenus sont obsolètes ou partiellement revertés ; des mismatches de checksum apparaissent dans une fenêtre temporelle étroite avant le crash.
Cause racine : ext4 data=writeback ou problèmes de barrières/flushs permettant aux métadonnées de committer avant que les blocs de données ne soient stables.
Correction : Utilisez data=ordered (ou data=journal quand justifié) ; gardez les flushs activés ; vérifiez les sémantiques de flush du contrôleur/périphérique ; réduisez le tuning risqué.
3) « Tout est passé en lecture seule en plein vol »
Symptômes : Les applis échouent avec « Read-only file system » ; les logs kernel montrent des erreurs de système de fichiers ; remount automatique.
Cause racine : Erreurs d’E/S sous-jacentes ou corruption de métadonnées ; errors=remount-ro a fait son travail. Ce n’est pas un bug d’option de montage — le noyau vous protège.
Correction : Enquêter sur la santé du périphérique ; collecter les logs ; exécuter des vérifications de système de fichiers en maintenance ; remplacer le matériel suspect ; restaurer depuis des backups connus bons si nécessaire.
4) « Nous avons activé une option de performance et maintenant la récupération après crash prend une éternité »
Symptômes : Longs replays de journal ; boot lent ; services en attente de la récupération du système de fichiers ; forte activité d’E/S au démarrage.
Cause racine : commit= trop grand, backlog massif de writeback, ou workload produisant beaucoup de métadonnées non engagées ; pour NFS, backlog côté serveur.
Correction : Réduire l’intervalle de commit ; assurer une capacité d’E/S adéquate ; éviter de tamponner d’énormes jeux de pages sales ; pour NFS, garder les exports synchrones pour les données critiques et scaler le stockage correctement.
5) « Nous n’avons changé que les options de montage, pourquoi l’intégrité des données est-elle maintenant ‘aléatoire’ ? »
Symptômes : Heisenbugs après reboots ; échecs de checksum intermittents ; non reproductible sous charge normale.
Cause racine : Vous avez changé les sémantiques d’ordonnancement/durabilité. La charge de travail dépendait accidentellement de l’ancien comportement (timing, ordre, flushs) et viole maintenant ses propres invariants.
Correction : Revenez à des sémantiques sûres ; puis définissez et appliquez explicitement les frontières de durabilité dans l’application et la conception du stockage.
Listes de vérification / plan pas à pas
Checklist 1 : Avant de toucher aux options de montage en production
- Classifiez les données : cache/régénérable vs durable/authoritative.
- Écrivez la promesse de durabilité en clair : « Après que l’appli signale le succès, les données survivent à une perte d’alimentation. »
- Confirmez le comportement applicatif : appelle-t-elle correctement
fsync/fdatasync(y compris fsync de répertoire pour les workflows basés fichiers) ? - Confirmez le comportement du stockage : le périphérique/contrôleur/hyperviseur honore-t-il les flushs ?
- Mettez en scène le changement sous une charge proche de la production et exécutez un test d’arrêt non propre.
- Ayez un rollback : remount rapide ou redeploy de la configuration précédente.
Checklist 2 : Valeurs par défaut sûres que je recommande (et quand dévier)
- ext4 : privilégiez
data=ordered, barrières/flush activés (par défaut), évitezdata=writebackpour toute donnée durable. - XFS : conservez les valeurs par défaut sauf raison testée et spécifique. Investissez l’effort pour valider le comportement de flush du périphérique.
- NFS pour des charges durables : privilégiez l’export serveur
sync. Si vous avez besoin de performances proches d’async, repensez l’architecture (WAL local + réplication, ou stockage spécialisé). - Intervals de commit : n’augmentez pas sans précautions. Des fenêtres plus grandes signifient des pertes potentielles plus importantes.
Checklist 3 : Vérification post-incident (après un arrêt non propre)
- Capturez les logs noyau pour les replays/erreurs du système de fichiers.
- Vérifiez que les options de montage sont bien celles attendues.
- Exécutez des vérifications d’intégrité au niveau applicatif (pas seulement les checks du système de fichiers).
- Validez les dernières transactions reconnues ou marqueurs d’état.
- Si un décalage existe, supposez une défaillance de la chaîne de durabilité et escaladez en conséquence.
FAQ
1) Est-ce que data=writeback est toujours une « corruption » ?
Non. Le système de fichiers peut rester structurellement cohérent. La « corruption » est souvent sémantique : les métadonnées peuvent référencer des données qui n’ont pas été écrites dans l’ordre que vous supposiez. Si vous attendiez « le nouveau fichier pointe vers de nouveaux octets », writeback peut violer cela après un crash.
2) Si mon appli utilise fsync(), suis-je en sécurité ?
Plus sûr, mais pas automatiquement en sécurité. Il faut aussi que la pile de stockage honore les flushs, et vous devez fsync les bonnes choses (y compris les répertoires après rename/create selon le pattern). Et si vous êtes sur NFS avec serveur async, les accusés de réception peuvent encore précéder le commit durable.
3) Pourquoi les gens utilisent-ils des options dangereuses ?
Parce que les benchmarks sont convaincants et les incidents rares — jusqu’à ce qu’ils ne le soient plus. Aussi parce que certains environnements (clusters scratch, caches, fermes de build) n’ont vraiment pas besoin de durabilité, et les options sont valides là. L’erreur est de copier ces réglages dans des systèmes durables par mimétisme.
4) Quelle est la différence entre « cohérence du système de fichiers » et « durabilité des données » ?
La cohérence signifie que les structures du système de fichiers sont saines après récupération. La durabilité signifie que les écritures reconnues survivent aux crashs. La journalisation vise surtout la cohérence. La durabilité exige un ordonnancement correct et un comportement de flush sur toute la chaîne.
5) NFS est-il un bon choix pour les bases de données ?
Parfois, avec les bons réglages serveur (sync), un stockage sous-jacent stable et une base de données qui le supporte. Mais c’est un design à risque élevé si vous ne contrôlez pas toute la chaîne. Beaucoup d’équipes préfèrent le stockage local pour le WAL/écritures primaires et répliquent pour la redondance.
6) Dois-je désactiver le cache d’écriture du disque pour la sécurité ?
Désactiver le cache peut réduire le risque sur des périphériques non protégés, mais cela peut aussi écraser les performances et n’est pas toujours supporté ou efficace. La meilleure réponse : utilisez des périphériques avec protection perte de puissance pour les tiers critiques et gardez les barrières/flushs activés.
7) Quelle option de montage améliore le plus la sécurité ?
Généralement, « ne pas désactiver les fonctionnalités de sécurité » est la meilleure stratégie : n’utilisez pas data=writeback pour des données durables, ne désactivez pas barrières/flushs, et évitez async côté serveur NFS là où la durabilité compte. La sécurité est souvent l’absence d’« optimisations ».
8) Comment prouver que mon stockage est durable ?
Vous le testez par injection de faute style perte d’alimentation sous une charge réaliste. Exécutez une charge effectuant des écritures reconnues avec des frontières fsync, crashuez de façon non propre, redémarrez et validez les invariants. Tout le reste n’est que théorie.
9) Mon système de fichiers est ext4 avec data=ordered. Puis-je quand même perdre des données ?
Oui. Vous pouvez perdre les écritures les plus récentes qui étaient encore en cache, et vous pouvez perdre des écritures reconnues si le périphérique ment sur les flushs ou si l’application ne fsync pas correctement. ordered réduit certaines classes de surprises post-crash ; il ne suspend pas les lois de la physique.
10) Est-ce que data=journal est la solution universelle ?
Non. C’est plus lent et augmente l’amplification d’écriture. C’est un outil pour des cas spécifiques, pas un réglage universel. Beaucoup de systèmes tirent mieux parti d’un logging applicatif approprié (WAL) et de paramètres sûrs côté système de fichiers.
Conclusion : prochaines étapes réalisables cette semaine
Si vous ne retenez qu’une idée : les options de montage ne font pas que tuner les performances. Elles définissent ce que « terminé » signifie. Quand vous les changez, vous changez le contrat que vos applications pensaient avoir.
Faites ces étapes :
- Inventairez les montages sur les chemins critiques avec
findmnt. Notez tout ce qui est non par défaut et justifiez-le. - Interdisez
data=writebackpour les données durables sauf exception documentée et testée. - Auditez les exports NFS pour
async. Si vous en trouvez sur une charge durable, traitez-le comme un risque de sev. - Validez la chaîne de flush : comportement du cache périphérique, politiques du contrôleur, sémantiques de la couche de virtualisation.
- Ajoutez un test d’arrêt non propre à la staging pour au moins un service critique. Faites-en une routine, pas un exploit héroïque.
Vous n’avez pas besoin de devenir développeur de systèmes de fichiers. Vous devez juste arrêter de laisser des tweaks de performance réécrire votre histoire de durabilité à votre insu.