← Back to context

Comment by otterley

4 years ago

It's important to read the entire document including the notes, which informs the reader of a pretty clear intent (emphasis mine):

> The fsync() function is intended to force a physical write of data from the buffer cache, and to assure that after a system crash or other failure that all data up to the time of the fsync() call is recorded on the disk.

This seems consistent with user expectations - fsync() completion should mean data is fully recorded and therefore power-cycle- or crash-safe.

You are quoting the non-normative informative part. If _POSIX_SYNCHRONIZED_IO is not defined, your fsync can literally be this and still be compliant:

    int fsync(int) {}

Quick Google search (maybe someone with a MBP can confirm) says that macOS doesn't purport to implement SIO.

  • That particular implementation seems inconsistent with the following requirement:

    > The fsync() function shall request that all data for the open file descriptor named by fildes is to be transferred to the storage device associated with the file described by fildes.

    If I wrote that requirement in a classroom programming assignment and you presented me with that code, you'd get a failing grade. Similarly, if I were a product manager and put that in the spec and you submitted the above code, it wouldn't be merged.

    > You are quoting the non-normative informative part

    Indeed, I am! It is important. Context matters, both in law and in programming. As a legal analogy, if you study Supreme Court rulings, you will find that in addition to examining the text of legislation or regulatory rules, the court frequently looks to legislative history, including Congressional findings and statements by regulators and legislators in order to figure out how to best interpret the law - especially when the text is ambiguous.

    • > If I wrote that requirement in a classroom programming assignment and you presented me with that code, you'd get a failing grade.

      It's a good thing operating systems aren't made up entirely of classroom programming assignments.

      Picture an OS which always runs on fully-synchronized storage (perhaps a custom Linux or BSD or QNX kernel). If there's no write cache and all writes are synchronous, then fsync() doesn't need to do anything at all; therefore `int fsync(int) {return 0}` is valid because fsync()'s method is implementation-specific.

      This allows you to have no software or hardware write cache and not implement fsync() and still be POSIX-compliant.

      > Context matters, both in law and in programming. As a legal analogy, if you study Supreme Court rulings, you will find that in addition to examining the text of legislation or regulatory rules, the court frequently looks to legislative history, including Congressional findings and statements by regulators and legislators in order to figure out how to best interpret the law - especially when the text is ambiguous.

      The POSIX specification is not a court of law, and the context is pretty clear: fsync() should do whatever it needs to do to request that pending writes are written to the storage device. In some valid cases, that could be nothing.

      4 replies →

  • Since crashes and power failures are out of scope for POSIX, even F_FULLSYNC's behavior description would of necessity be informative rather than normative.

    But, the reality is that all operating systems provide some way to make writes to persistent storage complete, and to wait for them. All of them. It doesn't matter what POSIX says, or that it leaves crashes and power failure out of scope.

    POSIX's model is not a get-out-of-jail-free card for actual operating systems.