A.3. Fsync

Fsync est connu pour être une opération utilisant beaucoup d'E/S, mais cela n'est pas totalement vrai.
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 passage au système de fichiers ext4. Ext3 était réglé sur un mode de données ordonnées, qui vidait la mémoire toutes les quelques secondes et l'enregistrait sur un disque. Mais avec ext4 et laptop_mode, l'intervalle entre les sauvegardes est devenu plus long et des données pourvaient se perdre lorsque le système était éteint de manière inattendue. Maintenant ext4 est corrigé, mais nous devons quand même prendre en considération le design de nos applications en faisant attention, et utiliser fsync lorsqu'approprié.
L'exemple suivant illustrant simplement la lecture et l'écriture dans un fichier de configuration montre comment une copie de sauvegarde peut être réalisée, ou comment des données peuvent être perdues :
/* open and read configuration file e.g. ./myconfig */
fd = open("./myconfig", O_RDONLY);
read(fd, myconfig_buf, sizeof(myconfig_buf));
close(fd);
...
fd = open("./myconfig", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
write(fd, myconfig_buf, sizeof(myconfig_buf));
close(fd);
Une meilleure approche aurait été comme suit :
/* open and read configuration file e.g. ./myconfig */
fd = open("./myconfig", O_RDONLY);
read(fd, myconfig_buf, sizeof(myconfig_buf));
close(fd);
...
fd = open("./myconfig.suffix", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR
write(fd, myconfig_buf, sizeof(myconfig_buf));
fsync(fd); /* paranoia - optional */
...
close(fd);
rename("./myconfig", "./myconfig~"); /* paranoia - optional */
rename("./myconfig.suffix", "./myconfig");