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");