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);
}