Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111382322
D44150.id135209.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D44150.id135209.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D44150: mbuf: provide mc_uiotomc() a function to copy from uio(9) to mchain
Attached
Detach File
Event Timeline
Log In to Comment