Summary
SyncFile.sync() calls platform.fdatasync(self.fd), which resolves to os.fdatasync or os.fsync
- On macOS,
fsync() only flushes data to the drive's write cache, not to persistent storage
- True durability on macOS requires
fcntl(fd, F_FULLSYNC)
- This was already acknowledged with a TODO comment at
src/borg/platform/base.py:154: TODO: Use F_FULLSYNC on macOS.
- Without
F_FULLSYNC, Borg's data durability guarantees on macOS are weaker than intended - a power loss could result in data that SyncFile believed was safely persisted being lost
Proposed fix
Detect macOS (sys.platform == "darwin") and use fcntl.fcntl(fd, fcntl.F_FULLSYNC) in the fdatasync path:
import sys
if sys.platform == "darwin":
import fcntl
fcntl.fcntl(fd, fcntl.F_FULLSYNC)
else:
os.fsync(fd)
This could either live in platform/darwin.py as a platform-specific override of fdatasync, or inline in base.py with a platform check.
| File |
Change |
src/borg/platform/base.py or src/borg/platform/darwin.py |
Use fcntl.F_FULLSYNC on macOS instead of os.fsync; |
Summary
SyncFile.sync()callsplatform.fdatasync(self.fd), which resolves toos.fdatasyncoros.fsyncfsync()only flushes data to the drive's write cache, not to persistent storagefcntl(fd, F_FULLSYNC)src/borg/platform/base.py:154:TODO: Use F_FULLSYNC on macOS.F_FULLSYNC, Borg's data durability guarantees on macOS are weaker than intended - a power loss could result in data thatSyncFilebelieved was safely persisted being lostProposed fix
Detect macOS (
sys.platform == "darwin") and usefcntl.fcntl(fd, fcntl.F_FULLSYNC)in the fdatasync path:This could either live in
platform/darwin.pyas a platform-specific override offdatasync, or inline inbase.pywith a platform check.src/borg/platform/base.pyorsrc/borg/platform/darwin.pyfcntl.F_FULLSYNCon macOS instead ofos.fsync;