aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2021-05-25 23:59:18 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2021-05-25 23:59:18 +0000
commit3f9dac85cc8f2963026fdc2d5477acb607176a89 (patch)
treeba097881e49c96310b805fc1af926e8a993ea7db
parent3c7a01d773ac2d128eabb596eed7098f76966cc5 (diff)
downloadsrc-3f9dac85cc8f2963026fdc2d5477acb607176a89.tar.gz
src-3f9dac85cc8f2963026fdc2d5477acb607176a89.zip
Extend m_copyback() to support unmapped mbufs.
Reviewed by: gallatin, markj Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D30133
-rw-r--r--sys/kern/uipc_mbuf.c30
1 files 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)