aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/uipc_mbuf.c
diff options
context:
space:
mode:
authorAndriy Voskoboinyk <avos@FreeBSD.org>2017-10-16 21:46:11 +0000
committerAndriy Voskoboinyk <avos@FreeBSD.org>2017-10-16 21:46:11 +0000
commit6623429867e0a48c72ccbe6c8c240a85e6b88b86 (patch)
treeab7a3c3c20cd9fe9bae40b9c4d34351a2d9863a9 /sys/kern/uipc_mbuf.c
parentc64c1f95a791046f4bd15e1d69b7c0de63e4cd83 (diff)
downloadsrc-6623429867e0a48c72ccbe6c8c240a85e6b88b86.tar.gz
src-6623429867e0a48c72ccbe6c8c240a85e6b88b86.zip
mbuf(9): unbreak m_fragment()
- Fix it by replacing m_cat() with m_prev->m_next = m_new (m_cat() will try to append data - as a result, there will be no fragmentation). - Move some constants out of the loop. Was previously tested with D4077. Differential Revision: https://reviews.freebsd.org/D4090
Notes
Notes: svn path=/head/; revision=324673
Diffstat (limited to 'sys/kern/uipc_mbuf.c')
-rw-r--r--sys/kern/uipc_mbuf.c57
1 files changed, 27 insertions, 30 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index a8a0391eae5c..6fe5f7630c58 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1449,62 +1449,59 @@ bad:
struct mbuf *
m_fragment(struct mbuf *m0, int how, int length)
{
- struct mbuf *m_new = NULL, *m_final = NULL;
- int progress = 0;
+ struct mbuf *m_first, *m_last;
+ int divisor = 255, progress = 0, fraglen;
if (!(m0->m_flags & M_PKTHDR))
return (m0);
- if ((length == 0) || (length < -2))
+ if (length == 0 || length < -2)
return (m0);
+ if (length > MCLBYTES)
+ length = MCLBYTES;
+ if (length < 0 && divisor > MCLBYTES)
+ divisor = MCLBYTES;
+ if (length == -1)
+ length = 1 + (arc4random() % divisor);
+ if (length > 0)
+ fraglen = length;
m_fixhdr(m0); /* Needed sanity check */
- m_final = m_getcl(how, MT_DATA, M_PKTHDR);
-
- if (m_final == NULL)
+ m_first = m_getcl(how, MT_DATA, M_PKTHDR);
+ if (m_first == NULL)
goto nospace;
- if (m_dup_pkthdr(m_final, m0, how) == 0)
+ if (m_dup_pkthdr(m_first, m0, how) == 0)
goto nospace;
- m_new = m_final;
-
- if (length == -1)
- length = 1 + (arc4random() & 255);
+ m_last = m_first;
while (progress < m0->m_pkthdr.len) {
- int fraglen;
-
- if (length > 0)
- fraglen = length;
- else
- fraglen = 1 + (arc4random() & 255);
+ if (length == -2)
+ fraglen = 1 + (arc4random() % divisor);
if (fraglen > m0->m_pkthdr.len - progress)
fraglen = m0->m_pkthdr.len - progress;
- if (fraglen > MCLBYTES)
- fraglen = MCLBYTES;
-
- if (m_new == NULL) {
- m_new = m_getcl(how, MT_DATA, 0);
+ if (progress != 0) {
+ struct mbuf *m_new = m_getcl(how, MT_DATA, 0);
if (m_new == NULL)
goto nospace;
+
+ m_last->m_next = m_new;
+ m_last = m_new;
}
- m_copydata(m0, progress, fraglen, mtod(m_new, caddr_t));
+ m_copydata(m0, progress, fraglen, mtod(m_last, caddr_t));
progress += fraglen;
- m_new->m_len = fraglen;
- if (m_new != m_final)
- m_cat(m_final, m_new);
- m_new = NULL;
+ m_last->m_len = fraglen;
}
m_freem(m0);
- m0 = m_final;
+ m0 = m_first;
return (m0);
nospace:
- if (m_final)
- m_freem(m_final);
+ if (m_first)
+ m_freem(m_first);
/* Return the original chain on failure */
return (m0);
}