From 3f9dac85cc8f2963026fdc2d5477acb607176a89 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 25 May 2021 16:59:18 -0700 Subject: [PATCH] Extend m_copyback() to support unmapped mbufs. Reviewed by: gallatin, markj Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D30133 --- sys/kern/uipc_mbuf.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index e5de2286d8f3..6a1085720a85 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1139,6 +1139,29 @@ m_devget(char *buf, int totlen, int off, struct ifnet *ifp, return (top); } +static void +m_copytounmapped(const struct mbuf *m, int off, int len, c_caddr_t cp) +{ + struct iovec iov; + struct uio uio; + int error; + + KASSERT(off >= 0, ("m_copytounmapped: negative off %d", off)); + KASSERT(len >= 0, ("m_copytounmapped: negative len %d", len)); + KASSERT(off < m->m_len, ("m_copytounmapped: len exceeds mbuf length")); + iov.iov_base = __DECONST(caddr_t, cp); + iov.iov_len = len; + uio.uio_resid = len; + uio.uio_iov = &iov; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_rw = UIO_WRITE; + error = m_unmappedtouio(m, off, &uio, len); + KASSERT(error == 0, ("m_unmappedtouio failed: off %d, len %d", off, + len)); +} + /* * Copy data from a buffer back into the indicated mbuf chain, * starting "off" bytes from the beginning, extending the mbuf @@ -1172,7 +1195,10 @@ m_copyback(struct mbuf *m0, int off, int len, c_caddr_t cp) M_TRAILINGSPACE(m)); } mlen = min (m->m_len - off, len); - bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen); + if ((m->m_flags & M_EXTPG) != 0) + m_copytounmapped(m, off, mlen, cp); + else + bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen); cp += mlen; len -= mlen; mlen += off; @@ -1870,7 +1896,7 @@ m_uiotombuf(struct uio *uio, int how, int len, int align, int flags) } /* - * Copy data from an unmapped mbuf into a uio limited by len if set. + * Copy data to/from an unmapped mbuf into a uio limited by len if set. */ int m_unmappedtouio(const struct mbuf *m, int m_off, struct uio *uio, int len)