Add wal_sync_method=fdatasync for Windows.
authorThomas Munro <[email protected]>
Wed, 20 Jul 2022 01:50:57 +0000 (13:50 +1200)
committerThomas Munro <[email protected]>
Wed, 20 Jul 2022 01:55:52 +0000 (13:55 +1200)
Windows 10 gained support for flushing NTFS files with fdatasync()
semantics.  The main advantage over open_datasync (in Windows API terms
FILE_FLAG_WRITE_THROUGH) is that the latter does not flush SATA drive
caches.  The default setting is not changed, so users have to opt in to
this.

Discussion: https://postgr.es/m/CA%2BhUKGJZJVO%3DiX%2Beb-PXi2_XS9ZRqnn_4URh0NUQOwt6-_51xQ%40mail.gmail.com

configure
configure.ac
doc/src/sgml/wal.sgml
src/include/c.h
src/include/port/win32_port.h
src/include/port/win32ntdll.h
src/port/fdatasync.c [new file with mode: 0644]
src/port/win32ntdll.c
src/tools/msvc/Mkvcbuild.pm
src/tools/msvc/Solution.pm

index a4f4d321fb72c3d01912396db24eacdb4143a843..59fa82b8d7aea5dcb8660a03fcbaddabf4b8477c 100755 (executable)
--- a/configure
+++ b/configure
  ;;
 esac
 
+  case " $LIBOBJS " in
+  *" fdatasync.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS fdatasync.$ac_objext"
+ ;;
+esac
+
   case " $LIBOBJS " in
   *" kill.$ac_objext "* ) ;;
   *) LIBOBJS="$LIBOBJS kill.$ac_objext"
index 5bd29a4d2f2f69e17831b1faa6549a898a07fd26..612dabf6988ffbaecf7e614a5871e4a41ae0df3d 100644 (file)
@@ -1988,6 +1988,7 @@ if test "$PORTNAME" = "win32"; then
   AC_CHECK_FUNCS(_configthreadlocale)
   AC_REPLACE_FUNCS(gettimeofday)
   AC_LIBOBJ(dirmod)
+  AC_LIBOBJ(fdatasync)
   AC_LIBOBJ(kill)
   AC_LIBOBJ(open)
   AC_LIBOBJ(system)
index 4b6ef283c1ce72d57ad6a1241724f47b4d72dcb9..01f7379ebb3d9dd581a643eefa839c29f27e6235 100644 (file)
         <literal>open_datasync</literal> (the default), write caching can be disabled
         by unchecking <literal>My Computer\Open\<replaceable>disk drive</replaceable>\Properties\Hardware\Properties\Policies\Enable write caching on the disk</literal>.
         Alternatively, set <varname>wal_sync_method</varname> to
-        <literal>fsync</literal> or <literal>fsync_writethrough</literal>, which prevent
+        <literal>fdatasync</literal> (NTFS only), <literal>fsync</literal> or
+        <literal>fsync_writethrough</literal>, which prevent
         write caching.
       </para>
     </listitem>
index 2cc2784750e9a14aa6899c62242df892def1b2e7..d35405f191a51635dd2efdb506131a3a627f31df 100644 (file)
@@ -1290,7 +1290,7 @@ typedef union PGAlignedXLogBlock
  * standard C library.
  */
 
-#if defined(HAVE_FDATASYNC) && !HAVE_DECL_FDATASYNC
+#if !HAVE_DECL_FDATASYNC
 extern int fdatasync(int fildes);
 #endif
 
index 5121c0c626e1be47b87615488ee2bca3c43d5100..5ea66528fadfeaa23481ff49f5abb9ef4e285d10 100644 (file)
 #define HAVE_FSYNC_WRITETHROUGH
 #define FSYNC_WRITETHROUGH_IS_FSYNC
 
