Je ne résiste pas à l'envie de vous partager cet excellent post de Teodore T'so sur fsync, l'atomicité, les ordinateurs portables et ext4, qui fait suite à la récente polémique à ce sujet.
C'est un excellent article qui m'a permis d'apprendre beaucoup de choses, et dont la lecture peut à mon avis être intéressante pour tous ceux qui développe des applications qui utilisent des fichiers :)
Seul bémol, l'article est en anglais :-/
Le lien: http://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/
Bonne lecture!
# Résumé à la louche
Posté par ʭ ☯ . Évalué à 4.
Il note que Firefox 3 écrit 2,5Mo sur le disque à chaque clic, pour préserver l'historique en cas de crash. Cela fait bien trop à son vis.
Enfin, il pense qu'il faudrait pouvoir retarder l'application effective de fsync() si on est sur un portable et qu'on a demandé de ne réveiller le disque que toutes les 5 minutes : dès lors qu'on indique au noyau qu'on est prêt à perdre 5 minutes de travail, cela doit s'appliquer à toute écriture."
Pour ma part, cela m'a permis de comprendre pourquoi Firefox réveille tout le temps le disque dur en LAPTOP_MODE... je vais donc prendre plutôt Konqueror ;-)
⚓ À g'Auch TOUTE! http://afdgauch.online.fr
[^] # Re: Résumé à la louche
Posté par Laurent J (site web personnel, Mastodon) . Évalué à 2.
Maintenant, dans Firefox 3.5 (anciennement 3.1), cela a été plus ou moins corrigé. Ils ont essayé de faire le moins de requêtes possibles, et de regrouper les requetes quand c'était possible, afin de moins solliciter sqlite (et donc moins faire de fsync).
[^] # Commentaire supprimé
Posté par Anonyme . Évalué à 5.
Ce commentaire a été supprimé par l’équipe de modération.
[^] # Commentaire supprimé
Posté par Anonyme . Évalué à 4.
Ce commentaire a été supprimé par l’équipe de modération.
[^] # Re: Résumé à la louche
Posté par Antoine . Évalué à 5.
Non non, c'est bien la faute de Firefox qui a décidé d'utiliser une base données transactionnelle ACID-compliant pour sauver des données parfaitement accessoires (historique de navigation). Sqlite, lui, fait le boulot pour lequel il a été conçu.
Ceci dit, si Firefox embarque son propre sqlite lié en static (c'est une hypothèse que je fais), ils auraient pu patcher le source pour enlever les fsync().
[^] # Re: Résumé à la louche
Posté par Laurent J (site web personnel, Mastodon) . Évalué à 4.
peut être de ton point de vue, pas du mien. J'aime bien que mon navigateur me retrouve l'url d'un site visité en tapant seulement un mot ou deux (ou une syllabe). ;-)
>si Firefox embarque son propre sqlite lié en static (c'est une hypothèse que je fais), ils auraient pu patcher le source pour enlever les fsync()
la version vanilla embarque sqlite en static (les sources de sqlite sont incluses dans les sources de mozilla), mais il y a une option de compil qui permet d'utiliser en dynamique (ce que font les distrib).
Pas de patch spécifique sur sqlite. Toutes les améliorations faites par les dev de Firefox ont été proposées en upstream dans sqlite et ont été acceptées.
Pour ce qui est d'enlever fsync, ça ne serait pas top pour certaines données qui peuvent être jugées critiques. la base sqlite ne sert pas que pour l'historique, mais pour beaucoup d'autres choses dans Firefox ou ses extensions (mots de passe, données offline des applis web, cookies...).
[^] # Re: Résumé à la louche
Posté par benoar . Évalué à 4.
Je suppose qu'il voulait dire que dans le contexte d'un crash, ce n'est pas grave de perdre l'historique des 30 dernières secondes de ta navigation ...
[^] # Re: Résumé à la louche
Posté par TImaniac (site web personnel) . Évalué à 4.
[^] # Re: Résumé à la louche
Posté par Hank Lords . Évalué à 4.
Je préfererais qu'il ne crashe pas ...
[^] # Re: Résumé à la louche
Posté par Guillaume Denry (site web personnel) . Évalué à -1.
[^] # Re: Résumé à la louche
Posté par 2PetitsVerres . Évalué à 2.
Tous les nombres premiers sont impairs, sauf un. Tous les nombres premiers sont impairs, sauf deux.
[^] # Re: Résumé à la louche
Posté par Guillaume Denry (site web personnel) . Évalué à 5.
[^] # Re: Résumé à la louche
Posté par benoar . Évalué à 4.
[^] # Re: Résumé à la louche
Posté par Matthieu Moy (site web personnel) . Évalué à 2.
pour garantir que les données sont « sorties du processus », c'est juste fflush, c'est beaucoup moins cher ...
[^] # Re: Résumé à la louche
Posté par Axioplase ıɥs∀ (site web personnel) . Évalué à 4.
Un fichier "base", et plusieurs fichiers qui contiennent des changements d'états successifs. Et une fois de temps en temps, on recrée un fichier "base" en relisant les petits, et toutes les deux créations de base, on fait une rotation (qui permet donc de pas tout perdre si jamais une action non atomique est interrompue brusquement pendant le renomage ou la copie).
# Le post de Matthew Garett est aussi très intéressant
Posté par Étienne . Évalué à 6.
Sa position est de dire que le pattern qui consiste à faire un open("foo.tmp"), write(), close() and then rename("foo.tmp", "foo") devrait correctement fonctionner, c'est à dire que l'on s'attend à avoir un fichier foo qui a soit l'ancienne version, soit la nouvelle version étant donné que rename() est atomique. Mais en aucun cas on ne devrait avoir de perte de données en cas de crash.
Le fait de préconiser un fsync() est une fausse solution d'après lui, car on ne cherche pas à garantir que le fichier est écrit, on cherche à garantir que le fichier sera dans un état correct et on n'a pas besoin de sans arrêt synchroniser sur le disque pour cela.
Étienne
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Antoine . Évalué à 8.
« fsync is a) immensely slow (can cause system-wide filesystem stalls for
many seconds) and b) doesn't guarantee file integrity on modern hardware
(many drives only guarantee that data has made it to their onboard
caches).
Because fsync has such a negative effect on average I/O bandwidth, it
can actually increase the odds of hardware corruption by widening the
corruption window. It's not at all clear that fsync is desirable. »
http://www.selenic.com/pipermail/mercurial/2009-March/024582(...)
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par fmaz fmaz . Évalué à 3.
Si on écrit 300To de données sur le disque, il faut bien s'attendre à un moment à ce que le disque écrive ces 300To. Ça, ça prend du temps. Si fsync prend du temps, c'est qu'il y avait beaucoup à écrire, c'est tout.
Je trouve cet argument plein de bon sens.
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Guillaume Knispel . Évalué à 3.
Imaginons qu'on écrive une "conf" de 1 Mo chaque seconde remplaçant la précédente, que le besoin alors que le système tourne est de pouvoir lire la plus récente à chaque instant, et que le besoin en cas de crash est simplement d'en récupérer une pas trop vielle (et surtout une ne consistant pas non plus en 0 octets pour cause de perte de données...) : si le FS se contente de garantir ce que Posix dit un fsync() est obligatoire à chaque fois, on va donc écrire 1 Mo par seconde. Alors que si un pattern ultra courant à la open() write() close() rename() induit implicitement une barrière entre l'écriture des data et des metadata, le FS peut se contenter de commiter 1 fois par minute (ou plus ou moins selon la configuration) et tout le monde est content.
C'est une garantie de la part du FS qui va au delà de Posix, certes. Une appli utilisant ça serait non portable ; mais on peut être malin et la rendre néanmoins portable grâce aux fonction Posix :
long fpathconf(int fildes, int name);
long pathconf(const char *path, int name);
(vu dans un commentaire de http://lwn.net/Articles/323752/ , article encore réservé aux abonnés à ce jour)
Grâce à ces fonctions, il suffit pour écrire une application portable mais qui sait profiter des systèmes biens conçus, de vérifier la présence d'une capacité publiée par le FS indiquant qu'il garanti que les séquences open() write() close() rename() sont implicitement "sûres". Si la capacité n'est pas présente, l'application rajoute simplement un fsync().
Ce serait la bonne chose à faire. Bien meilleure que de demander à tout le monde de mettre tout le temps des fsync(), quitte à introduire des threads rien que pour ça et à écrire 42x plus sur le disque que nécessaire...
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
Je me demande d'ailleurs si on peut garantir l'existence partielle d'un fichier. (si on le voit comme une suite d'enregistrement) Il faudrait avoir une modification atomique d'un fichier. Par contre, cela veut dire beaucoup de choses sur la manière de fonctionner des disques durs.
"La première sécurité est la liberté"
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par ✅ ffx . Évalué à 3.
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Matthieu Moy (site web personnel) . Évalué à 4.
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par ✅ ffx . Évalué à 4.
Mais je n'ai pas forcément bien compris à quel problème on voulait s'attaquer ;)
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Étienne . Évalué à 4.
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Étienne . Évalué à 5.
Le problème lié à ext4 c'est que les le filesystem ne garantie pas que les modifications seront faite dans l'ordre où elles ont été appelées. Donc le rename peut survenir avant le write() en pratique car les modifications sur les données sont gérées séparément des modifications sur la table des inodes de ce que j'ai pu comprendre. En faisant son rename() à la fin (le rename doit être atomique, en tout cas on n'a pas une fenêtre d'ouverture de 50 secondes) on se dit que si tous le reste a été effectué, alors seulement on fera le rename(), si un plantage a eu lieu avant d'arriver au rename(), on aura au pire un fichier en trop sur le filesystem mais on aura gardé l'ancienne configuration.
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Anonyme . Évalué à 4.
So, what is the problem. POSIX fundamentally says that what happens if the system is not shutdown cleanly is undefined. If you want to force things to be stored on disk, you must use fsync() or fdatasync().
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Guillaume Knispel . Évalué à 2.
Un rename() étant une opération atomique, cela n'a quasiment aucun sens de ne pas garantir que le pattern open() write() close() rename() soit atomique quant à la transition entre les anciennes données et les nouvelles, et ce même en cas de crash. J'ose imaginer que les disques courants (ATA, SATA, SCSI, ...) ont des mécanisme de commandes de barrières qui permettrait d'apporter "facilement" de telles garanties - si ce n'est pas le cas il est urgent que leur comités normalisateurs respectifs se penchent sur le sujet....
fsync() est beaucoup plus fort qu'une simple barrière. L'utiliser dans tous les cas serait désastreux. C'est étonnant que ça ne paraisse pas évident à un kernel hacker.
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Anonyme . Évalué à 2.
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Hobgoblins Master (Mastodon) . Évalué à 3.
Ext4 n'est pas le seul à appliquer de cette façon cette partie de POSIX, XFS fait pareil et je perd la moitié ma conf KDE à chaque coupure électrique, ext3 doit également avoir le même comportement si le journal est en mode « writeback » et non « ordered »
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Nicolas Boulay (site web personnel) . Évalué à 5.
"La première sécurité est la liberté"
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Axioplase ıɥs∀ (site web personnel) . Évalué à 2.
Elle est pas chargée en lecture seule ?
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par Anonyme . Évalué à 1.
[^] # Re: Le post de Matthew Garett est aussi très intéressant
Posté par claudex . Évalué à 2.
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.