Date: Fri, 24 Jul 2020 23:17:10 +0000 (UTC) From: Rick Macklem <rmacklem@FreeBSD.org> 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 Message-ID: <202007242317.06ONHAd7009496@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007242317.06ONHAd7009496>