Index: uipc_socket.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket.c,v diff -u -p -r1.344 uipc_socket.c --- uipc_socket.c 31 Oct 2024 12:51:55 -0000 1.344 +++ uipc_socket.c 1 Nov 2024 23:53:25 -0000 @@ -787,48 +787,36 @@ m_getuio(struct mbuf **mp, int atomic, l { struct mbuf *m, *top = NULL; struct mbuf **nextp = ⊤ - u_long len, mlen; - size_t resid = uio->uio_resid; + u_long len, mlen, alen; + int align = atomic ? roundup(max_hdr, sizeof(long)) : 0; int error; - do { - if (top == NULL) { - MGETHDR(m, M_WAIT, MT_DATA); - mlen = MHLEN; - } else { - MGET(m, M_WAIT, MT_DATA); - mlen = MLEN; - } + m = m_gethdr(M_WAIT, MT_DATA); + mlen = MHLEN; + + for (;;) { /* chain mbuf together */ *nextp = m; nextp = &m->m_next; - resid = ulmin(resid, space); - if (resid >= MINCLSIZE) { - MCLGETL(m, M_NOWAIT, ulmin(resid, MAXMCLBYTES)); - if ((m->m_flags & M_EXT) == 0) + /* How much data we want to put in this mbuf? */ + len = ulmin(uio->uio_resid, space); + /* How much space are we allocating for that data? */ + alen = align + len; + if (alen > mlen) { + MCLGETL(m, M_NOWAIT, ulmin(alen, MAXMCLBYTES)); + if (!ISSET(m->m_flags, M_EXT) && alen > MCLBYTES) MCLGETL(m, M_NOWAIT, MCLBYTES); - if ((m->m_flags & M_EXT) == 0) - goto nopages; - mlen = m->m_ext.ext_size; - len = ulmin(mlen, resid); - /* - * For datagram protocols, leave room - * for protocol headers in first mbuf. - */ - if (atomic && m == top && len < mlen - max_hdr) - m->m_data += max_hdr; - } else { -nopages: - len = ulmin(mlen, resid); - /* - * For datagram protocols, leave room - * for protocol headers in first mbuf. - */ - if (atomic && m == top && len < mlen - max_hdr) - m_align(m, len); + if (ISSET(m->m_flags, M_EXT)) + mlen = m->m_ext.ext_size; } + /* Avoid pain from a stupid max_hdr value */ + if (align < mlen) + m->m_data += align; + + /* How much data can we put in this mbuf? */ + len = ulmin(mlen, len); error = uiomove(mtod(m, caddr_t), len, uio); if (error) { m_freem(top); @@ -836,13 +824,19 @@ nopages: } /* adjust counters */ - resid = uio->uio_resid; space -= len; m->m_len = len; top->m_pkthdr.len += len; /* Is there more space and more data? */ - } while (space > 0 && resid > 0); + if (space == 0 || uio->uio_resid == 0) + break; + + align = 0; + + m = m_get(M_WAIT, MT_DATA); + mlen = MLEN; + } *mp = top; return 0;