A.3. Fsync
Fsync
est connu pour être une opération d'E/S coûteuse, mais ce n'est pas totalement vrai. Par exemple, reportez-vous à l'article de Theodore Ts'o Don't fear the fsync! [5] et à la discussion l'accompagnant.
Firefox avait pour habitude d'appeler la bibliothèque sqlite à chaque fois que l'utilisateur cliquait sur un lien vers une nouvelle page. Sqlite appellait
fsync
et à cause des paramètres du système de fichiers (principalement ext3 avec le mode data-ordered), il y avait une longue latence lorsque rien ne se passait. Ceci pouvait ainsi prendre longtemps (jusqu'à 30 secondes) si un autre processus copiait un fichier de grande taille au même moment.
Cependant, dans d'autres cas, où
fsync
n'était pas du tout utilisé, des problèmes sont survenus lors du basculement vers les systèmes de fichiers ext4. Ext3 était réglé sur le mode data-ordered, qui vide la mémoire toutes les quelques secondes et l'enregistre sur le disque. Avec ext4 et laptop_mode, l'intervalle entre les enregistrements était plus long et les données pouvaient être perdues lorsque le système était éteint de manière inattendue. Il existe maintenant un patch pour ext4, mais il faut tout de même prendre en considération le design de nos applications avec prudence, et utiliser fsync
de manière appropriée.
L'exemple suivant illustrant simplement la lecture et l'écriture dans un fichier de configuration montre comment une copie de suavegarde peut être réalisée, ou comment des données peuvent être perdues :
/* open and read configuration file e.g. ~/.kde/myconfig */ fd = open("./kde/myconfig", O_WRONLY|O_TRUNC|O_CREAT); read(myconfig); ... write(fd, bufferOfNewData, sizeof(bufferOfNewData)); close(fd);
Une meilleure approche aurait été comme suit :
open("/.kde/myconfig", O_WRONLY|O_TRUNC|O_CREAT); read(myconfig); ... fd = open("/.kde/myconfig.suffix", O_WRONLY|O_TRUNC|O_CREAT); write(fd, bufferOfNewData, sizeof(bufferOfNewData)); fsync; /* paranoia - optional */ ... close(fd); rename("/.kde/myconfig", "/.kde/myconfig~"); /* paranoia - optional */ rename("/.kde/myconfig.suffix", "/.kde/myconfig");