Page MenuHomeFreeBSD

D44150.id135209.diff
No OneTemporary

D44150.id135209.diff

diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1937,65 +1937,101 @@
/*
* Copy the contents of uio into a properly sized mbuf chain.
+ * A compat KPI. Users are recommended to use direct calls to backing
+ * functions.
*/
struct mbuf *
-m_uiotombuf(struct uio *uio, int how, int len, int align, int flags)
+m_uiotombuf(struct uio *uio, int how, int len, int lspace, int flags)
{
- struct mbuf *m, *mb;
- int error, length;
- ssize_t total;
- int progress = 0;
- if (flags & M_EXTPG)
- return (m_uiotombuf_nomap(uio, how, len, align, flags));
+ if (flags & M_EXTPG) {
+ /* XXX: 'lspace' magically becomes maxseg! */
+ return (m_uiotombuf_nomap(uio, how, len, lspace, flags));
+ } else if (__predict_false(uio->uio_resid + len == 0)) {
+ struct mbuf *m;
- /*
- * len can be zero or an arbitrary large value bound by
- * the total data supplied by the uio.
- */
- if (len > 0)
- total = (uio->uio_resid < len) ? uio->uio_resid : len;
- else
- total = uio->uio_resid;
+ /*
+ * m_uiotombuf() is known to return zero length buffer, keep
+ * this compatibility. mc_uiotomc() won't do that.
+ */
+ if (flags & M_PKTHDR) {
+ m = m_gethdr(how, MT_DATA);
+ m->m_pkthdr.memlen = MSIZE;
+ } else
+ m = m_get(how, MT_DATA);
+ if (m != NULL)
+ m->m_data += lspace;
+ return (m);
+ } else {
+ struct mchain mc;
+ int error;
+
+ error = mc_uiotomc(&mc, uio, len, lspace, how, flags);
+ if (__predict_true(error == 0)) {
+ if (flags & M_PKTHDR) {
+ STAILQ_FIRST(&mc.mc_q)->m_pkthdr.len =
+ mc.mc_len;
+ STAILQ_FIRST(&mc.mc_q)->m_pkthdr.memlen =
+ mc.mc_mlen;
+ }
+ return (STAILQ_FIRST(&mc.mc_q));
+ } else
+ return (NULL);
+ }
+}
- /*
- * The smallest unit returned by m_getm2() is a single mbuf
- * with pkthdr. We can't align past it.
- */
- if (align >= MHLEN)
- return (NULL);
+/*
+ * Copy the contents of uio into a properly sized mbuf chain.
+ * In case of failure state of mchain is inconsistent.
+ */
+int
+mc_uiotomc(struct mchain *mc, struct uio *uio, u_int len, u_int lspace,
+ int how, int flags)
+{
+ struct mbuf *mb;
+ u_int total, progress, length;
+ int error;
- /*
- * Give us the full allocation or nothing.
- * If len is zero return the smallest empty mbuf.
- */
- m = m_getm2(NULL, max(total + align, 1), how, MT_DATA, flags);
- if (m == NULL)
- return (NULL);
- m->m_data += align;
+ MPASS(lspace < MHLEN);
+ MPASS(UINT_MAX - lspace >= len);
+ MPASS(uio->uio_resid >= 0);
+
+ if (len > 0) {
+ if (uio->uio_resid > len) {
+ total = len;
+ flags &= ~M_EOR;
+ } else
+ total = uio->uio_resid;
+ } else
+ total = (uio->uio_resid + lspace > UINT_MAX) ?
+ UINT_MAX - lspace : uio->uio_resid;
+
+ if (__predict_false(total + lspace == 0)) {
+ *mc = MCHAIN_INITIALIZER(mc);
+ return (0);
+ }
+
+ error = mc_get(mc, total + lspace, how, MT_DATA, flags);
+ if (__predict_false(error))
+ return (error);
+ STAILQ_FIRST(&mc->mc_q)->m_data += lspace;
/* Fill all mbufs with uio data and update header information. */
- for (mb = m; mb != NULL; mb = mb->m_next) {
+ progress = 0;
+ STAILQ_FOREACH(mb, &mc->mc_q, m_stailq) {
length = min(M_TRAILINGSPACE(mb), total - progress);
-
error = uiomove(mtod(mb, void *), length, uio);
- if (error) {
- m_freem(m);
- return (NULL);
+ if (__predict_false(error)) {
+ m_freem(STAILQ_FIRST(&mc->mc_q));
+ return (error);
}
-
mb->m_len = length;
+ mc->mc_len += length;
progress += length;
- if (flags & M_PKTHDR) {
- m->m_pkthdr.len += length;
- m->m_pkthdr.memlen += MSIZE;
- if (mb->m_flags & M_EXT)
- m->m_pkthdr.memlen += mb->m_ext.ext_size;
- }
}
KASSERT(progress == total, ("%s: progress != total", __func__));
- return (m);
+ return (0);
}
/*
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1761,6 +1761,7 @@
int mc_split(struct mchain *, struct mchain *, u_int, int);
int mc_get(struct mchain *, u_int, int, short, int);
+int mc_uiotomc(struct mchain *, struct uio *, u_int, u_int, int, int);
/*
* Note: STAILQ_REMOVE() is expensive. mc_remove_after() needs to be provided

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 4, 2:19 AM (12 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16959194
Default Alt Text
D44150.id135209.diff (4 KB)

Event Timeline