Revised notes on the reliability of FlushFileBuffers


Some time ago, I wrote on the hard drives that lie about flushing file buffers (and the drivers who love them). Here's a check-in on what's happened over the past few years.

As things stand today, you can rely on Flush­File­Buffers committing your changes to physical disk. (Noting of course that this operation is expensive and may not actually help you if you aren't updating your data transactionally.)

Historically, NTFS used the Force Unit Access flag to indicate to the driver that it should wait until the information is committed to non-volatile storage before signaling that the operation has completed. The conventional technique to force writes to go to media is to pass FILE_FLAG_WRITE_THROUGH, which internally tells the file system to set the FUA flag on I/O operations to that file. But as noted in this article, in the Windows 7 time frame, EIDE and SATA drivers do not respect the FUA flag, which means that your writes may still be buffered by the drive's internal memory.

Fortunately, even with those drivers, the Flush­File­Buffers function will send the FLUSH_CACHE command, which tells the drive, "Hey, I know you have internal buffers. Look at me when I'm talking to you. Yes, you. With the internal buffers. Go flush them." Fortunately, nearly all drivers in the Windows 7 era respect that command. (There are a few stragglers that still ignore it.)

Fast-forward to Windows 8. Support for FLUSH_CACHE is required by all drives in order to be declared compatible with Windows 8, and the Windows storage team has worked with hard drive vendors to ensure that FLUSH_CACHE is properly respected. NTFS switched from using the FUA flag to the FLUSH_CACHE command to enforce consistency of its metadata.

Note that if an application opens a file with the FILE_FLAG_WRITE_THROUGH flag, NTFS still sets the FUA flag on the write operations. But as noted above, EIDE and SATA drivers do not respect the FUA flag, so asking for FILE_FLAG_WRITE_THROUGH doesn't give you any additional robustness in those cases.

If you want to flush the data to physical media, the Flush­File­Buffers function is your ticket.

As noted in the linked article, there are options in the UI to disable the signal to flush intermediate buffers, but you should use them only if you have a separate UPS for the hard drive, or if you simply don't mind that the drive can get corrupted in the event of a power failure.

Comments (10)
  1. Karellen says:

    So why doesn't FILE_FLAG_WRITE_THROUGH cause a FlushFileBuffers() on every write?

    FILE_FLAG_WRITE_THROUGH is not documented as "setting the FUA flag on write operations", it is documented as "Write operations will not go through any intermediate cache, they will go directly to disk."[0] If calling FlushFileBuffers() is what it takes to do that, why does FILE_FLAG_WRITE_THROUGH not do it?

    Yes, yes, the linked article points out that FlushFileBuffers() kills your performance, but that's what ignoring/flushing caches does, and anyone who asks for FILE_FLAG_WRITE_THROUGH has explicitly requested that tradeoff be made.

    Or should the documentation for FILE_FLAG_WRITE_THROUGH be updated to mention that it may be a no-op?

    [0] https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx

    1. Pierre B. says:

      Stand back a little and you will find the answer.

      First, there is the problem that programs would suddenly be slower. As Raymond often mentioned, making a new OS version that is perceptibly worse would prevent its adoption. If Windows 8 had made write-through more strict, then existing programs (that may even have used it inadvertently) would be worse.

      Second, there is the problem of backward compatibility. If you started to write code using write-through instead of flush-buffers under Windows 8, users of older OS would not get the correct behaviour because these previosu OS would not enforce it on the driver level.

      1. Karellen says:

        But the only reason that the program was running "faster" before is because it was buggy and incorrect! It wasn't actually doing a thing it was meant to be doing.

        And yes, if you fix a bug in a new version of your OS, older versions of your OS are not magically fixed also. So? Are you claiming that this is a good reason not to fix bugs in new versions of your OS?

        OTOH, if you're happy to trade speed for I/O correctness, Windows could make most programs run much quicker (if less correctly) by simply terminating them when they perform their first I/O operation. Tada!

    2. Presumably this flag is still honored by SCSI drives, so it does have some utility, albeit not consistently. Microsoft could make the flag trigger FlushFileBuffers in a future version of Windows 10 (they've done stuff like that before, though it's rare), but presumably there isn't much impetus to do so, especially if no customers have come demanding that the FILE_FLAG_WRITE_THROUGH behave as documented.

      1. Dave says:

        SCSI drives had this broken long before IDE did. I remember writing drivers for SCSI drives in the late 80s/early 90s and had to include a whole table of workarounds for various bugs in this mechanism. The worst one that I remember was the Iomega devices, which threw away the data write if you set the... whatever the equivalent of FUA was at the time. Took us a long time to figure that one out (because there were so many other bugs and error conditions that could have caused that or a similar-looking problem). Reported it to Iomega, their response was "well no-one uses that flag anyway". Pretty much said it all for Iomega's engineering approach as a whole.

    3. Drak says:

      "Write operations will not go through any intermediate cache, they will go directly to disk."

      Well, they do go directly to the disk. But the disk keeps them in its own buffers. It's quite possible that even with the flushing on, the writes still go through the buffers, but simply do not linger there. The only thing you know for sure is that Windows isn't storing the info in an intermediate cache itself.

      1. DWalker07 says:

        I think "go directly to disk" in this context means "go onto the magnetic platters" (or into SSD flash memory).

        The disk is the whole drive and all of its electronics, and the disk is also the round thing or the set of stacked round things (the discs) so the terminology is ambiguous.

  2. Joshua says:

    I'm glad that somebody finally did in that hydra.

    I was pondering the sequence of buy disk, run published test to detect that flush doesn't work, than return disk as defective, running in a loop until the manufacture got the point.

  3. Kevin says:

    Semi-related: Raymond, is TxF actually going away anytime soon, or are they just saying that?

    https://msdn.microsoft.com/en-us/library/windows/desktop/hh802690(v=vs.85).aspx

    I'm asking mostly because, on non-TxF systems, you have to do much more complicated things to get TxF-like semantics, e.g. see https://www.sqlite.org/atomiccommit.html#_multi_file_commit, and I want to know whether this is going to become true of Windows as well.

  4. Neil says:

    (The Atom feed thinks this is dated 20th February, although the RSS feed agrees with 10th May.)

Comments are closed.

Skip to main content