The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=23210f538a008788b2e16b9eddafa4f598a21663

commit 23210f538a008788b2e16b9eddafa4f598a21663
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2023-11-12 18:37:29 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2023-11-13 22:26:34 +0000

    vn_copy_file_range(): busy both in and out mp around call to 
VOP_COPY_FILE_RANGE()
    
    This is required e.g. for nullfs to ensure liveness of the lower mount
    points.
    
    Reviewed by:    jah, rmacklem, Olivier Certner <olce.free...@certner.fr>
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D42554
---
 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 e2227537dde1..27ce5401f15f 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -3078,6 +3078,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 vnodes are for the same file system type, call
@@ -3092,6 +3115,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);
 }

Reply via email to