How to ensure all data has been physically written to disk?

Stefan Schultze picture Stefan Schultze · Dec 20, 2008 · Viewed 17.6k times · Source

I understand that .NET FileStream's Flush method only writes the current buffer to disk, but dependent on Windows' disk driver and the hard disk firmware this is no guarantee that the data is actually physically written to disk.

Is there a .NET or Win32 method that can give me this guarantee? So if there is power loss one nanosecond after the call to this method comes back, I can still be sure that everything is OK?

Answer

jimvfr picture jimvfr · Oct 22, 2010

Stefan S. said:

I understand that .NET FileStream's Flush method only writes the current buffer to disk

No, .NET FileStream's Flush only writes the .NET buffers to the OS cache, it does not flush the OS cache to disk. Sadly the MSDN doc on this class doesn't say that. For .NET < 4.0, you'll have to call Flush + Win32's FlushFilebuffers:

using System.Runtime.InteropServices;
. . .

// start of class:
[DllImport("kernel32", SetLastError=true)]
private static extern bool FlushFileBuffers(IntPtr handle);
. . .

stream.Flush();     // Flush .NET buffers to OS file cache.
#pragma warning disable 618,612 // disable stream.Handle deprecation warning.
if (!FlushFileBuffers(stream.Handle))   // Flush OS file cache to disk.
#pragma warning restore 618,612
{
  Int32 err = Marshal.GetLastWin32Error();
  throw new Win32Exception(err, "Win32 FlushFileBuffers returned error for " + stream.Name);
}

For .NET 4.0, you can instead use the new flush(true) method. 11/09/2012 update: MS bug report here says it's broken, then fixed, but doesn't say what version or service pack it was fixed in! Sounds like bug was if internal .NET FileStream buffer is empty, the Flush(true) did nothing??