+/*
+ * We have a replacement for fdatasync() in src/port/fdatasync.c, which is
+ * unconditionally used by MSVC and Mingw builds.
+ */
+#define HAVE_FDATASYNC
+
 #define USES_WINSOCK
 
 /*
index 291b067ea4fe186d20078993a7fdc02e7f184b7e..34cebddd542726783e6894c5839ce3c152a09b81 100644 (file)
 #include <ntstatus.h>
 #include <winternl.h>
 
-typedef NTSTATUS (__stdcall * RtlGetLastNtStatus_t) (void);
+#ifndef FLUSH_FLAGS_FILE_DATA_SYNC_ONLY
+#define FLUSH_FLAGS_FILE_DATA_SYNC_ONLY 0x4
+#endif
+
+typedef NTSTATUS (__stdcall *RtlGetLastNtStatus_t) (void);
+typedef ULONG (__stdcall *RtlNtStatusToDosError_t) (NTSTATUS);
+typedef NTSTATUS (__stdcall *NtFlushBuffersFileEx_t) (HANDLE, ULONG, PVOID, ULONG, PIO_STATUS_BLOCK);
 
 extern PGDLLIMPORT RtlGetLastNtStatus_t pg_RtlGetLastNtStatus;
+extern PGDLLIMPORT RtlNtStatusToDosError_t pg_RtlNtStatusToDosError;
+extern PGDLLIMPORT NtFlushBuffersFileEx_t pg_NtFlushBuffersFileEx;
 
 extern int initialize_ntdll(void);
 
diff --git a/src/port/fdatasync.c b/src/port/fdatasync.c
new file mode 100644 (file)
index 0000000..afef853
--- /dev/null
@@ -0,0 +1,53 @@
+/*-------------------------------------------------------------------------
+ *
+ * fdatasync.c
+ *    Win32 fdatasync() replacement
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * src/port/fdatasync.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#define UMDF_USING_NTSTATUS
+
+#ifdef FRONTEND
+#include "postgres_fe.h"
+#else
+#include "postgres.h"
+#endif
+
+#include "port/win32ntdll.h"
+
+int
+fdatasync(int fd)
+{
+   IO_STATUS_BLOCK iosb;
+   NTSTATUS    status;
+   HANDLE      handle;
+
+   handle = (HANDLE) _get_osfhandle(fd);
+   if (handle == INVALID_HANDLE_VALUE)
+   {
+       errno = EBADF;
+       return -1;
+   }
+
+   if (initialize_ntdll() < 0)
+       return -1;
+
+   memset(&iosb, 0, sizeof(iosb));
+   status = pg_NtFlushBuffersFileEx(handle,
+                                    FLUSH_FLAGS_FILE_DATA_SYNC_ONLY,
+                                    NULL,
+                                    0,
+                                    &iosb);
+
+   if (NT_SUCCESS(status))
+       return 0;
+
+   _dosmaperr(pg_RtlNtStatusToDosError(status));
+   return -1;
+}
index 10c33c6a01d7ed8a3dc90c519a116be4cf156331..eb6140775432f4ca1badc2e534d4ed58489b673a 100644 (file)
@@ -20,6 +20,8 @@
 #include "port/win32ntdll.h"
 
 RtlGetLastNtStatus_t pg_RtlGetLastNtStatus;
+RtlNtStatusToDosError_t pg_RtlNtStatusToDosError;
+NtFlushBuffersFileEx_t pg_NtFlushBuffersFileEx;
 
 typedef struct NtDllRoutine
 {
@@ -28,7 +30,9 @@ typedef struct NtDllRoutine
 } NtDllRoutine;
 
 static const NtDllRoutine routines[] = {
-   {"RtlGetLastNtStatus", (pg_funcptr_t *) &pg_RtlGetLastNtStatus}
+   {"RtlGetLastNtStatus", (pg_funcptr_t *) &pg_RtlGetLastNtStatus},
+   {"RtlNtStatusToDosError", (pg_funcptr_t *) &pg_RtlNtStatusToDosError},
+   {"NtFlushBuffersFileEx", (pg_funcptr_t *) &pg_NtFlushBuffersFileEx}
 };
 
 static bool initialized;
index e4feda10fd81f991e3e815e7b6002cf3b406c7f9..cc7a908d10a982f576e1b142368bbe08d22ffd73 100644 (file)
@@ -99,7 +99,8 @@ sub mkvcbuild
    $solution = CreateSolution($vsVersion, $config);
 
    our @pgportfiles = qw(
-     chklocale.c explicit_bzero.c fls.c getpeereid.c getrusage.c inet_aton.c
+     chklocale.c explicit_bzero.c fls.c fdatasync.c
+     getpeereid.c getrusage.c inet_aton.c
      getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c
      snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
      dirent.c dlopen.c getopt.c getopt_long.c link.c
index 1e125aef942cd40dfebe50d2d3c38ff1dab68443..3ddcd024a78c11b71f50a336efbc64baff47bf4c 100644 (file)
@@ -257,7 +257,7 @@ sub GenerateFiles
        HAVE_EDITLINE_READLINE_H                    => undef,
        HAVE_EXECINFO_H                             => undef,
        HAVE_EXPLICIT_BZERO                         => undef,
-       HAVE_FDATASYNC                              => undef,
+       HAVE_FDATASYNC                              => 1,
        HAVE_FLS                                    => undef,
        HAVE_FSEEKO                                 => 1,
        HAVE_FUNCNAME__FUNC                         => undef,