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().