diff --git a/share/man/man9/VOP_COPY_FILE_RANGE.9 b/share/man/man9/VOP_COPY_FILE_RANGE.9 --- a/share/man/man9/VOP_COPY_FILE_RANGE.9 +++ b/share/man/man9/VOP_COPY_FILE_RANGE.9 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 30, 2020 +.Dd February 27, 2023 .Dt VOP_COPY_FILE_RANGE 9 .Os .Sh NAME @@ -138,7 +138,14 @@ Corrupted data was detected while reading/writing the files. .It Bq Er ENOSPC The file system is full. +.It Bq Er EOPNOTSUPP +The file system was not able to perform the operation, but it should be still +possible to perform generic copy. +.It Bq Er EXDEV +The file system was not able to perform the operation, but it should be still +possible to perform generic copy. .El .Sh SEE ALSO +.Xr copy_file_range 2 , .Xr vn_rdwr 9 , .Xr vnode 9 diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -847,16 +847,16 @@ int err; if (mp != vnode_mount(outvp)) - goto fallback; + return (EOPNOTSUPP); if (incred->cr_uid != outcred->cr_uid) - goto fallback; + return (EOPNOTSUPP); if (incred->cr_groups[0] != outcred->cr_groups[0]) - goto fallback; + return (EOPNOTSUPP); if (fsess_not_impl(mp, FUSE_COPY_FILE_RANGE)) - goto fallback; + return (EOPNOTSUPP); if (ap->a_fsizetd == NULL) td = curthread; @@ -941,10 +941,7 @@ if (err == ENOSYS) { fsess_set_notimpl(mp, FUSE_COPY_FILE_RANGE); -fallback: - err = 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); + err = EOPNOTSUPP; } /* diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -3897,11 +3897,8 @@ bool consecutive, must_commit, tryoutcred; /* NFSv4.2 Copy is not permitted for infile == outfile. */ - if (invp == outvp) { -generic_copy: - return (vn_generic_copy_file_range(invp, ap->a_inoffp, - outvp, ap->a_outoffp, ap->a_lenp, ap->a_flags, - ap->a_incred, ap->a_outcred, ap->a_fsizetd)); + if (invp == outvp || invp->v_mount != outvp->v_mount) { + return (EOPNOTSUPP); } /* Lock both vnodes, avoiding risk of deadlock. */ @@ -3942,7 +3939,7 @@ VOP_UNLOCK(outvp); if (mp != NULL) vn_finished_write(mp); - goto generic_copy; + return (EOPNOTSUPP); } mtx_unlock(&nmp->nm_mtx); diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -1465,12 +1465,8 @@ static int vop_stdcopy_file_range(struct vop_copy_file_range_args *ap) { - int error; - 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); + return (EOPNOTSUPP); } int diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -3074,12 +3074,16 @@ * which can handle copies across multiple file systems. */ *lenp = len; - if (invp->v_mount == outvp->v_mount) + if (invp->v_mount->mnt_vfc == outvp->v_mount->mnt_vfc) { error = VOP_COPY_FILE_RANGE(invp, inoffp, outvp, outoffp, lenp, flags, incred, outcred, fsize_td); - else + } else { + error = EOPNOTSUPP; + } + if (error == EOPNOTSUPP || error == EXDEV) { error = vn_generic_copy_file_range(invp, inoffp, outvp, outoffp, lenp, flags, incred, outcred, fsize_td); + } out: return (error); }