Re: fdatasync behaviour in macOS

Sitsofe Wheeler <[email protected]> Thu, 11 Dec 2025 21:34:07 +0000
Newsgroups org.kernel.vger.fio
Message-ID <CALjAwxg-==Q7VQcVOHkqXBS-EnWLUkanuxVYfLYs1AD8pc_Kdg@mail.gmail.com>
Hi Anil,

On Thu, 11 Dec 2025 at 03:28, Anil Sharma <[email protected]> wrote:
>
> I think the confusing point for me was that I assumed for darwin fdatasync is mapped to the way fio handle fsync option and not OS's implementation (In documentation we mention when not supported it maps to fsync) and fsync option internally is mapped to fcntl(..., F_FULLFSYNC). I think other users might have similar understanding,

That's a fair point; doing a quick "git grep -C 5 DDIR_DATASYNC" shows
there are many ioengines that treat calls for fsync and fdatasync the
same way but do_io_u_sync() in io_u.c does not. There are at least two
ways to look at this: the documentation is wrong and needs updating
(i.e. lack of fdatasync() MAY fallback to fsync()) or the code is
wrong and needs updating :-)

> either we can disable the support of fdatasync option for darwin by either printing the warning and map to OS's fsync implementation or fail early.
>
> In general, fsync implementation in Darwin is not POSIX standard; we can't do much about it.

Technically the macOS's fsync() implementation *is* POSIX compliant (I
guess because macOS keeps achieving UNIX compliance this follows).
macOS defines _POSIX_SYNCHRONIZED_IO as -1 so strictly speaking it is
allowed to have an fsync() that doesn't flush the drive buffers (see
https://pubs.opengroup.org/onlinepubs/9799919799/ for POSIX's
wording). One can debate whether this is in the spirit of a POSIX
compliant fsync() but it matches the letter of it. There are other
OSes that "weak" fsync() behaviour (FreeBSD won't flush drive buffers
on fsync() unless ZFS is being used or you do some extra filesystem
specific configuration).

> But I would have assumed in any platform both fsync and fdatasync options will provide similar durability guarantees. So, intuitively fsync and fdatasync both can map Darwin's fsync implementation. There could be a separate option f_fullfsync = int only supported for darwin. Which makes it clear when running benchmarks for specific durability guarantee.

You can see Jens' introducing the fsync() -> fcntl(..., F_FULLFSYNC)
mapping in https://github.com/axboe/fio/commit/a04e0665cb5d3a545ab1dbe2d2b7c150b404735d
so my guess is if such an option were introduced it would have to
default to off. I pretty much agree that doing one of the following
would be an improvement:
- If CONFIG_FDATASYNC is defined map fdatasync to fcntl(..., F_FULLFSYNC)
- Change the #ifdef CONFIG_FDATASYNC before fdatasync to #if
defined(CONFIG_FDATASYNC) && !defined(CONFIG_FDATASYNC)
- Introduce a ffullfsync option (name to be bikeshedded) if
CONFIG_FDATASYNC is defined and if the ffullfsync option is disabled
use the "real" fsync()/fdatasync() otherwise use fcntl(...,
F_FULLFSYNC) for both fsync()/fdatasync()

Again, if someone (I'm not volunteering ;-) were to submit a non-ugly
patch/PR cleaning everything up then it could be reviewed.

--
Sitsofe