Hi hackers,

My learn-me-some-operating-system-hacking project for the holidays was
to add O_DSYNC to FreeBSD 13 (due out end of Q1ish).  I was motivated
by my project to port some of Andres's Linux-only PostgreSQL AIO stuff
to POSIX interfaces, where you need O_DSYNC to initiate the
asynchronous equivalent of fdatasync(2).

The system header change has one interesting consequence for existing
releases of PostgreSQL, though: xlogdefs.h now sees that there is an
O_DSYNC macro that is distinct from O_SYNC, and defaults to
wal_sync_method=open_datasync.  That's not a great default setting,
because it gets you O_DIRECT | O_DSYNC, which performs terribly when
you're writing 8KB blocks on UFS's default 32KB logical block size (it
triggers read-before-write, quite visibly destroying performance with
eg pg_test_fsync), and for all I know, it might even not work at all
on some other file systems.  I suspect it might come out very slightly
ahead on a UFS filesystem created with 8KB blocks, but in any case,
that seems like something you should have to opt in to, as you do on
Linux.

One idle question I have is whether there is any platform on Earth
where it's a good idea to use open_datasync as the default,
considering the complications of those two flags.  I can't answer
that, and it'd be hard to justify unleashing a global change on the
world, so I think the right change would be to single out FreeBSD for
the exact same treatment we give Linux.  That is, I'd like to force
the default to fdatasync in all release branches on that platform.
Here is patch to do that.

I wrapped it in #ifdef HAVE_FDATASYNC.  There are no supported
releases of FreeBSD that lack fdatasync(2), but older releases will be
out there (huh, there's an animal in our build farm that might
qualify), so in that case we should just fall back to the regular
decision logic that'll wind up using good old fsync().
From b5c7b0512ccbc1378803a8cc9a33fb9abf859eaf Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.mu...@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

Reply via email to