From b5c7b0512ccbc1378803a8cc9a33fb9abf859eaf Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Fri, 8 Jan 2021 14:06:27 +1300
Subject: [PATCH] Default to wal_sync_method=fdatasync on FreeBSD.

FreeBSD 13 gained O_DSYNC, which would normally cause wal_sync_method to
default to open_datasync.  That wouldn't be a good default for UFS due
to a mismatch in the default block sizes of PostgreSQL and UFS.  Let's
make sure we keep using fdatasync by default, to preserve existing
behavior.

Back-patch to all releases.
---
 doc/src/sgml/config.sgml                      |  2 +-
 src/backend/utils/misc/postgresql.conf.sample |  2 +-
 src/include/port/freebsd.h                    | 10 ++++++++++
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 4b60382778..e0711444db 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2920,7 +2920,7 @@ include_dir 'conf.d'
         Not all of these choices are available on all platforms.
         The default is the first method in the above list that is supported
         by the platform, except that <literal>fdatasync</literal> is the default on
-        Linux.  The default is not necessarily ideal; it might be
+        Linux and FreeBSD.  The default is not necessarily ideal; it might be
         necessary to change this setting or other aspects of your system
         configuration in order to create a crash-safe configuration or
         achieve optimal performance.
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index b7fb2ec1fe..b15d05e594 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -206,7 +206,7 @@
 #wal_sync_method = fsync		# the default is the first option
 					# supported by the operating system:
 					#   open_datasync
-					#   fdatasync (default on Linux)
+					#   fdatasync (default on Linux and FreeBSD)
 					#   fsync
 					#   fsync_writethrough
 					#   open_sync
diff --git a/src/include/port/freebsd.h b/src/include/port/freebsd.h
index 2e36d3da4f..567d2dbaf1 100644
--- a/src/include/port/freebsd.h
+++ b/src/include/port/freebsd.h
@@ -1 +1,11 @@
 /* src/include/port/freebsd.h */
+
+/*
+ * FreeBSD 13 gained O_DSYNC support.  Set the default wal_sync_method to
+ * fdatasync, because xlogdefs.h's normal rules would prefer open_datasync.
+ * That wouldn't be a good default, because 8KB direct writes interact badly
+ * with the default 32KB block size on UFS, requiring read-before-write.
+ */
+#ifdef HAVE_FDATASYNC
+#define PLATFORM_DEFAULT_SYNC_METHOD	SYNC_METHOD_FDATASYNC
+#endif
-- 
2.20.1

