diff --git a/config/user-largefile.m4 b/config/user-largefile.m4 new file mode 100644 index 000000000..e9e576f86 --- /dev/null +++ b/config/user-largefile.m4 @@ -0,0 +1,21 @@ +dnl # +dnl # ZFS_AC_CONFIG_USER_LARGEFILE +dnl # +dnl # Ensure off_t is 64-bit for large file support in userspace. +dnl # This is required for OpenZFS to handle files larger than 2GB. +dnl # +AC_DEFUN([ZFS_AC_CONFIG_USER_LARGEFILE], [ + AC_SYS_LARGEFILE + AC_CHECK_SIZEOF([off_t]) + + AC_MSG_CHECKING([for 64-bit off_t]) + AS_IF([test "$ac_cv_sizeof_off_t" -ne 8], [ + AC_MSG_RESULT([no, $ac_cv_sizeof_off_t bytes]) + AC_MSG_FAILURE([ +*** OpenZFS userspace requires 64-bit off_t support for large files. +*** Please ensure your system supports large file operations. +*** Current off_t size: $ac_cv_sizeof_off_t bytes]) + ], [ + AC_MSG_RESULT([yes, $ac_cv_sizeof_off_t bytes]) + ]) +]) diff --git a/config/user.m4 b/config/user.m4 index 62e59ed94..28c5162f5 100644 --- a/config/user.m4 +++ b/config/user.m4 @@ -3,6 +3,7 @@ dnl # Default ZFS user configuration dnl # AC_DEFUN([ZFS_AC_CONFIG_USER], [ ZFS_AC_CONFIG_USER_GETTEXT + ZFS_AC_CONFIG_USER_LARGEFILE ZFS_AC_CONFIG_USER_MOUNT_HELPER ZFS_AC_CONFIG_USER_SYSVINIT ZFS_AC_CONFIG_USER_DRACUT diff --git a/include/sys/zfs_file.h b/include/sys/zfs_file.h index 67abe9988..34870e826 100644 --- a/include/sys/zfs_file.h +++ b/include/sys/zfs_file.h @@ -25,6 +25,17 @@ #include +/* + * loff_t is a Linux kernel/VFS type. glibc and musl expose it to user + * space via , but FreeBSD libc does not. For FreeBSD user + * space we map loff_t to off_t so the shared interfaces that use the + * loff_t name still compile. The FreeBSD kernel gets loff_t from its + * own linux-compat headers. + */ +#if !defined(_KERNEL) && defined(__FreeBSD__) +typedef off_t loff_t; +#endif + #ifndef _KERNEL typedef struct zfs_file { int f_fd; diff --git a/lib/libspl/include/sys/kstat.h b/lib/libspl/include/sys/kstat.h index 361f24df3..b86737c96 100644 --- a/lib/libspl/include/sys/kstat.h +++ b/lib/libspl/include/sys/kstat.h @@ -86,6 +86,6 @@ extern void kstat_delete(kstat_t *); extern void kstat_set_raw_ops(kstat_t *ksp, int (*headers)(char *buf, size_t size), int (*data)(char *buf, size_t size, void *data), - void *(*addr)(kstat_t *ksp, loff_t index)); + void *(*addr)(kstat_t *ksp, off_t index)); #endif /* _SYS_KSTAT_H */ diff --git a/lib/libspl/include/sys/types.h b/lib/libspl/include/sys/types.h index 37cf1d241..f4bb85c79 100644 --- a/lib/libspl/include/sys/types.h +++ b/lib/libspl/include/sys/types.h @@ -50,19 +50,4 @@ typedef int projid_t; #include /* for NBBY */ -#ifdef __FreeBSD__ -typedef off_t loff_t; -#endif - -/* - * On musl, loff_t is a macro within fcntl.h when _GNU_SOURCE is defined. - * If no macro is defined, a typedef fallback is provided. - */ -#if defined(__linux__) && !defined(__GLIBC__) -#include -#ifndef loff_t -typedef off_t loff_t; -#endif -#endif - #endif diff --git a/lib/libspl/kstat.c b/lib/libspl/kstat.c index af4b870ed..5f62fd358 100644 --- a/lib/libspl/kstat.c +++ b/lib/libspl/kstat.c @@ -58,7 +58,7 @@ void kstat_set_raw_ops(kstat_t *ksp, int (*headers)(char *buf, size_t size), int (*data)(char *buf, size_t size, void *data), - void *(*addr)(kstat_t *ksp, loff_t index)) + void *(*addr)(kstat_t *ksp, off_t index)) { (void) ksp, (void) headers, (void) data, (void) addr; } diff --git a/tests/zfs-tests/cmd/clone_mmap_cached.c b/tests/zfs-tests/cmd/clone_mmap_cached.c index b0be77798..d10431e3f 100644 --- a/tests/zfs-tests/cmd/clone_mmap_cached.c +++ b/tests/zfs-tests/cmd/clone_mmap_cached.c @@ -36,12 +36,13 @@ #include #include -#ifdef __FreeBSD__ -#define loff_t off_t +#if defined(_GNU_SOURCE) && defined(__linux__) +_Static_assert(sizeof (loff_t) == sizeof (off_t), + "loff_t and off_t must be the same size"); #endif ssize_t -copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int) +copy_file_range(int, off_t *, int, off_t *, size_t, unsigned int) __attribute__((weak)); static void * diff --git a/tests/zfs-tests/cmd/clone_mmap_write.c b/tests/zfs-tests/cmd/clone_mmap_write.c index 8423b6568..183c95d76 100644 --- a/tests/zfs-tests/cmd/clone_mmap_write.c +++ b/tests/zfs-tests/cmd/clone_mmap_write.c @@ -42,12 +42,13 @@ #include #include -#ifdef __FreeBSD__ -#define loff_t off_t +#if defined(_GNU_SOURCE) && defined(__linux__) +_Static_assert(sizeof (loff_t) == sizeof (off_t), + "loff_t and off_t must be the same size"); #endif ssize_t -copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int) +copy_file_range(int, off_t *, int, off_t *, size_t, unsigned int) __attribute__((weak)); static int diff --git a/tests/zfs-tests/cmd/clonefile.c b/tests/zfs-tests/cmd/clonefile.c index 809a33d2f..eae69bef6 100644 --- a/tests/zfs-tests/cmd/clonefile.c +++ b/tests/zfs-tests/cmd/clonefile.c @@ -59,16 +59,17 @@ #endif #endif /* __NR_copy_file_range */ -#ifdef __FreeBSD__ -#define loff_t off_t +#if defined(_GNU_SOURCE) && defined(__linux__) +_Static_assert(sizeof (loff_t) == sizeof (off_t), + "loff_t and off_t must be the same size"); #endif ssize_t -copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int) +copy_file_range(int, off_t *, int, off_t *, size_t, unsigned int) __attribute__((weak)); static inline ssize_t -cf_copy_file_range(int sfd, loff_t *soff, int dfd, loff_t *doff, +cf_copy_file_range(int sfd, off_t *soff, int dfd, off_t *doff, size_t len, unsigned int flags) { if (copy_file_range) @@ -151,9 +152,9 @@ usage(void) } int do_clone(int sfd, int dfd); -int do_clonerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len); -int do_copyfilerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len); -int do_deduperange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len); +int do_clonerange(int sfd, int dfd, off_t soff, off_t doff, size_t len); +int do_copyfilerange(int sfd, int dfd, off_t soff, off_t doff, size_t len); +int do_deduperange(int sfd, int dfd, off_t soff, off_t doff, size_t len); int quiet = 0; @@ -203,7 +204,7 @@ main(int argc, char **argv) abort(); } - loff_t soff = 0, doff = 0; + off_t soff = 0, doff = 0; size_t len = SSIZE_MAX; unsigned long long len2; if ((argc-optind) == 5) { @@ -295,7 +296,7 @@ do_clone(int sfd, int dfd) } int -do_clonerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) +do_clonerange(int sfd, int dfd, off_t soff, off_t doff, size_t len) { if (!quiet) fprintf(stderr, "using FICLONERANGE\n"); @@ -314,7 +315,7 @@ do_clonerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) } int -do_copyfilerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) +do_copyfilerange(int sfd, int dfd, off_t soff, off_t doff, size_t len) { if (!quiet) fprintf(stderr, "using copy_file_range\n"); @@ -341,7 +342,7 @@ do_copyfilerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) } int -do_deduperange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) +do_deduperange(int sfd, int dfd, off_t soff, off_t doff, size_t len) { if (!quiet) fprintf(stderr, "using FIDEDUPERANGE\n");