git: 11f0b96a9745 - stable/13 - vn_copy_file_range(): busy both in and out mp around call to VOP_COPY_FILE_RANGE()

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 20 Nov 2023 01:41:44 UTC
The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=11f0b96a974513628d4b8d2257d921fca4b9c5cf

commit 11f0b96a974513628d4b8d2257d921fca4b9c5cf
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-11-12 18:37:29 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-11-20 01:40:34 +0000

    vn_copy_file_range(): busy both in and out mp around call to VOP_COPY_FILE_RANGE()
    
    (cherry picked from commit 23210f538a008788b2e16b9eddafa4f598a21663)
---
 sys/kern/vfs_vnops.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 5194d708f250..7af4df16252c 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -3058,6 +3058,29 @@ vn_copy_file_range(struct vnode *invp, off_t *inoffp, struct vnode *outvp,
 
 	inmp = invp->v_mount;
 	outmp = outvp->v_mount;
+	if (inmp == NULL || outmp == NULL) {
+		error = EBADF;
+		goto out;
+	}
+
+	for (;;) {
+		error = vfs_busy(inmp, 0);
+		if (error != 0)
+			goto out;
+		if (inmp == outmp)
+			break;
+		error = vfs_busy(outmp, MBF_NOWAIT);
+		if (error != 0) {
+			vfs_unbusy(inmp);
+			error = vfs_busy(outmp, 0);
+			if (error == 0) {
+				vfs_unbusy(outmp);
+				continue;
+			}
+			goto out;
+		}
+		break;
+	}
 
 	/*
 	 * If the two vnode are for the same file system, call
@@ -3071,6 +3094,9 @@ vn_copy_file_range(struct vnode *invp, off_t *inoffp, struct vnode *outvp,
 	else
 		error = vn_generic_copy_file_range(invp, inoffp, outvp,
 		    outoffp, lenp, flags, incred, outcred, fsize_td);
+	vfs_unbusy(outmp);
+	if (inmp != outmp)
+		vfs_unbusy(inmp);
 out:
 	return (error);
 }