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 @@ -861,7 +861,7 @@ pid_t pid; int err; - if (mp != vnode_mount(outvp)) + if (mp == NULL || mp != vnode_mount(outvp)) goto fallback; if (incred->cr_uid != outcred->cr_uid) @@ -870,6 +870,7 @@ if (incred->cr_groups[0] != outcred->cr_groups[0]) goto fallback; + /* Caller busied mp, mnt_data can be safely accessed. */ if (fsess_not_impl(mp, FUSE_COPY_FILE_RANGE)) goto fallback; @@ -879,23 +880,7 @@ td = ap->a_fsizetd; pid = td->td_proc->p_pid; - /* Lock both vnodes, avoiding risk of deadlock. */ - do { - err = vn_lock(outvp, LK_EXCLUSIVE); - if (invp == outvp) - break; - if (err == 0) { - err = vn_lock(invp, LK_SHARED | LK_NOWAIT); - if (err == 0) - break; - VOP_UNLOCK(outvp); - err = vn_lock(invp, LK_SHARED); - if (err == 0) - VOP_UNLOCK(invp); - } - } while (err == 0); - if (err != 0) - return (err); + vn_lock_pair(invp, false, LK_SHARED, outvp, false, LK_EXCLUSIVE); err = fuse_filehandle_getrw(invp, FREAD, &infufh, incred, pid); if (err)