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 index 107cd69c756c..e799a7091b8e 100644 --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c @@ -6270,6 +6270,11 @@ zfs_freebsd_copy_file_range(struct vop_copy_file_range_args *ap) goto bad_write_fallback; } } + + if (invp->v_mount->mnt_vfc != outvp->v_mount->mnt_vfc) { + goto bad_write_fallback; + } + if (invp == outvp) { if (vn_lock(outvp, LK_EXCLUSIVE) != 0) { goto bad_write_fallback; diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 9898bf010a21..6af1b5e6f737 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -1131,6 +1131,46 @@ null_vput_pair(struct vop_vput_pair_args *ap) return (res); } +static int +null_copy_file_range(struct vop_copy_file_range_args *ap) +{ + struct vnode *inlvp, *outlvp; + int error; + + if (vn_lock(ap->a_invp, LK_SHARED) != 0) { + error = EBADF; + goto outi; + } + + inlvp = NULLVPTOLOWERVP(ap->a_invp); + vref(inlvp); + VOP_UNLOCK(ap->a_invp); + + if (vn_lock(ap->a_outvp, LK_SHARED) != 0) { + error = EBADF; + goto outo; + } + + if (strcmp(ap->a_outvp->v_mount->mnt_vfc->vfc_name, "nullfs") == 0) { + outlvp = NULLVPTOLOWERVP(ap->a_outvp); + } else { + outlvp = ap->a_outvp; + + } + vref(outlvp); + VOP_UNLOCK(ap->a_outvp); + + error = VOP_COPY_FILE_RANGE(inlvp, ap->a_inoffp, outlvp, + ap->a_outoffp, ap->a_lenp, ap->a_flags, ap->a_incred, + ap->a_outcred, ap->a_fsizetd); + + vrele(outlvp); +outo: + vrele(inlvp); +outi: + return (error); +} + /* * Global vfs data structures */ @@ -1163,5 +1203,6 @@ struct vop_vector null_vnodeops = { .vop_vptofh = null_vptofh, .vop_add_writecount = null_add_writecount, .vop_vput_pair = null_vput_pair, + .vop_copy_file_range = null_copy_file_range, }; VFS_VOP_VECTOR_REGISTER(null_vnodeops); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 27ce5401f15f..d9e13c682dcc 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -3108,13 +3108,8 @@ vn_copy_file_range(struct vnode *invp, off_t *inoffp, struct vnode *outvp, * which can handle copies across multiple file system types. */ *lenp = len; - if (inmp == outmp || strcmp(inmp->mnt_vfc->vfc_name, - outmp->mnt_vfc->vfc_name) == 0) - error = VOP_COPY_FILE_RANGE(invp, inoffp, outvp, outoffp, - lenp, flags, incred, outcred, fsize_td); - else - error = vn_generic_copy_file_range(invp, inoffp, outvp, - outoffp, lenp, flags, incred, outcred, fsize_td); + error = VOP_COPY_FILE_RANGE(invp, inoffp, outvp, outoffp, + lenp, flags, incred, outcred, fsize_td); vfs_unbusy(outmp); if (inmp != outmp) vfs_unbusy(inmp);