Date: Wed, 23 Oct 2019 01:29:09 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r353910 - projects/nfsv42/sys/fs/nfsclient Message-ID: <201910230129.x9N1T9sF086461@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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) \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201910230129.x9N1T9sF086461>