Esempio n. 1
0
/*
 * Non-directly-exported function to clean up after mbufs with M_EXT
 * storage attached to them if the reference count hits 1.
 */
void
mb_free_ext(struct mbuf *m)
{
	int freembuf;

	KASSERT(m->m_flags & M_EXT, ("%s: M_EXT not set on %p", __func__, m));

	/*
	 * Check if the header is embedded in the cluster.
	 */
	freembuf = (m->m_flags & M_NOFREE) ? 0 : 1;

	switch (m->m_ext.ext_type) {
	case EXT_SFBUF:
		sf_ext_free(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
		break;
	default:
		KASSERT(m->m_ext.ext_cnt != NULL,
		    ("%s: no refcounting pointer on %p", __func__, m));
		/* 
		 * Free attached storage if this mbuf is the only
		 * reference to it.
		 */
		if (*(m->m_ext.ext_cnt) != 1) {
			if (atomic_fetchadd_int(m->m_ext.ext_cnt, -1) != 1)
				break;
		}

		switch (m->m_ext.ext_type) {
		case EXT_PACKET:	/* The packet zone is special. */
			if (*(m->m_ext.ext_cnt) == 0)
				*(m->m_ext.ext_cnt) = 1;
			uma_zfree(zone_pack, m);
			return;		/* Job done. */
		case EXT_CLUSTER:
			uma_zfree(zone_clust, m->m_ext.ext_buf);
			break;
		case EXT_JUMBOP:
			uma_zfree(zone_jumbop, m->m_ext.ext_buf);
			break;
		case EXT_JUMBO9:
			uma_zfree(zone_jumbo9, m->m_ext.ext_buf);
			break;
		case EXT_JUMBO16:
			uma_zfree(zone_jumbo16, m->m_ext.ext_buf);
			break;
		case EXT_NET_DRV:
		case EXT_MOD_TYPE:
		case EXT_DISPOSABLE:
			*(m->m_ext.ext_cnt) = 0;
			uma_zfree(zone_ext_refcnt, __DEVOLATILE(u_int *,
				m->m_ext.ext_cnt));
			/* FALLTHROUGH */
		case EXT_EXTREF:
			KASSERT(m->m_ext.ext_free != NULL,
				("%s: ext_free not set", __func__));
			(*(m->m_ext.ext_free))(m, m->m_ext.ext_arg1,
			    m->m_ext.ext_arg2);
			break;
		default:
			KASSERT(m->m_ext.ext_type == 0,
				("%s: unknown ext_type", __func__));
		}
	}

	if (freembuf)
		uma_zfree(zone_mbuf, m);
}
Esempio n. 2
0
/*
 * Clean up after mbufs with M_EXT storage attached to them if the
 * reference count hits 1.
 */
void
mb_free_ext(struct mbuf *m)
{
	volatile u_int *refcnt;
	struct mbuf *mref;
	int freembuf;

	KASSERT(m->m_flags & M_EXT, ("%s: M_EXT not set on %p", __func__, m));

	/* See if this is the mbuf that holds the embedded refcount. */
	if (m->m_ext.ext_flags & EXT_FLAG_EMBREF) {
		refcnt = &m->m_ext.ext_count;
		mref = m;
	} else {
		KASSERT(m->m_ext.ext_cnt != NULL,
		    ("%s: no refcounting pointer on %p", __func__, m));
		refcnt = m->m_ext.ext_cnt;
		mref = __containerof(refcnt, struct mbuf, m_ext.ext_count);
	}

	/*
	 * Check if the header is embedded in the cluster.  It is
	 * important that we can't touch any of the mbuf fields
	 * after we have freed the external storage, since mbuf
	 * could have been embedded in it.
	 */
	freembuf = (m->m_flags & M_NOFREE) ? 0 : 1;

	/* Free attached storage if this mbuf is the only reference to it. */
	if (*refcnt == 1 || atomic_fetchadd_int(refcnt, -1) == 1) {
		switch (m->m_ext.ext_type) {
		case EXT_PACKET:
			/* The packet zone is special. */
			if (*refcnt == 0)
				*refcnt = 1;
			uma_zfree(zone_pack, mref);
			break;
		case EXT_CLUSTER:
			uma_zfree(zone_clust, m->m_ext.ext_buf);
			uma_zfree(zone_mbuf, mref);
			break;
		case EXT_JUMBOP:
			uma_zfree(zone_jumbop, m->m_ext.ext_buf);
			uma_zfree(zone_mbuf, mref);
			break;
		case EXT_JUMBO9:
			uma_zfree(zone_jumbo9, m->m_ext.ext_buf);
			uma_zfree(zone_mbuf, mref);
			break;
		case EXT_JUMBO16:
			uma_zfree(zone_jumbo16, m->m_ext.ext_buf);
			uma_zfree(zone_mbuf, mref);
			break;
		case EXT_SFBUF:
			sf_ext_free(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
			uma_zfree(zone_mbuf, mref);
			break;
		case EXT_SFBUF_NOCACHE:
			sf_ext_free_nocache(m->m_ext.ext_arg1,
			    m->m_ext.ext_arg2);
			uma_zfree(zone_mbuf, mref);
			break;
		case EXT_NET_DRV:
		case EXT_MOD_TYPE:
		case EXT_DISPOSABLE:
			KASSERT(m->m_ext.ext_free != NULL,
				("%s: ext_free not set", __func__));
			(*(m->m_ext.ext_free))(m, m->m_ext.ext_arg1,
			    m->m_ext.ext_arg2);
			uma_zfree(zone_mbuf, mref);
			break;
		case EXT_EXTREF:
			KASSERT(m->m_ext.ext_free != NULL,
				("%s: ext_free not set", __func__));
			(*(m->m_ext.ext_free))(m, m->m_ext.ext_arg1,
			    m->m_ext.ext_arg2);
			break;
		default:
			KASSERT(m->m_ext.ext_type == 0,
				("%s: unknown ext_type", __func__));
		}
	}

	if (freembuf && m != mref)
		uma_zfree(zone_mbuf, m);
}