Revert r274494, r274712, r275955 and provide extra comments explaining

why there could appear a zero-sized mbufs in socket buffers.

A proper fix would be to divorce record socket buffers and stream
socket buffers, and divorce pru_send that accepts normal data from
pru_send that accepts control data.
This commit is contained in:
Gleb Smirnoff 2014-12-20 22:12:04 +00:00
parent b03b5d729a
commit e834a84026
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=275968
2 changed files with 21 additions and 6 deletions

View File

@ -640,9 +640,6 @@ sbappendstream_locked(struct sockbuf *sb, struct mbuf *m, int flags)
{
SOCKBUF_LOCK_ASSERT(sb);
if (m == NULL)
return;
KASSERT(m->m_nextpkt == NULL,("sbappendstream 0"));
KASSERT(sb->sb_mb == sb->sb_lastrecord,("sbappendstream 1"));
@ -1065,6 +1062,21 @@ sbcut_internal(struct sockbuf *sb, int len)
m = n;
}
}
/*
* Free any zero-length mbufs from the buffer.
* For SOCK_DGRAM sockets such mbufs represent empty records.
* XXX: For SOCK_STREAM sockets such mbufs can appear in the buffer,
* when sosend_generic() needs to send only control data.
*/
while (m && m->m_len == 0) {
struct mbuf *n;
sbfree(sb, m);
n = m->m_next;
m->m_next = mfree;
mfree = m;
m = n;
}
if (m) {
sb->sb_mb = m;
m->m_nextpkt = next;

View File

@ -1310,11 +1310,14 @@ sosend_generic(struct socket *so, struct sockaddr *addr, struct uio *uio,
resid = 0;
if (flags & MSG_EOR)
top->m_flags |= M_EOR;
} else if (resid > 0) {
} else {
/*
* Copy the data from userland into a mbuf
* chain. If no data is to be copied in,
* a single empty mbuf is returned.
* chain. If resid is 0, which can happen
* only if we have control to send, then
* a single empty mbuf is returned. This
* is a workaround to prevent protocol send
* methods to panic.
*/
top = m_uiotombuf(uio, M_WAITOK, space,
(atomic ? max_hdr : 0),