git: aa4d15bb8e7a - stable/13 - nfsclient: access v_mount only after the vnode is locked

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Tue, 04 Oct 2022 00:43:22 UTC
The branch stable/13 has been updated by kib:

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

commit aa4d15bb8e7a8310cf185c71dfa6ccdc93a9136f
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-09-26 18:10:47 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-10-04 00:42:56 +0000

    nfsclient: access v_mount only after the vnode is locked
    
    (cherry picked from commit ab17854f974b5671b09139079d98e2068802064b)
---
 sys/fs/nfsclient/nfs_clvnops.c | 34 +++++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index a92875aae6ed..569327b14e41 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -3805,19 +3805,13 @@ nfs_copy_file_range(struct vop_copy_file_range_args *ap)
 	off_t inoff, outoff;
 	bool consecutive, must_commit, tryoutcred;
 
-	ret = ret2 = 0;
-	nmp = VFSTONFS(invp->v_mount);
-	mtx_lock(&nmp->nm_mtx);
 	/* NFSv4.2 Copy is not permitted for infile == outfile. */
-	if (!NFSHASNFSV4(nmp) || nmp->nm_minorvers < NFSV42_MINORVERSION ||
-	    (nmp->nm_privflag & NFSMNTP_NOCOPY) != 0 || invp == outvp) {
-		mtx_unlock(&nmp->nm_mtx);
-		error = vn_generic_copy_file_range(ap->a_invp, ap->a_inoffp,
-		    ap->a_outvp, ap->a_outoffp, ap->a_lenp, ap->a_flags,
-		    ap->a_incred, ap->a_outcred, ap->a_fsizetd);
-		return (error);
+	if (invp == outvp) {
+generic_copy:
+		return (vn_generic_copy_file_range(invp, ap->a_inoffp,
+		    outvp, ap->a_outoffp, ap->a_lenp, ap->a_flags,
+		    ap->a_incred, ap->a_outcred, ap->a_fsizetd));
 	}
-	mtx_unlock(&nmp->nm_mtx);
 
 	/* Lock both vnodes, avoiding risk of deadlock. */
 	do {
@@ -3844,6 +3838,23 @@ nfs_copy_file_range(struct vop_copy_file_range_args *ap)
 	if (error != 0)
 		return (error);
 
+	/*
+	 * More reasons to avoid nfs copy: not NFSv4.2, or explicitly
+	 * disabled.
+	 */
+	nmp = VFSTONFS(invp->v_mount);
+	mtx_lock(&nmp->nm_mtx);
+	if (!NFSHASNFSV4(nmp) || nmp->nm_minorvers < NFSV42_MINORVERSION ||
+	    (nmp->nm_privflag & NFSMNTP_NOCOPY) != 0) {
+		mtx_unlock(&nmp->nm_mtx);
+		VOP_UNLOCK(invp);
+		VOP_UNLOCK(outvp);
+		if (mp != NULL)
+			vn_finished_write(mp);
+		goto generic_copy;
+	}
+	mtx_unlock(&nmp->nm_mtx);
+
 	/*
 	 * Do the vn_rlimit_fsize() check.  Should this be above the VOP layer?
 	 */
@@ -3865,6 +3876,7 @@ nfs_copy_file_range(struct vop_copy_file_range_args *ap)
 		error = ncl_flush(outvp, MNT_WAIT, curthread, 1, 0);
 
 	/* Do the actual NFSv4.2 RPC. */
+	ret = ret2 = 0;
 	len = *ap->a_lenp;
 	mtx_lock(&nmp->nm_mtx);
 	if ((nmp->nm_privflag & NFSMNTP_NOCONSECUTIVE) == 0)