diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -1131,6 +1131,56 @@ return (res); } +static int +null_copy_file_range(struct vop_copy_file_range_args *ap) +{ + struct vnode *inlvp, *outlvp; + struct mount *inlmp, *outlmp; + int error; + + if (vn_lock(ap->a_invp, LK_SHARED) == 0) { + inlvp = NULLVPTOLOWERVP(ap->a_invp); + vref(inlvp); + VOP_UNLOCK(ap->a_invp); + } else { + error = EBADF; + goto outi; + } + + if (vn_lock(ap->a_outvp, LK_SHARED) == 0) { + outlvp = NULLVPTOLOWERVP(ap->a_outvp); + vref(outlvp); + VOP_UNLOCK(ap->a_outvp); + } else { + error = EBADF; + goto outo; + } + + inlmp = inlvp->v_mount; + outlmp = outlvp->v_mount; + if (inlmp == NULL || outlmp == NULL) { + error = EBADF; + goto out; + } + + if (inlmp == outlmp || strcmp(inlmp->mnt_vfc->vfc_name, + outlmp->mnt_vfc->vfc_name) == 0) + 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); + else + error = vn_generic_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); + +out: + vrele(outlvp); +outo: + vrele(inlvp); +outi: + return (error); +} + /* * Global vfs data structures */ @@ -1163,5 +1213,6 @@ .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);