title: How to do atomic file write & fsync to stable storage on Linux?
body: <p>I'm writing a specialized database-like thingie targeting Linux. It needs to support atomic and durable modification.</p>
  <p>I'm trying to implement this using <a href="https://en.m.wikipedia.org/wiki/Write-ahead_logging" rel="nofollow noreferrer">write-ahead logging</a>, but having trouble figuring out how to properly atomically commit the log to stable storage.</p>
  <p>Currently, within the log record header I have a single byte for the <code>is_committed</code> flag, which indicates that the record is fully written to stable storage (to protect against failures mid-append) and the commit procedure goes like this:</p>
  <ol>
  <li>Append the complete log record with the <code>is_committed</code> byte set to <code>0</code>.</li>
  <li><code>fsync</code> the log file.</li>
  <li>Do a single-byte write setting <code>is_committed</code> byte to <code>1</code>.</li>
  <li><code>fsync</code> it again.</li>
  </ol>
  <p>Since single-byte write which modifies only one bit is surely atomic, if something fails at any point the stable storage will either contain full and correct record or <code>is_committed</code> byte will be <code>0</code>. So this appears to work as intended.</p>
  <p>However, consider what happens if second <code>fsync</code> reports an error for whatever reason. On one hand, this means that it was unable to propagate <code>is_committed == 1</code> to stable storage. On the other hand, since the preceding write succeeded, <code>is_committed == 1</code> remains in the file cache, and can still be written out to stable storage by the OS at any point as usual.</p>
  <p>So, while this procedure does provide durability and atomicity in the above sense, in this case there is no way to tell whether it has succeeded or failed. Therefore it appears a primitive is required that will perform steps 3 and 4 atomically.</p>
  <p><code>pwritev2</code> with <code>RWF_SYNC</code> flag, which can be used to do steps 3 and 4 in a single syscall is a candidate for such a primitive. However, it's not clear if this is just saving a syscall or is actually atomic in the sense required.</p>
  <p>So, how does one do an atomic write and fsync to stable storage while being able to tell whether it has succeeded or failed on Linux? Or am I misunderstanding something and the commit procedure should be different?</p>