diff --git a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h --- a/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h +++ b/sys/contrib/openzfs/include/os/freebsd/zfs/sys/zfs_vfsops_os.h @@ -287,6 +287,7 @@ extern uint_t zfs_fsyncer_key; extern int zfs_super_owner; +extern int zfs_bclone_enabled; extern void zfs_init(void); extern void zfs_fini(void); diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c @@ -89,6 +89,10 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, debug, CTLFLAG_RWTUN, &zfs_debug_level, 0, "Debug level"); +int zfs_bclone_enabled; +SYSCTL_INT(_vfs_zfs, OID_AUTO, bclone_enabled, CTLFLAG_RWTUN, + &zfs_bclone_enabled, 0, "Enable block cloning"); + struct zfs_jailparam { int mount_snapshot; }; diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c @@ -6214,7 +6214,6 @@ } #endif -#if 0 #ifndef _SYS_SYSPROTO_H_ struct vop_copy_file_range_args { struct vnode *a_invp; @@ -6245,6 +6244,11 @@ int error; uint64_t len = *ap->a_lenp; + if (!zfs_bclone_enabled) { + mp = NULL; + goto bad_write_fallback; + } + /* * TODO: If offset/length is not aligned to recordsize, use * vn_generic_copy_file_range() on this fragment. @@ -6310,7 +6314,6 @@ ap->a_incred, ap->a_outcred, ap->a_fsizetd); return (error); } -#endif struct vop_vector zfs_vnodeops; struct vop_vector zfs_fifoops; @@ -6375,6 +6378,7 @@ #if __FreeBSD_version >= 1400043 .vop_add_writecount = vop_stdadd_writecount_nomsync, #endif + .vop_copy_file_range = zfs_freebsd_copy_file_range, }; VFS_VOP_VECTOR_REGISTER(zfs_vnodeops);