A.3. Fsync

Fsync は I/O コストが高い操作として知られていますが、実際にはそうでない場合もあります。
ユーザーが新しいページに移動するリンクをクリックする度に、Firefoxsqlite ライブラリーを呼び出していました。sqlitefsync を呼び出すときに、ファイルシステム設定 (主に data-ordered モードの ext3) が原因で、長い遅延が発生し、何も処理が行われませんでした。また、この場合は、同時に別のプロセスが大きなファイルをコピーしているときに、最大で 30 秒の時間がかかっていました。
ただし、fsync が全く使用されない別のケースでは、ext4 ファイルシステムへの切り替えで問題が発生していました。Ext3 は data-ordered モードに設定され、数秒毎にメモリーがフラッシュされ、その内容がディスクに保存されていました。ただし、ext4 と laptop_mode を使用する場合は、保存の間隔が長いため、システムの電源が予期せずにオフになったときにデータが消失することがありました。現在、ext4 にはパッチが適用されましたが、アプリケーションを慎重に設計し、適切に fsync を使用する必要があります。
設定ファイルに対する読み書きの以下の簡単な例は、ファイルのバックアップ方法と、データがどのように失われるかを示しています。
/* 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);
より適切な例は以下のようになります。
/* 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");