From owner-svn-src-all@freebsd.org Fri Jul 24 23:17:11 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 009FB3768EF; Fri, 24 Jul 2020 23:17:11 +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 4BD4pt63T1z4Pl7; Fri, 24 Jul 2020 23:17: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 B30BA12513; Fri, 24 Jul 2020 23:17: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 06ONHAuB009499; Fri, 24 Jul 2020 23:17:10 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 06ONHAd7009496; Fri, 24 Jul 2020 23:17:10 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202007242317.06ONHAd7009496@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Fri, 24 Jul 2020 23:17:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r363499 - in head/sys/fs: nfs nfsclient X-SVN-Group: head X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in head/sys/fs: nfs nfsclient X-SVN-Commit-Revision: 363499 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: Fri, 24 Jul 2020 23:17:11 -0000 Author: rmacklem Date: Fri Jul 24 23:17:09 2020 New Revision: 363499 URL: https://svnweb.freebsd.org/changeset/base/363499 Log: Add support for ext_pgs mbufs to nfsm_uiombuflist() and nfsm_split(). This patch uses a slightly different algorithm for nfsm_uiombuflist() for the non-ext_pgs case, where a variable called "mcp" is maintained, pointing to the current location that mbuf data can be filled into. This avoids use of mtod(mp, char *) + mp->m_len to calculate the location, since this does not work for ext_pgs mbufs and I think it makes the algorithm more readable. This change should not result in semantic changes for the non-ext_pgs case. The patch also deletes come unneeded code. It also adds support for anonymous page ext_pgs mbufs to nfsm_split(). 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. At this time for this case, use of ext_pgs mbufs cannot be enabled, since ktls_encrypt() replaces the unencrypted data with encrypted data in place. Until such time as this can be enabled, there should be no semantic change. Also, note that this code is only used by the NFS client for a mirrored pNFS server. Modified: head/sys/fs/nfs/nfs_var.h head/sys/fs/nfsclient/nfs_clcomsubs.c head/sys/fs/nfsclient/nfs_clrpcops.c Modified: head/sys/fs/nfs/nfs_var.h ============================================================================== --- head/sys/fs/nfs/nfs_var.h Fri Jul 24 23:15:42 2020 (r363498) +++ head/sys/fs/nfs/nfs_var.h Fri Jul 24 23:17:09 2020 (r363499) @@ -365,7 +365,7 @@ struct mbuf *nfsm_add_ext_pgs(struct mbuf *, int, int /* nfs_clcomsubs.c */ void nfsm_uiombuf(struct nfsrv_descript *, struct uio *, int); -struct mbuf *nfsm_uiombuflist(struct uio *, int, struct mbuf **, char **); +struct mbuf *nfsm_uiombuflist(struct uio *, int, u_int); nfsuint64 *nfscl_getcookie(struct nfsnode *, off_t off, int); u_int8_t *nfscl_getmyip(struct nfsmount *, struct in6_addr *, int *); int nfsm_getfh(struct nfsrv_descript *, struct nfsfh **); Modified: head/sys/fs/nfsclient/nfs_clcomsubs.c ============================================================================== --- head/sys/fs/nfsclient/nfs_clcomsubs.c Fri Jul 24 23:15:42 2020 (r363498) +++ head/sys/fs/nfsclient/nfs_clcomsubs.c Fri Jul 24 23:17:09 2020 (r363499) @@ -160,26 +160,33 @@ nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *ui * NOTE: can ony handle iovcnt == 1 */ struct mbuf * -nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp) +nfsm_uiombuflist(struct uio *uiop, int siz, u_int maxext) { char *uiocp; struct mbuf *mp, *mp2, *firstmp; - int i, left, mlen, rem, xfer; + int extpg, extpgsiz = 0, i, left, mlen, rem, xfer; int uiosiz, clflg; char *mcp, *tcp; KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1")); - if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */ - clflg = 1; - else - clflg = 0; - if (clflg != 0) - NFSMCLGET(mp, M_WAITOK); - else - NFSMGET(mp); + if (maxext > 0) { + mp = mb_alloc_ext_plus_pages(PAGE_SIZE, M_WAITOK); + mcp = (char *)(void *)PHYS_TO_DMAP(mp->m_epg_pa[0]); + extpg = 0; + extpgsiz = PAGE_SIZE; + } else { + if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */ + clflg = 1; + else + clflg = 0; + if (clflg != 0) + NFSMCLGET(mp, M_WAITOK); + else + NFSMGET(mp); + mcp = mtod(mp, char *); + } mp->m_len = 0; - mcp = mtod(mp, char *); firstmp = mp2 = mp; rem = NFSM_RNDUP(siz) - siz; while (siz > 0) { @@ -189,17 +196,28 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbu left = siz; uiosiz = left; while (left > 0) { - mlen = M_TRAILINGSPACE(mp); - if (mlen == 0) { - if (clflg) - NFSMCLGET(mp, M_WAITOK); - else - NFSMGET(mp); - mp->m_len = 0; - mcp = mtod(mp, char *); - mp2->m_next = mp; - mp2 = mp; + if (maxext > 0) + mlen = extpgsiz; + else mlen = M_TRAILINGSPACE(mp); + if (mlen == 0) { + if (maxext > 0) { + mp = nfsm_add_ext_pgs(mp, maxext, + &extpg); + mlen = extpgsiz = PAGE_SIZE; + mcp = (char *)(void *)PHYS_TO_DMAP( + mp->m_epg_pa[extpg]); + } else { + if (clflg) + NFSMCLGET(mp, M_WAITOK); + else + NFSMGET(mp); + mcp = mtod(mp, char *); + mlen = M_TRAILINGSPACE(mp); + mp->m_len = 0; + mp2->m_next = mp; + mp2 = mp; + } } xfer = (left > mlen) ? mlen : left; if (uiop->uio_segflg == UIO_SYSSPACE) @@ -208,6 +226,10 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbu copyin(uiocp, mcp, xfer); mp->m_len += xfer; mcp += xfer; + if (maxext > 0) { + extpgsiz -= xfer; + mp->m_epg_last_len += xfer; + } left -= xfer; uiocp += xfer; uiop->uio_offset += xfer; @@ -220,16 +242,15 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbu siz -= uiosiz; } if (rem > 0) { - KASSERT(rem <= M_TRAILINGSPACE(mp), + KASSERT((mp->m_flags & M_EXTPG) != 0 || + rem <= M_TRAILINGSPACE(mp), ("nfsm_uiombuflist: no space for padding")); for (i = 0; i < rem; i++) *mcp++ = '\0'; mp->m_len += rem; + if (maxext > 0) + mp->m_epg_last_len += rem; } - if (cpp != NULL) - *cpp = mtod(mp, caddr_t) + mp->m_len; - if (mbp != NULL) - *mbp = mp; return (firstmp); } Modified: head/sys/fs/nfsclient/nfs_clrpcops.c ============================================================================== --- head/sys/fs/nfsclient/nfs_clrpcops.c Fri Jul 24 23:15:42 2020 (r363498) +++ head/sys/fs/nfsclient/nfs_clrpcops.c Fri Jul 24 23:17:09 2020 (r363499) @@ -5862,7 +5862,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode uiop->uio_iov->iov_base; iovlen = uiop->uio_iov->iov_len; m = nfsm_uiombuflist(uiop, len, - NULL, NULL); + 0); } tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP, M_WAITOK | @@ -6545,12 +6545,6 @@ nfsrpc_writedsmir(vnode_t vp, int *iomode, int *must_c if (len > 0) { /* Put data in mbuf chain. */ nd->nd_mb->m_next = m; - /* Set nd_mb and nd_bpos to end of data. */ - while (m->m_next != NULL) - m = m->m_next; - nd->nd_mb = m; - nd->nd_bpos = mtod(m, char *) + m->m_len; - NFSCL_DEBUG(4, "nfsrpc_writedsmir: lastmb len=%d\n", m->m_len); } nrp = dsp->nfsclds_sockp; if (nrp == NULL) @@ -8625,8 +8619,97 @@ nfsmout: static struct mbuf * nfsm_split(struct mbuf *mp, uint64_t xfer) { - struct mbuf *m; + struct mbuf *m, *m2; + vm_page_t pg; + int i, j, left, pgno, plen, trim; + char *cp, *cp2; - m = m_split(mp, xfer, M_WAITOK); - return (m); + if ((mp->m_flags & M_EXTPG) == 0) { + m = m_split(mp, xfer, M_WAITOK); + return (m); + } + + /* Find the correct mbuf to split at. */ + for (m = mp; m != NULL && xfer > m->m_len; m = m->m_next) + xfer -= m->m_len; + if (m == NULL) + return (NULL); + + /* If xfer == m->m_len, we can just split the mbuf list. */ + if (xfer == m->m_len) { + m2 = m->m_next; + m->m_next = NULL; + return (m2); + } + + /* Find the page to split at. */ + pgno = 0; + left = xfer; + do { + if (pgno == 0) + plen = m_epg_pagelen(m, 0, m->m_epg_1st_off); + else + plen = m_epg_pagelen(m, pgno, 0); + if (left <= plen) + break; + left -= plen; + pgno++; + } while (pgno < m->m_epg_npgs); + if (pgno == m->m_epg_npgs) + panic("nfsm_split: eroneous ext_pgs mbuf"); + + m2 = mb_alloc_ext_pgs(M_WAITOK, mb_free_mext_pgs); + m2->m_epg_flags |= EPG_FLAG_ANON; + + /* + * If left < plen, allocate a new page for the new mbuf + * and copy the data after left in the page to this new + * page. + */ + if (left < plen) { + do { + pg = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | + VM_ALLOC_NOOBJ | VM_ALLOC_NODUMP | + VM_ALLOC_WIRED); + if (pg == NULL) + vm_wait(NULL); + } while (pg == NULL); + m2->m_epg_pa[0] = VM_PAGE_TO_PHYS(pg); + m2->m_epg_npgs = 1; + + /* Copy the data after left to the new page. */ + trim = plen - left; + cp = (char *)(void *)PHYS_TO_DMAP(m->m_epg_pa[pgno]); + if (pgno == 0) + cp += m->m_epg_1st_off; + cp += left; + cp2 = (char *)(void *)PHYS_TO_DMAP(m2->m_epg_pa[0]); + if (pgno == m->m_epg_npgs - 1) + m2->m_epg_last_len = trim; + else { + cp2 += PAGE_SIZE - trim; + m2->m_epg_1st_off = PAGE_SIZE - trim; + m2->m_epg_last_len = m->m_epg_last_len; + } + memcpy(cp2, cp, trim); + m2->m_len = trim; + } else { + m2->m_len = 0; + m2->m_epg_last_len = m->m_epg_last_len; + } + + /* Move the pages beyond pgno to the new mbuf. */ + for (i = pgno + 1, j = m2->m_epg_npgs; i < m->m_epg_npgs; i++, j++) { + m2->m_epg_pa[j] = m->m_epg_pa[i]; + /* Never moves page 0. */ + m2->m_len += m_epg_pagelen(m, i, 0); + } + m2->m_epg_npgs = j; + m->m_epg_npgs = pgno + 1; + m->m_epg_last_len = left; + m->m_len = xfer; + + m2->m_next = m->m_next; + m->m_next = NULL; + return (m2); }