コード例 #1
0
ファイル: uipc_mbuf.c プロジェクト: orumin/openbsd-efivars
/*
 * mbuf chain defragmenter. This function uses some evil tricks to defragment
 * an mbuf chain into a single buffer without changing the mbuf pointer.
 * This needs to know a lot of the mbuf internals to make this work.
 */
int
m_defrag(struct mbuf *m, int how)
{
	struct mbuf *m0;

	if (m->m_next == NULL)
		return (0);

#ifdef DIAGNOSTIC
	if (!(m->m_flags & M_PKTHDR))
		panic("m_defrag: no packet hdr or not a chain");
#endif

	if ((m0 = m_gethdr(how, m->m_type)) == NULL)
		return (ENOBUFS);
	if (m->m_pkthdr.len > MHLEN) {
		MCLGETI(m0, how, NULL, m->m_pkthdr.len);
		if (!(m0->m_flags & M_EXT)) {
			m_free(m0);
			return (ENOBUFS);
		}
	}
	m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
	m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;

	/* free chain behind and possible ext buf on the first mbuf */
	m_freem(m->m_next);
	m->m_next = NULL;
	if (m->m_flags & M_EXT)
		m_extfree(m);

	/*
	 * Bounce copy mbuf over to the original mbuf and set everything up.
	 * This needs to reset or clear all pointers that may go into the
	 * original mbuf chain.
	 */
	if (m0->m_flags & M_EXT) {
		memcpy(&m->m_ext, &m0->m_ext, sizeof(struct mbuf_ext));
		MCLINITREFERENCE(m);
		m->m_flags |= m0->m_flags & (M_EXT|M_EXTWR);
		m->m_data = m->m_ext.ext_buf;
	} else {
		m->m_data = m->m_pktdat;
		memcpy(m->m_data, m0->m_data, m0->m_len);
	}
	m->m_pkthdr.len = m->m_len = m0->m_len;

	m0->m_flags &= ~(M_EXT|M_EXTWR);	/* cluster is gone */
	m_free(m0);

	return (0);
}
コード例 #2
0
void
m_clget(struct mbuf *m, int how)
{
	int s;

	s = splvm();
	m->m_ext.ext_buf =
	    pool_get(&mclpool, how == M_WAIT ? PR_WAITOK : 0);
	splx(s);
	if (m->m_ext.ext_buf != NULL) {
		m->m_data = m->m_ext.ext_buf;
		m->m_flags |= M_EXT|M_CLUSTER;
		m->m_ext.ext_size = MCLBYTES;
		m->m_ext.ext_free = NULL;
		m->m_ext.ext_arg = NULL;
		MCLINITREFERENCE(m);
	}
}