--- sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c	2023-04-04 07:09:16.404499000 -0700
+++ sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c.new	2023-04-04 07:56:05.228286000 -0700
@@ -6242,7 +6242,31 @@ zfs_freebsd_copy_file_range(struct vop_copy_file_range
 	struct uio io;
 	int error;
 	uint64_t len = *ap->a_lenp;
+	zfsvfs_t *outzfsvfs;
+	ojset_t *outos;
+	bool done_outvp;
 
+	mp = NULL;
+	error = vn_start_write(outvp, &mp, V_WAIT);
+	if (error == 0)
+		error = vn_lock(outvp, LK_EXCLUSIVE);
+	done_outvp = true;
+	if (error == 0) {
+		outzfsvfs = ZTOZSB(VTOZ(outvp));
+		outos = outzfsvfs->z_os;
+		if (!spa_feature_is_enabled(dmu_ojset_spa(outos),
+		    SPA_FEATURE_BLOCK_CLONING)) {
+			VOP_UNLOCK(outvp);
+			if (mp != NULL)
+				vn_finished_write(mp);
+			error = vn_generic_copy_file_range(ap->a_invp,
+			    ap->a_inoffp, ap->a_outvp, ap->a_outoffp,
+			    ap->a_lenp, ap->a_flags, ap->a_incred,
+			    ap->a_outcred, ap->a_fsizetd);
+			return (error);
+		}
+	}
+
 	/*
 	 * TODO: If offset/length is not aligned to recordsize, use
 	 * vn_generic_copy_file_range() on this fragment.
@@ -6252,27 +6276,29 @@ zfs_freebsd_copy_file_range(struct vop_copy_file_range
 
 	/* Lock both vnodes, avoiding risk of deadlock. */
 	do {
-		mp = NULL;
-		error = vn_start_write(outvp, &mp, V_WAIT);
+		if (!done_outvp) {
+			mp = NULL;
+			error = vn_start_write(outvp, &mp, V_WAIT);
+			if (error == 0)
+				error = vn_lock(outvp, LK_EXCLUSIVE);
+		}
 		if (error == 0) {
-			error = vn_lock(outvp, LK_EXCLUSIVE);
-			if (error == 0) {
-				if (invp == outvp)
-					break;
-				error = vn_lock(invp, LK_SHARED | LK_NOWAIT);
-				if (error == 0)
-					break;
-				VOP_UNLOCK(outvp);
-				if (mp != NULL)
-					vn_finished_write(mp);
-				mp = NULL;
-				error = vn_lock(invp, LK_SHARED);
-				if (error == 0)
-					VOP_UNLOCK(invp);
-			}
+			if (invp == outvp)
+				break;
+			error = vn_lock(invp, LK_SHARED | LK_NOWAIT);
+			if (error == 0)
+				break;
+			VOP_UNLOCK(outvp);
+			if (mp != NULL)
+				vn_finished_write(mp);
+			mp = NULL;
+			error = vn_lock(invp, LK_SHARED);
+			if (error == 0)
+				VOP_UNLOCK(invp);
 		}
 		if (mp != NULL)
 			vn_finished_write(mp);
+		done_outvp = false;
 	} while (error == 0);
 	if (error != 0)
 		return (error);
