Ich habe eine Datei mmap'd read-only/shared, mit mehreren Threads/Prozesse lesen die Daten gleichzeitig. Ein einzelner Schreiber darf die Daten jederzeit ändern (mit einem Mutex in einem separaten gemeinsamen Speicherbereich). Änderungen werden mit einem write() auf der zugrunde liegenden Datei durchgeführt. Der gesamte Aufbau ist Teil einer Datenbank, die transaktionskonsistent sein soll.
Es wird eine beliebige Anzahl von Datenseiten in beliebiger Reihenfolge ausgegeben, und dann wird fdatasync() aufgerufen. Nichts in der Datei zeigt auf diese geänderten Seiten, bis eine Root-Seite geschrieben wird. Die Root-Seite wird unter Verwendung eines zweiten Dateideskriptors geschrieben, der mit O_SYNC geöffnet wurde, so dass der Schreibvorgang nicht zurückkehrt, bevor die Root-Seite erfolgreich geschrieben wurde. Alle Seiten, die geschrieben werden, sind Teil der mmap-Region, so dass sie schließlich für alle Leser sichtbar werden.
Die Frage ist, ob der endgültige O_SYNC-Schreibvorgang sofort sichtbar wird, sobald der Kernel den Benutzerpuffer in den Seiten-Cache kopiert. Oder wird er erst sichtbar, wenn der synchrone Schreibvorgang abgeschlossen ist? Ich habe den Kernel-Code ein wenig durchgelesen, bin ihm aber nicht ganz gefolgt; für mich sieht es so aus, als ob die Benutzerdaten sofort in den Seiten-Cache kopiert werden, dann wird ein Schreibvorgang geplant, und dann wird gewartet, bis der Schreibvorgang abgeschlossen ist. In der Zwischenzeit befinden sich die geschriebenen Daten bereits im Page Cache und sind somit für die Leseprozesse sofort sichtbar. Dies ist unerwünscht, denn wenn der physische Schreibvorgang fehlschlägt, muss die Transaktion zurückgesetzt werden, und die Leser sollten niemals etwas sehen können, das von einer fehlgeschlagenen Transaktion geschrieben wurde.
Weiß jemand mit Sicherheit, wie O_SYNC-Schreibvorgänge mit dem Seiten-Cache interagieren? Ich nehme an, nur um sicher zu sein, kann ich wrap Zugriffe auf die Root-Seite mit einem Mutex, aber das fügt eine Schicht von Overhead, die besser zu vermeiden wäre.