The branch main has been updated by kib:

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

commit ab17854f974b5671b09139079d98e2068802064b
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2022-09-26 18:10:47 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2022-09-27 20:00:51 +0000

    nfsclient: access v_mount only after the vnode is locked
    
    and we checked that it is not reclaimed.
    
    Reviewed by:    markj, rmacklem
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D36722
---
 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 4c6a3b527049..f013b13b0cbe 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -3894,19 +3894,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 {
@@ -3933,6 +3927,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?
         */
@@ -3959,6 +3970,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)

Reply via email to