From 6e05c1b606677cdfd29a20c7a39efac32df2642e Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Sun, 1 Sep 2024 12:34:17 +1000 Subject: [PATCH] zfs_file: implement zfs_file_deallocate for FreeBSD 14 FreeBSD 14 gained a `VOP_DEALLOCATE` VFS operation and a `fspacectl` syscall to use it. At minimum, these zero the given region, and if the underlying filesystem supports it, can make the region sparse. We can use this to get TRIM-like behaviour for file vdevs. Sponsored-by: https://despairlabs.com/sponsor/ Signed-off-by: Rob Norris --- lib/libzpool/kernel.c | 6 ++++++ module/os/freebsd/zfs/zfs_file_os.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index 68d22a431b96..4f4cf490f8e9 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -1380,6 +1380,12 @@ zfs_file_deallocate(zfs_file_t *fp, loff_t offset, loff_t len) #if defined(__linux__) rc = fallocate(fp->f_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, len); +#elif defined(__FreeBSD__) && (__FreeBSD_version >= 1400029) + struct spacectl_range rqsr = { + .r_offset = offset, + .r_len = len, + }; + rc = fspacectl(fp->f_fd, SPACECTL_DEALLOC, &rqsr, 0, &rqsr); #else (void) fp, (void) offset, (void) len; rc = EOPNOTSUPP; diff --git a/module/os/freebsd/zfs/zfs_file_os.c b/module/os/freebsd/zfs/zfs_file_os.c index 0a91ed47e144..f6ee391deddd 100644 --- a/module/os/freebsd/zfs/zfs_file_os.c +++ b/module/os/freebsd/zfs/zfs_file_os.c @@ -295,8 +295,20 @@ zfs_file_fsync(zfs_file_t *fp, int flags) int zfs_file_deallocate(zfs_file_t *fp, loff_t offset, loff_t len) { + int rc; +#if __FreeBSD_version >= 1400029 + struct thread *td; + + td = curthread; + rc = fo_fspacectl(fp, SPACECTL_DEALLOC, &offset, &len, 0, + td->td_ucred, td); +#else (void) fp, (void) offset, (void) len; - return (SET_ERROR(EOPNOTSUPP)); + rc = EOPNOTSUPP; +#endif + if (rc) + return (SET_ERROR(rc)); + return (0); } zfs_file_t *