From owner-svn-src-all@freebsd.org Sun Jul 26 02:42:10 2020 Return-Path: Delivered-To: svn-src-all@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 C81BA37A00A; Sun, 26 Jul 2020 02:42: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) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 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 4BDnJy4ycZz40LS; Sun, 26 Jul 2020 02:42: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 8DF84257DF; Sun, 26 Jul 2020 02:42: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 06Q2gA68046680; Sun, 26 Jul 2020 02:42:10 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 06Q2g9fA046676; Sun, 26 Jul 2020 02:42:09 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202007260242.06Q2g9fA046676@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Sun, 26 Jul 2020 02:42:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r363541 - in head/sys/fs: nfs nfsserver X-SVN-Group: head X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in head/sys/fs: nfs nfsserver X-SVN-Commit-Revision: 363541 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 26 Jul 2020 02:42:10 -0000 Author: rmacklem Date: Sun Jul 26 02:42:09 2020 New Revision: 363541 URL: https://svnweb.freebsd.org/changeset/base/363541 Log: Add support for ext_pgs mbufs to nfsrv_adj(). This patch uses a slightly different algorithm for nfsrv_adj() since ext_pgs mbuf lists are not permitted to have m_len == 0 mbufs. As such, the code now frees mbufs after the adjustment in the list instead of setting their m_len field to 0. Since mbuf(s) may be trimmed off the tail of the list, the function now returns a pointer to the last mbuf in the list. This saves the caller from needing to use m_last() to find the last mbuf. It also implies that it might return a nul list, which required a check for that in nfsrvd_readlink(). This is another in the series of commits that add support to the NFS client and server for building RPC messages in ext_pgs mbufs with anonymous pages. This is useful so that the entire mbuf list does not need to be copied before calling sosend() when NFS over TLS is enabled. Use of ext_pgs mbufs will not be enabled until the kernel RPC is updated to handle TLS. Modified: head/sys/fs/nfs/nfs_var.h head/sys/fs/nfsserver/nfs_nfsdport.c head/sys/fs/nfsserver/nfs_nfsdserv.c head/sys/fs/nfsserver/nfs_nfsdsubs.c Modified: head/sys/fs/nfs/nfs_var.h ============================================================================== --- head/sys/fs/nfs/nfs_var.h Sun Jul 26 01:45:26 2020 (r363540) +++ head/sys/fs/nfs/nfs_var.h Sun Jul 26 02:42:09 2020 (r363541) @@ -391,7 +391,7 @@ int nfsv4_fillattr(struct nfsrv_descript *, struct mou struct vattr *, fhandle_t *, int, nfsattrbit_t *, struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t, struct statfs *); void nfsrv_fillattr(struct nfsrv_descript *, struct nfsvattr *); -void nfsrv_adj(struct mbuf *, int, int); +struct mbuf *nfsrv_adj(struct mbuf *, int, int); void nfsrv_postopattr(struct nfsrv_descript *, int, struct nfsvattr *); int nfsd_errmap(struct nfsrv_descript *); void nfsv4_uidtostr(uid_t, u_char **, int *); Modified: head/sys/fs/nfsserver/nfs_nfsdport.c ============================================================================== --- head/sys/fs/nfsserver/nfs_nfsdport.c Sun Jul 26 01:45:26 2020 (r363540) +++ head/sys/fs/nfsserver/nfs_nfsdport.c Sun Jul 26 02:42:09 2020 (r363541) @@ -757,7 +757,12 @@ nfsvno_readlink(struct vnode *vp, struct ucred *cred, if (uiop->uio_resid > 0) { len -= uiop->uio_resid; tlen = NFSM_RNDUP(len); - nfsrv_adj(mp3, NFS_MAXPATHLEN - tlen, tlen - len); + if (tlen == 0) { + m_freem(mp3); + mp3 = mp = NULL; + } else if (tlen != NFS_MAXPATHLEN || tlen != len) + mp = nfsrv_adj(mp3, NFS_MAXPATHLEN - tlen, + tlen - len); } *lenp = len; *mpp = mp3; @@ -872,9 +877,9 @@ nfsvno_read(struct vnode *vp, off_t off, int cnt, stru tlen = NFSM_RNDUP(cnt); if (tlen == 0) { m_freem(m3); - m3 = NULL; + m3 = m = NULL; } else if (len != tlen || tlen != cnt) - nfsrv_adj(m3, len - tlen, tlen - cnt); + m = nfsrv_adj(m3, len - tlen, tlen - cnt); *mpp = m3; *mpendp = m; @@ -6247,7 +6252,11 @@ nfsvno_getxattr(struct vnode *vp, char *name, uint32_t tlen = NFSM_RNDUP(len); if (alen != tlen) printf("nfsvno_getxattr: weird size read\n"); - nfsrv_adj(m, alen - tlen, tlen - len); + if (tlen == 0) { + m_freem(m); + m = m2 = NULL; + } else if (alen != tlen || tlen != len) + m2 = nfsrv_adj(m, alen - tlen, tlen - len); } *lenp = len; *mpp = m; Modified: head/sys/fs/nfsserver/nfs_nfsdserv.c ============================================================================== --- head/sys/fs/nfsserver/nfs_nfsdserv.c Sun Jul 26 01:45:26 2020 (r363540) +++ head/sys/fs/nfsserver/nfs_nfsdserv.c Sun Jul 26 02:42:09 2020 (r363541) @@ -690,9 +690,11 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused in goto out; NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); *tl = txdr_unsigned(len); - nd->nd_mb->m_next = mp; - nd->nd_mb = mpend; - nd->nd_bpos = mtod(mpend, caddr_t) + mpend->m_len; + if (mp != NULL) { + nd->nd_mb->m_next = mp; + nd->nd_mb = mpend; + nd->nd_bpos = mtod(mpend, caddr_t) + mpend->m_len; + } out: NFSEXITCODE2(0, nd); Modified: head/sys/fs/nfsserver/nfs_nfsdsubs.c ============================================================================== --- head/sys/fs/nfsserver/nfs_nfsdsubs.c Sun Jul 26 01:45:26 2020 (r363540) +++ head/sys/fs/nfsserver/nfs_nfsdsubs.c Sun Jul 26 02:42:09 2020 (r363541) @@ -1268,62 +1268,100 @@ static short *nfsrv_v4errmap[] = { }; /* - * A fiddled version of m_adj() that ensures null fill to a long - * boundary and only trims off the back end + * Trim tlen bytes off the end of the mbuf list and then ensure + * the end of the last mbuf is nul filled to a long boundary, + * as indicated by the value of "nul". + * Return the last mbuf in the updated list and free and mbufs + * that follow it in the original list. + * This is somewhat different than the old nfsrv_adj() with + * support for ext_pgs mbufs. It frees the remaining mbufs + * instead of setting them 0 length, since lists of ext_pgs + * mbufs are all expected to be non-empty. */ -void +struct mbuf * nfsrv_adj(struct mbuf *mp, int len, int nul) { - struct mbuf *m; - int count, i; + struct mbuf *m, *m2; + vm_page_t pg; + int i, lastlen, pgno, plen, tlen, trim; + uint16_t off; char *cp; /* - * Trim from tail. Scan the mbuf chain, - * calculating its length and finding the last mbuf. - * If the adjustment only affects this mbuf, then just - * adjust and return. Otherwise, rescan and truncate - * after the remaining size. + * Find the last mbuf after adjustment and + * how much it needs to be adjusted by. */ - count = 0; + tlen = 0; m = mp; for (;;) { - count += m->m_len; + tlen += m->m_len; if (m->m_next == NULL) break; m = m->m_next; } - if (m->m_len > len) { - m->m_len -= len; - if (nul > 0) { - cp = mtod(m, caddr_t) + m->m_len - nul; - for (i = 0; i < nul; i++) - *cp++ = '\0'; + /* m is now the last mbuf and tlen the total length. */ + + if (len >= m->m_len) { + /* Need to trim away the last mbuf(s). */ + i = tlen - len; + m = mp; + for (;;) { + if (m->m_len >= i) + break; + i -= m->m_len; + m = m->m_next; } - return; - } - count -= len; - if (count < 0) - count = 0; + lastlen = i; + } else + lastlen = m->m_len - len; + /* - * Correct length for chain is "count". - * Find the mbuf with last data, adjust its length, - * and toss data from remaining mbufs on chain. + * m is now the last mbuf after trimming and its length needs to + * be lastlen. + * Adjust the last mbuf and set cp to point to where nuls must be + * written. */ - for (m = mp; m; m = m->m_next) { - if (m->m_len >= count) { - m->m_len = count; - if (nul > 0) { - cp = mtod(m, caddr_t) + m->m_len - nul; - for (i = 0; i < nul; i++) - *cp++ = '\0'; + if ((m->m_flags & M_EXTPG) != 0) { + pgno = m->m_epg_npgs - 1; + off = (pgno == 0) ? m->m_epg_1st_off : 0; + plen = m_epg_pagelen(m, pgno, off); + if (m->m_len > lastlen) { + /* Trim this mbuf. */ + trim = m->m_len - lastlen; + while (trim >= plen) { + KASSERT(pgno > 0, + ("nfsrv_adj: freeing page 0")); + /* Free page. */ + pg = PHYS_TO_VM_PAGE(m->m_epg_pa[pgno]); + vm_page_unwire_noq(pg); + vm_page_free(pg); + trim -= plen; + m->m_epg_npgs--; + pgno--; + off = (pgno == 0) ? m->m_epg_1st_off : 0; + plen = m_epg_pagelen(m, pgno, off); } - break; + plen -= trim; + m->m_epg_last_len = plen; + m->m_len = lastlen; } - count -= m->m_len; + cp = (char *)(void *)PHYS_TO_DMAP(m->m_epg_pa[pgno]); + cp += off + plen - nul; + } else { + m->m_len = lastlen; + cp = mtod(m, char *) + m->m_len - nul; } - for (m = m->m_next; m; m = m->m_next) - m->m_len = 0; + + /* Write the nul bytes. */ + for (i = 0; i < nul; i++) + *cp++ = '\0'; + + /* Free up any mbufs past "m". */ + m2 = m->m_next; + m->m_next = NULL; + if (m2 != NULL) + m_freem(m2); + return (m); } /*