From owner-svn-src-projects@freebsd.org Wed Oct 23 01:29:10 2019 Return-Path: Delivered-To: svn-src-projects@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 68EB016A733 for ; Wed, 23 Oct 2019 01:29:10 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46yXpZ27hrz4V5V; Wed, 23 Oct 2019 01:29:10 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 28C591D046; Wed, 23 Oct 2019 01:29:10 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x9N1TASh086463; Wed, 23 Oct 2019 01:29:10 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x9N1T9sF086461; Wed, 23 Oct 2019 01:29:09 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <201910230129.x9N1T9sF086461@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Wed, 23 Oct 2019 01:29:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r353910 - projects/nfsv42/sys/fs/nfsclient X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: projects/nfsv42/sys/fs/nfsclient X-SVN-Commit-Revision: 353910 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Oct 2019 01:29:10 -0000 Author: rmacklem Date: Wed Oct 23 01:29:09 2019 New Revision: 353910 URL: https://svnweb.freebsd.org/changeset/base/353910 Log: Add a flag for Advise not supported and fix Copy for length == 0. When an NFSv4.2 reports that the Advise operation is not supported, note that so that no more Advise operations will be attempted for the mount. For Copy where the NFSv4.2 server replies a copied length == 0, fix the client so that it recognizes this as "at EOF". This will not normally happen, since the client clips the requested copy length at EOF, however if another client truncates the file, this could happen for a Linux style NFSv4.2 server. Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c projects/nfsv42/sys/fs/nfsclient/nfsmount.h Modified: projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c ============================================================================== --- projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Wed Oct 23 01:11:25 2019 (r353909) +++ projects/nfsv42/sys/fs/nfsclient/nfs_clvnops.c Wed Oct 23 01:29:09 2019 (r353910) @@ -3475,12 +3475,21 @@ nfs_advise(struct vop_advise_args *ap) else len = ap->a_end - ap->a_start + 1; nmp = VFSTONFS(ap->a_vp->v_mount); + mtx_lock(&nmp->nm_mtx); if (!NFSHASNFSV4(nmp) || nmp->nm_minorvers < NFSV42_MINORVERSION || (NFSHASPNFS(nmp) && (nmp->nm_privflag & NFSMNTP_IOADVISETHRUMDS) == - 0)) + 0) || (nmp->nm_privflag & NFSMNTP_NOADVISE) != 0) { + mtx_unlock(&nmp->nm_mtx); return (0); - nfsrpc_advise(ap->a_vp, ap->a_start, len, ap->a_advice, + } + mtx_unlock(&nmp->nm_mtx); + error = nfsrpc_advise(ap->a_vp, ap->a_start, len, ap->a_advice, td->td_ucred, td); + if (error == NFSERR_NOTSUPP) { + mtx_lock(&nmp->nm_mtx); + nmp->nm_privflag |= NFSMNTP_NOADVISE; + mtx_unlock(&nmp->nm_mtx); + } return (0); } @@ -3533,10 +3542,11 @@ nfs_copy_file_range(struct vop_copy_file_range_args *a struct vnode *outvp = ap->a_outvp; struct mount *mp; struct nfsvattr innfsva, outnfsva; + struct vattr *vap; struct uio io; struct nfsmount *nmp; - size_t len, len2; - int error, inattrflag, outattrflag, ret; + size_t len, len2, copiedlen; + int error, inattrflag, outattrflag, ret, ret2; off_t inoff, outoff; bool consecutive, must_commit, tryoutcred; @@ -3610,6 +3620,24 @@ nfs_copy_file_range(struct vop_copy_file_range_args *a outoff = *ap->a_outoffp; tryoutcred = true; must_commit = false; + if (error == 0) { + vap = &VTONFS(invp)->n_vattr.na_vattr; + error = VOP_GETATTR(invp, vap, ap->a_incred); + if (error == 0) { + /* + * Clip "len" at va_size so that RFC compliant servers + * will not reply NFSERR_INVAL. + * Setting "len == 0" for the RPC would be preferred, + * but some Linux servers do not support that, + */ + if (inoff >= vap->va_size) + *ap->a_lenp = len = 0; + else if (inoff + len > vap->va_size) + *ap->a_lenp = len = vap->va_size - inoff; + } else + error = 0; + } + copiedlen = 0; while (len > 0 && error == 0) { inattrflag = outattrflag = 0; len2 = len; @@ -3623,27 +3651,12 @@ nfs_copy_file_range(struct vop_copy_file_range_args *a outvp, ap->a_outoffp, &len2, ap->a_flags, &inattrflag, &innfsva, &outattrflag, &outnfsva, ap->a_incred, consecutive, &must_commit); - if (inattrflag != 0) { + if (inattrflag != 0) ret = nfscl_loadattrcache(&invp, &innfsva, NULL, NULL, 0, 1); - if (error == 0 && ret != 0) - error = ret; - } - if (outattrflag != 0) { - ret = nfscl_loadattrcache(&outvp, &outnfsva, NULL, NULL, - 1, 1); - if (error == 0 && ret != 0) - error = ret; - } - if (error == 0 && len2 == 0) { - /* - * Some Linux NFSv4.2 servers can reply NFS_OK, but - * with a copied length (wr_count) == 0 when the - * offset + len is past EOF. (RFC-7862 requires a - * reply of NFS4ERR_INVAL for this case.) - */ - error = NFSERR_INVAL; - } + if (outattrflag != 0) + ret2 = nfscl_loadattrcache(&outvp, &outnfsva, NULL, + NULL, 1, 1); if (error == 0) { if (consecutive == false) { if (len2 == len) { @@ -3654,10 +3667,24 @@ nfs_copy_file_range(struct vop_copy_file_range_args *a } else error = NFSERR_OFFLOADNOREQS; } - len -= len2; + /* + * If the Copy returns a length == 0, it hit the + * EOF on the input file. + */ + if (len2 == 0) { + *ap->a_lenp = copiedlen; + len = 0; + } else { + len -= len2; + copiedlen += len2; + } if (len == 0 && must_commit && error == 0) error = ncl_commit(outvp, outoff, *ap->a_lenp, ap->a_outcred, curthread); + if (error == 0 && ret != 0) + error = ret; + if (error == 0 && ret2 != 0) + error = ret2; } else if (error == NFSERR_OFFLOADNOREQS && consecutive) { /* * Try consecutive == false, which is ok only if all Modified: projects/nfsv42/sys/fs/nfsclient/nfsmount.h ============================================================================== --- projects/nfsv42/sys/fs/nfsclient/nfsmount.h Wed Oct 23 01:11:25 2019 (r353909) +++ projects/nfsv42/sys/fs/nfsclient/nfsmount.h Wed Oct 23 01:29:09 2019 (r353910) @@ -111,6 +111,7 @@ struct nfsmount { #define NFSMNTP_SEEK 0x00000020 #define NFSMNTP_SEEKTESTED 0x00000040 #define NFSMNTP_NOXATTR 0x00000080 +#define NFSMNTP_NOADVISE 0x00000100 #define NFSMNT_DIRPATH(m) (&((m)->nm_name[(m)->nm_krbnamelen + 1])) #define NFSMNT_SRVKRBNAME(m) \