git: a9bc8637690c - main - vn_copy_file_range(): find write vnodes on which to call the VOP
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 28 Nov 2023 17:33:23 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=a9bc8637690ce29496650a41d3c25e225ed22e3d commit a9bc8637690ce29496650a41d3c25e225ed22e3d Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2023-11-18 08:57:44 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2023-11-28 17:32:53 +0000 vn_copy_file_range(): find write vnodes on which to call the VOP Reviewed by: markj, Olivier Certner <olce.freebsd@certner.fr> Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D42603 --- sys/kern/vfs_vnops.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index e90330b08cbc..29114f795f5e 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -3070,10 +3070,12 @@ vn_copy_file_range(struct vnode *invp, off_t *inoffp, struct vnode *outvp, struct ucred *outcred, struct thread *fsize_td) { struct mount *inmp, *outmp; + struct vnode *invpl, *outvpl; int error; size_t len; uint64_t uval; + invpl = outvpl = NULL; len = *lenp; *lenp = 0; /* For error returns. */ error = 0; @@ -3099,17 +3101,22 @@ vn_copy_file_range(struct vnode *invp, off_t *inoffp, struct vnode *outvp, if (len == 0) goto out; - inmp = invp->v_mount; - outmp = outvp->v_mount; - if (inmp == NULL || outmp == NULL) { - error = EBADF; + error = VOP_GETLOWVNODE(invp, &invpl, FREAD); + if (error != 0) goto out; - } + error = VOP_GETLOWVNODE(outvp, &outvpl, FWRITE); + if (error != 0) + goto out1; + + inmp = invpl->v_mount; + outmp = outvpl->v_mount; + if (inmp == NULL || outmp == NULL) + goto out2; for (;;) { error = vfs_busy(inmp, 0); if (error != 0) - goto out; + goto out2; if (inmp == outmp) break; error = vfs_busy(outmp, MBF_NOWAIT); @@ -3120,7 +3127,7 @@ vn_copy_file_range(struct vnode *invp, off_t *inoffp, struct vnode *outvp, vfs_unbusy(outmp); continue; } - goto out; + goto out2; } break; } @@ -3131,16 +3138,21 @@ 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, + if (inmp == outmp || inmp->mnt_vfc == outmp->mnt_vfc) + error = VOP_COPY_FILE_RANGE(invpl, inoffp, outvpl, outoffp, lenp, flags, incred, outcred, fsize_td); else - error = vn_generic_copy_file_range(invp, inoffp, outvp, + error = vn_generic_copy_file_range(invpl, inoffp, outvpl, outoffp, lenp, flags, incred, outcred, fsize_td); vfs_unbusy(outmp); if (inmp != outmp) vfs_unbusy(inmp); +out2: + if (outvpl != NULL) + vrele(outvpl); +out1: + if (invpl != NULL) + vrele(invpl); out: return (error); }