diff options
Diffstat (limited to 'sys/kern/uipc_mbuf.c')
-rw-r--r-- | sys/kern/uipc_mbuf.c | 79 |
1 files changed, 39 insertions, 40 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 8a56227..36432e0 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -287,19 +287,31 @@ m_extadd(struct mbuf *mb, caddr_t buf, u_int size, void mb_free_ext(struct mbuf *m) { - int skipmbuf; + int freembuf; - KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__)); - KASSERT(m->m_ext.ext_cnt != NULL, ("%s: ext_cnt not set", __func__)); + KASSERT(m->m_flags & M_EXT, ("%s: M_EXT not set on %p", __func__, m)); /* - * check if the header is embedded in the cluster + * Check if the header is embedded in the cluster. */ - skipmbuf = (m->m_flags & M_NOFREE); + 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; + } - /* Free attached storage if this mbuf is the only reference to it. */ - if (*(m->m_ext.ext_cnt) == 1 || - atomic_fetchadd_int(m->m_ext.ext_cnt, -1) == 1) { switch (m->m_ext.ext_type) { case EXT_PACKET: /* The packet zone is special. */ if (*(m->m_ext.ext_cnt) == 0) @@ -318,7 +330,6 @@ mb_free_ext(struct mbuf *m) case EXT_JUMBO16: uma_zfree(zone_jumbo16, m->m_ext.ext_buf); break; - case EXT_SFBUF: case EXT_NET_DRV: case EXT_MOD_TYPE: case EXT_DISPOSABLE: @@ -337,23 +348,9 @@ mb_free_ext(struct mbuf *m) ("%s: unknown ext_type", __func__)); } } - if (skipmbuf) - return; - /* - * Free this mbuf back to the mbuf zone with all m_ext - * information purged. - */ - m->m_ext.ext_buf = NULL; - m->m_ext.ext_free = NULL; - m->m_ext.ext_arg1 = NULL; - m->m_ext.ext_arg2 = NULL; - m->m_ext.ext_cnt = NULL; - m->m_ext.ext_size = 0; - m->m_ext.ext_type = 0; - m->m_ext.ext_flags = 0; - m->m_flags &= ~M_EXT; - uma_zfree(zone_mbuf, m); + if (freembuf) + uma_zfree(zone_mbuf, m); } /* @@ -363,22 +360,24 @@ mb_free_ext(struct mbuf *m) static void mb_dupcl(struct mbuf *n, struct mbuf *m) { - KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__)); - KASSERT(m->m_ext.ext_cnt != NULL, ("%s: ext_cnt not set", __func__)); - KASSERT((n->m_flags & M_EXT) == 0, ("%s: M_EXT set", __func__)); - if (*(m->m_ext.ext_cnt) == 1) - *(m->m_ext.ext_cnt) += 1; - else - atomic_add_int(m->m_ext.ext_cnt, 1); - n->m_ext.ext_buf = m->m_ext.ext_buf; - n->m_ext.ext_free = m->m_ext.ext_free; - n->m_ext.ext_arg1 = m->m_ext.ext_arg1; - n->m_ext.ext_arg2 = m->m_ext.ext_arg2; - n->m_ext.ext_size = m->m_ext.ext_size; - n->m_ext.ext_cnt = m->m_ext.ext_cnt; - n->m_ext.ext_type = m->m_ext.ext_type; - n->m_ext.ext_flags = m->m_ext.ext_flags; + KASSERT(m->m_flags & M_EXT, ("%s: M_EXT not set on %p", __func__, m)); + KASSERT(!(n->m_flags & M_EXT), ("%s: M_EXT set on %p", __func__, n)); + + switch (m->m_ext.ext_type) { + case EXT_SFBUF: + sf_ext_ref(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)); + if (*(m->m_ext.ext_cnt) == 1) + *(m->m_ext.ext_cnt) += 1; + else + atomic_add_int(m->m_ext.ext_cnt, 1); + } + + bcopy(&m->m_ext, &n->m_ext, sizeof(m->m_ext)); n->m_flags |= M_EXT; n->m_flags |= m->m_flags & M_RDONLY; } |