From owner-svn-src-projects@freebsd.org Fri Jul 24 02:19:01 2020 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 B1F4136BC6E for ; Fri, 24 Jul 2020 02:19:01 +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 4BCXv94WRGz4T04; Fri, 24 Jul 2020 02:19:01 +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 7EF00228EC; Fri, 24 Jul 2020 02:19:01 +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 06O2J1MG056916; Fri, 24 Jul 2020 02:19:01 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 06O2J14h056914; Fri, 24 Jul 2020 02:19:01 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202007240219.06O2J14h056914@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 02:19:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r363470 - in projects/nfs-over-tls/sys/fs: nfs nfsclient X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in projects/nfs-over-tls/sys/fs: nfs nfsclient X-SVN-Commit-Revision: 363470 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.33 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: Fri, 24 Jul 2020 02:19:01 -0000 Author: rmacklem Date: Fri Jul 24 02:19:00 2020 New Revision: 363470 URL: https://svnweb.freebsd.org/changeset/base/363470 Log: Update nfsm_uiombuflist() and nfscl_dofflayoutio() so that ext_pgs mbufs can be used. The use of ext_pgs mbufs is not yet enabled, since it requires changes to ktls_encrypt() so that the encrypted pages are not in the same mbuf list. Modified: projects/nfs-over-tls/sys/fs/nfs/nfs_var.h projects/nfs-over-tls/sys/fs/nfsclient/nfs_clcomsubs.c projects/nfs-over-tls/sys/fs/nfsclient/nfs_clrpcops.c Modified: projects/nfs-over-tls/sys/fs/nfs/nfs_var.h ============================================================================== --- projects/nfs-over-tls/sys/fs/nfs/nfs_var.h Fri Jul 24 01:25:57 2020 (r363469) +++ projects/nfs-over-tls/sys/fs/nfs/nfs_var.h Fri Jul 24 02:19:00 2020 (r363470) @@ -363,7 +363,7 @@ void nfsm_set(struct nfsrv_descript *, u_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: projects/nfs-over-tls/sys/fs/nfsclient/nfs_clcomsubs.c ============================================================================== --- projects/nfs-over-tls/sys/fs/nfsclient/nfs_clcomsubs.c Fri Jul 24 01:25:57 2020 (r363469) +++ projects/nfs-over-tls/sys/fs/nfsclient/nfs_clcomsubs.c Fri Jul 24 02:19:00 2020 (r363470) @@ -160,26 +160,35 @@ 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 xfer, left, mlen; + int extpg, extpgsiz = 0, i, left, mlen, rem, xfer; int uiosiz, clflg; - char *tcp; + 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; firstmp = mp2 = mp; + rem = NFSM_RNDUP(siz) - siz; while (siz > 0) { left = uiop->uio_iov->iov_len; uiocp = uiop->uio_iov->iov_base; @@ -187,25 +196,40 @@ 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; - 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) - NFSBCOPY(uiocp, mtod(mp, caddr_t) + - mp->m_len, xfer); + NFSBCOPY(uiocp, mcp, xfer); else - copyin(uiocp, mtod(mp, caddr_t) + - mp->m_len, xfer); + 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; @@ -217,10 +241,16 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbu uiop->uio_iov->iov_len -= uiosiz; siz -= uiosiz; } - if (cpp != NULL) - *cpp = mtod(mp, caddr_t) + mp->m_len; - if (mbp != NULL) - *mbp = mp; + if (rem > 0) { + 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; + } return (firstmp); } Modified: projects/nfs-over-tls/sys/fs/nfsclient/nfs_clrpcops.c ============================================================================== --- projects/nfs-over-tls/sys/fs/nfsclient/nfs_clrpcops.c Fri Jul 24 01:25:57 2020 (r363469) +++ projects/nfs-over-tls/sys/fs/nfsclient/nfs_clrpcops.c Fri Jul 24 02:19:00 2020 (r363470) @@ -160,7 +160,6 @@ static int nfscl_dofflayoutio(vnode_t, struct uio *, i nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *, struct nfsclflayout *, uint64_t, uint64_t, int, int, struct mbuf *, struct nfsclwritedsdorpc *, struct ucred *, NFSPROC_T *); -static struct mbuf *nfsm_copym(struct mbuf *, int, int); static int nfsrpc_readds(vnode_t, struct uio *, nfsv4stateid_t *, int *, struct nfsclds *, uint64_t, int, struct nfsfh *, int, int, int, struct ucred *, NFSPROC_T *); @@ -222,6 +221,7 @@ static int nfsrpc_copyrpc(vnode_t, off_t, vnode_t, off struct nfsvattr *, int *, bool, int *, struct ucred *, NFSPROC_T *); static int nfsrpc_seekrpc(vnode_t, off_t *, nfsv4stateid_t *, bool *, int, struct nfsvattr *, int *, struct ucred *); +static struct mbuf *nfsm_split(struct mbuf *, uint64_t); int nfs_pnfsio(task_fn_t *, void *); @@ -5759,7 +5759,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode struct nfscllayout *layp; struct nfscldevinfo *dip; struct nfsclflayout *rflp; - struct mbuf *m; + struct mbuf *m, *m2; struct nfsclwritedsdorpc *drpc, *tdrpc; nfsv4stateid_t stateid; struct ucred *newcred; @@ -5865,7 +5865,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 | @@ -5873,6 +5873,13 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode } } for (i = firstmirror; i < mirrorcnt && error == 0; i++){ + m2 = NULL; + if (m != NULL && i < mirrorcnt - 1) + m2 = m_copym(m, 0, M_COPYALL, M_WAITOK); + else { + m2 = m; + m = NULL; + } if ((layp->nfsly_flags & NFSLY_FLEXFILE) != 0) { dev = rflp->nfsfl_ffm[i].dev; dip = nfscl_getdevinfo(nmp->nm_clp, dev, @@ -5889,7 +5896,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode uiop, iomode, must_commit, &eof, &stateid, rwaccess, dip, layp, rflp, off, xfer, - i, docommit, m, tdrpc, + i, docommit, m2, tdrpc, newcred, p); else error = nfscl_doflayoutio(vp, @@ -5898,8 +5905,11 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode dip, layp, rflp, off, xfer, docommit, newcred, p); nfscl_reldevinfo(dip); - } else + } else { + if (m2 != NULL) + m_freem(m2); error = EIO; + } tdrpc++; } if (m != NULL) @@ -5965,38 +5975,6 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode } /* - * Make a copy of the mbuf chain and add an mbuf for null padding, as required. - */ -static struct mbuf * -nfsm_copym(struct mbuf *m, int off, int xfer) -{ - struct mbuf *m2, *m3, *m4; - uint32_t *tl; - int rem; - - m2 = m_copym(m, off, xfer, M_WAITOK); - rem = NFSM_RNDUP(xfer) - xfer; - if (rem > 0) { - /* - * The zero padding to a multiple of 4 bytes is required by - * the XDR. So that the mbufs copied by reference aren't - * modified, add an mbuf with the zero'd bytes to the list. - * rem will be a maximum of 3, so one zero'd uint32_t is - * sufficient. - */ - m3 = m2; - while (m3->m_next != NULL) - m3 = m3->m_next; - NFSMGET(m4); - tl = mtod(m4, uint32_t *); - *tl = 0; - m4->m_len = rem; - m3->m_next = m4; - } - return (m2); -} - -/* * Find a file layout that will handle the first bytes of the requested * range and return the information from it needed to the I/O operation. */ @@ -6151,17 +6129,17 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int * uint64_t len, int mirror, int docommit, struct mbuf *mp, struct nfsclwritedsdorpc *drpc, struct ucred *cred, NFSPROC_T *p) { - uint64_t transfer, xfer; - int error, rel_off; + uint64_t xfer; + int error; struct nfsnode *np; struct nfsfh *fhp; struct nfsclds **dspp; struct ucred *tcred; - struct mbuf *m; + struct mbuf *m, *m2; + uint32_t copylen; np = VTONFS(vp); error = 0; - rel_off = 0; NFSCL_DEBUG(4, "nfscl_dofflayoutio: off=%ju len=%ju\n", (uintmax_t)off, (uintmax_t)len); /* Loop around, doing I/O for each stripe unit. */ @@ -6179,14 +6157,31 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int * } else tcred = cred; if (rwflag == NFSV4OPEN_ACCESSREAD) - transfer = dp->nfsdi_rsize; - else - transfer = dp->nfsdi_wsize; + copylen = dp->nfsdi_rsize; + else { + copylen = dp->nfsdi_wsize; + if (len > copylen && mp != NULL) { + /* + * When a mirrored configuration needs to do + * multiple writes to each mirror, all writes + * except the last one must be a multiple of + * 4 bytes. This is required so that the XDR + * does not need padding. + * If possible, clip the size to an exact + * multiple of the mbuf length, so that the + * split will be on an mbuf boundary. + */ + copylen &= 0xfffffffc; + if (copylen > mp->m_len) + copylen = copylen / mp->m_len * + mp->m_len; + } + } NFSLOCKNODE(np); np->n_flag |= NDSCOMMIT; NFSUNLOCKNODE(np); - if (len > transfer && docommit == 0) - xfer = transfer; + if (len > copylen && docommit == 0) + xfer = copylen; else xfer = len; if (docommit != 0) { @@ -6247,31 +6242,41 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int * NFSUNLOCKCLSTATE(); } } else { - m = nfsm_copym(mp, rel_off, xfer); - NFSCL_DEBUG(4, "mcopy reloff=%d xfer=%jd\n", - rel_off, (uintmax_t)xfer); + m = mp; + if (xfer < len) { + /* The mbuf list must be split. */ + m2 = nfsm_split(mp, xfer); + if (m2 != NULL) + mp = m2; + else { + m_freem(mp); + error = EIO; + } + } + NFSCL_DEBUG(4, "mcopy len=%jd xfer=%jd\n", + (uintmax_t)len, (uintmax_t)xfer); /* - * Do the writes after the first loop iteration - * and the write for the last mirror via this + * Do last write to a mirrored DS with this * thread. - * This loop only iterates for small values - * of nfsdi_wsize, which may never occur in - * practice. However, the drpc is completely - * used by the first iteration and, as such, - * cannot be used after that. */ - if (mirror < flp->nfsfl_mirrorcnt - 1 && - rel_off == 0) - error = nfsio_writedsmir(vp, iomode, - must_commit, stateidp, *dspp, off, - xfer, fhp, m, dp->nfsdi_vers, - dp->nfsdi_minorvers, drpc, tcred, - p); - else - error = nfsrpc_writedsmir(vp, iomode, - must_commit, stateidp, *dspp, off, - xfer, fhp, m, dp->nfsdi_vers, - dp->nfsdi_minorvers, tcred, p); + if (error == 0) { + if (mirror < flp->nfsfl_mirrorcnt - 1) + error = nfsio_writedsmir(vp, + iomode, must_commit, + stateidp, *dspp, off, + xfer, fhp, m, + dp->nfsdi_vers, + dp->nfsdi_minorvers, drpc, + tcred, p); + else + error = nfsrpc_writedsmir(vp, + iomode, must_commit, + stateidp, *dspp, off, + xfer, fhp, m, + dp->nfsdi_vers, + dp->nfsdi_minorvers, tcred, + p); + } NFSCL_DEBUG(4, "nfsio_writedsmir=%d\n", error); if (error != 0 && error != EACCES && error != ESTALE) { @@ -6286,7 +6291,6 @@ nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int * if (error == 0) { len -= xfer; off += xfer; - rel_off += xfer; } if ((dp->nfsdi_flags & NFSDI_TIGHTCOUPLED) == 0) NFSFREECRED(tcred); @@ -6544,12 +6548,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) @@ -8626,3 +8624,103 @@ nfsmout: return (error); } +/* + * Split an mbuf list. For non-M_EXTPG mbufs, just use m_split(). + */ +static struct mbuf * +nfsm_split(struct mbuf *mp, uint64_t xfer) +{ + struct mbuf *m, *m2; + vm_page_t pg; + int i, j, left, pgno, plen, trim; + char *cp, *cp2; + + 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); +}