diff --git a/setup.py b/setup.py index 8cdaef3e7..796c74567 100644 --- a/setup.py +++ b/setup.py @@ -76,6 +76,7 @@ item_source = 'src/borg/item.pyx' checksums_source = 'src/borg/algorithms/checksums.pyx' platform_posix_source = 'src/borg/platform/posix.pyx' platform_linux_source = 'src/borg/platform/linux.pyx' +platform_syncfilerange_source = 'src/borg/platform/syncfilerange.pyx' platform_darwin_source = 'src/borg/platform/darwin.pyx' platform_freebsd_source = 'src/borg/platform/freebsd.pyx' msgpack_packer_source = 'src/borg/algorithms/msgpack/_packer.pyx' @@ -92,6 +93,7 @@ cython_c_sources = [ platform_posix_source, platform_linux_source, + platform_syncfilerange_source, platform_freebsd_source, platform_darwin_source, ] @@ -832,6 +834,7 @@ if not on_rtd: ext_modules.append(Extension('borg.platform.posix', [platform_posix_source])) if sys.platform == 'linux': ext_modules.append(Extension('borg.platform.linux', [platform_linux_source], libraries=['acl'])) + ext_modules.append(Extension('borg.platform.syncfilerange', [platform_syncfilerange_source])) elif sys.platform.startswith('freebsd'): ext_modules.append(Extension('borg.platform.freebsd', [platform_freebsd_source])) elif sys.platform == 'darwin': diff --git a/src/borg/platform/linux.pyx b/src/borg/platform/linux.pyx index 37875d2ad..4a5b27513 100644 --- a/src/borg/platform/linux.pyx +++ b/src/borg/platform/linux.pyx @@ -12,6 +12,11 @@ from ..helpers import safe_decode, safe_encode from .base import SyncFile as BaseSyncFile from .base import safe_fadvise from .posix import swidth +try: + from .syncfilerange import sync_file_range, SYNC_FILE_RANGE_WRITE, SYNC_FILE_RANGE_WAIT_BEFORE, SYNC_FILE_RANGE_WAIT_AFTER + SYNC_FILE_RANGE_LOADED = True +except ImportError: + SYNC_FILE_RANGE_LOADED = False from libc cimport errno from libc.stdint cimport int64_t @@ -36,12 +41,6 @@ cdef extern from "sys/acl.h": cdef extern from "acl/libacl.h": int acl_extended_file(const char *path) -cdef extern from "fcntl.h": - int sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags) - unsigned int SYNC_FILE_RANGE_WRITE - unsigned int SYNC_FILE_RANGE_WAIT_BEFORE - unsigned int SYNC_FILE_RANGE_WAIT_AFTER - cdef extern from "linux/fs.h": # ioctls int FS_IOC_SETFLAGS @@ -241,7 +240,7 @@ cdef _sync_file_range(fd, offset, length, flags): cdef unsigned PAGE_MASK = sysconf(_SC_PAGESIZE) - 1 -if 'basesyncfile' in workarounds: +if 'basesyncfile' in workarounds or not SYNC_FILE_RANGE_LOADED: class SyncFile(BaseSyncFile): # if we are on platforms with a broken or not implemented sync_file_range, # use the more generic BaseSyncFile to avoid issues. diff --git a/src/borg/platform/syncfilerange.pyx b/src/borg/platform/syncfilerange.pyx new file mode 100644 index 000000000..f3c57ef31 --- /dev/null +++ b/src/borg/platform/syncfilerange.pyx @@ -0,0 +1,13 @@ +from libc.stdint cimport int64_t + + +# Some Linux systems (like Termux on Android 7 or earlier) do not have access +# to sync_file_range. By isolating the access to sync_file_range in this +# separate extension, it can be imported dynamically from linux.pyx only when +# available and systems without support can otherwise use the rest of +# linux.pyx. +cdef extern from "fcntl.h": + int sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags) + unsigned int SYNC_FILE_RANGE_WRITE + unsigned int SYNC_FILE_RANGE_WAIT_BEFORE + unsigned int SYNC_FILE_RANGE_WAIT_AFTER