diff -ruN /usr/src.org/sys/dev/en/midway.c /usr/src/sys/dev/en/midway.c --- /usr/src.org/sys/dev/en/midway.c Sun Sep 3 14:17:15 2000 +++ /usr/src/sys/dev/en/midway.c Mon Sep 4 22:25:55 2000 @@ -1826,7 +1826,7 @@ m = *mm; if (m->m_flags & M_EXT) { - if (m->m_ext.ext_free) { + if (!(m->m_ext.ext_type == EXT_CLUSTER)) { /* external buffer isn't an ordinary mbuf cluster! */ printf("%s: mfix: special buffer! can't make a copy!\n", sc->sc_dev.dv_xname); diff -ruN /usr/src.org/sys/kern/uipc_mbuf2.c /usr/src/sys/kern/uipc_mbuf2.c --- /usr/src.org/sys/kern/uipc_mbuf2.c Sun Sep 3 14:17:53 2000 +++ /usr/src/sys/kern/uipc_mbuf2.c Mon Sep 4 22:14:19 2000 @@ -82,7 +82,7 @@ * * on error return (NULL return value), original "m" will be freed. * - * XXX M_TRAILINGSPACE/M_LEADINGSPACE on shared cluster (sharedcluster) + * XXX M_TRAILINGSPACE/M_LEADINGSPACE only on writable external buffer. */ struct mbuf * m_pulldown(m, off, len, offp) @@ -92,7 +92,7 @@ { struct mbuf *n, *o; int hlen, tlen, olen; - int sharedcluster; + short writable; /* check invalid arguments. */ if (m == NULL) @@ -177,25 +177,24 @@ * easy cases first. * we need to use m_copydata() to get data from m_next, 0>. */ - if ((n->m_flags & M_EXT) == 0) - sharedcluster = 0; - else { - if (n->m_ext.ext_free) - sharedcluster = 1; - else if (MEXT_IS_REF(n)) - sharedcluster = 1; - else - sharedcluster = 0; - } + /* + * XXX: If we're writable, we're sure we're writable, because the + * XXX: ref. count cannot increase from 1, as that would require + * XXX: posession of mbuf n (which is impossible). However, if + * XXX: we're not writable, we may eventually become writable, + * XXX: but we'll fail to notice it as writable will already be + * XXX: set and we cannot invalidate it. + */ + writable = M_WRITABLE(n) ? 1 : 0; if ((off == 0 || offp) && M_TRAILINGSPACE(n) >= tlen - && !sharedcluster) { + && writable) { m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len); n->m_len += tlen; m_adj(n->m_next, tlen); goto ok; } if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen - && !sharedcluster) { + && writable) { n->m_next->m_data -= hlen; n->m_next->m_len += hlen; bcopy(mtod(n, caddr_t) + off, mtod(n->m_next, caddr_t), hlen); diff -ruN /usr/src.org/sys/kern/uipc_syscalls.c /usr/src/sys/kern/uipc_syscalls.c --- /usr/src.org/sys/kern/uipc_syscalls.c Sun Sep 3 14:17:50 2000 +++ /usr/src/sys/kern/uipc_syscalls.c Mon Sep 4 12:52:26 2000 @@ -1616,7 +1616,8 @@ /* * Setup external storage for mbuf. */ - MEXTADD(m, sf->kva, PAGE_SIZE, sf_buf_free, NULL); + MEXTADD(m, sf->kva, PAGE_SIZE, sf_buf_free, NULL, M_RDONLY, + EXT_SENDFILE); m->m_data = (char *) sf->kva + pgoff; m->m_pkthdr.len = m->m_len = xfsize; /* diff -ruN /usr/src.org/sys/netinet/ip_fil.c /usr/src/sys/netinet/ip_fil.c --- /usr/src.org/sys/netinet/ip_fil.c Sun Sep 3 14:18:30 2000 +++ /usr/src/sys/netinet/ip_fil.c Mon Sep 4 22:56:00 2000 @@ -1148,7 +1148,7 @@ m_freem(m); return ENOBUFS; } - avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN; + avail = MCLBYTES; xtra = MIN(ntohs(oip6->ip6_plen) + sizeof(ip6_t), avail - hlen - sizeof(*icmp) - max_linkhdr); if (dst == 0) { @@ -1361,11 +1361,7 @@ # if BSD >= 199306 int i = 0; -# ifdef MCLISREFERENCED - if ((m->m_flags & M_EXT) && MCLISREFERENCED(m)) -# else - if (m->m_flags & M_EXT) -# endif + if ((m->m_flags & M_EXT) && MEXT_IS_REF(m)) i = 1; # endif # ifndef sparc diff -ruN /usr/src.org/sys/netinet6/ipsec.c /usr/src/sys/netinet6/ipsec.c --- /usr/src.org/sys/netinet6/ipsec.c Sun Sep 3 14:18:26 2000 +++ /usr/src/sys/netinet6/ipsec.c Mon Sep 4 22:17:54 2000 @@ -3223,10 +3223,8 @@ * to the cluster. * XXX: is this approach effective? */ - if ( - n->m_ext.ext_free || - MEXT_IS_REF(n) - ) + if (!(n->m_ext.ext_type == EXT_CLUSTER) || + MEXT_IS_REF(n)) { int remain, copied; struct mbuf *mm; diff -ruN /usr/src.org/sys/pci/if_sk.c /usr/src/sys/pci/if_sk.c --- /usr/src.org/sys/pci/if_sk.c Sun Sep 3 14:18:13 2000 +++ /usr/src/sys/pci/if_sk.c Mon Sep 4 22:31:11 2000 @@ -689,7 +689,8 @@ } /* Attach the buffer to the mbuf */ - MEXTADD(m_new, buf, SK_MCLBYTES, sk_jfree, NULL); + MEXTADD(m_new, buf, SK_MCLBYTES, sk_jfree, NULL, 0, + EXT_DRV_IF_SK); m_new->m_data = (void *)buf; m_new->m_pkthdr.len = m_new->m_len = SK_MCLBYTES; } else { diff -ruN /usr/src.org/sys/pci/if_ti.c /usr/src/sys/pci/if_ti.c --- /usr/src.org/sys/pci/if_ti.c Sun Sep 3 14:18:13 2000 +++ /usr/src/sys/pci/if_ti.c Mon Sep 4 22:30:04 2000 @@ -825,7 +825,8 @@ /* Attach the buffer to the mbuf. */ m_new->m_data = (void *) buf; m_new->m_len = m_new->m_pkthdr.len = TI_JUMBO_FRAMELEN; - MEXTADD(m_new, buf, TI_JUMBO_FRAMELEN, ti_jfree, NULL); + MEXTADD(m_new, buf, TI_JUMBO_FRAMELEN, ti_jfree, NULL, 0, + EXT_DRV_IF_TI); } else { m_new = m; m_new->m_data = m_new->m_ext.ext_buf; diff -ruN /usr/src.org/sys/pci/if_wb.c /usr/src/sys/pci/if_wb.c --- /usr/src.org/sys/pci/if_wb.c Sun Sep 3 14:18:11 2000 +++ /usr/src/sys/pci/if_wb.c Mon Sep 4 22:30:49 2000 @@ -1104,7 +1104,8 @@ } m_new->m_data = c->wb_buf; m_new->m_pkthdr.len = m_new->m_len = WB_BUFBYTES; - MEXTADD(m_new, c->wb_buf, WB_BUFBYTES, wb_bfree, NULL); + MEXTADD(m_new, c->wb_buf, WB_BUFBYTES, wb_bfree, NULL, 0, + EXT_DRV_IF_WB); } else { m_new = m; m_new->m_len = m_new->m_pkthdr.len = WB_BUFBYTES; diff -ruN /usr/src.org/sys/sys/mbuf.h /usr/src/sys/sys/mbuf.h --- /usr/src.org/sys/sys/mbuf.h Sun Sep 3 14:18:15 2000 +++ /usr/src/sys/sys/mbuf.h Mon Sep 4 22:29:31 2000 @@ -89,6 +89,7 @@ void *ext_args; /* optional argument pointer */ u_int ext_size; /* size of buffer, for ext_free */ union mext_refcnt *ref_cnt; /* pointer to ref count info */ + short ext_type; /* Type of external storage */ }; struct mbuf { @@ -120,18 +121,27 @@ #define M_EXT 0x0001 /* has associated external storage */ #define M_PKTHDR 0x0002 /* start of record */ #define M_EOR 0x0004 /* end of record */ -#define M_PROTO1 0x0008 /* protocol-specific */ -#define M_PROTO2 0x0010 /* protocol-specific */ -#define M_PROTO3 0x0020 /* protocol-specific */ -#define M_PROTO4 0x0040 /* protocol-specific */ -#define M_PROTO5 0x0080 /* protocol-specific */ +#define M_RDONLY 0x0008 /* associated data is read-only */ +#define M_PROTO1 0x0010 /* protocol-specific */ +#define M_PROTO2 0x0020 /* protocol-specific */ +#define M_PROTO3 0x0040 /* protocol-specific */ +#define M_PROTO4 0x0080 /* protocol-specific */ +#define M_PROTO5 0x0100 /* protocol-specific */ /* mbuf pkthdr flags, also in m_flags */ -#define M_BCAST 0x0100 /* send/received as link-level broadcast */ -#define M_MCAST 0x0200 /* send/received as link-level multicast */ -#define M_FRAG 0x0400 /* packet is a fragment of a larger packet */ -#define M_FIRSTFRAG 0x0800 /* packet is first fragment */ -#define M_LASTFRAG 0x1000 /* packet is last fragment */ +#define M_BCAST 0x0200 /* send/received as link-level broadcast */ +#define M_MCAST 0x0400 /* send/received as link-level multicast */ +#define M_FRAG 0x0800 /* packet is a fragment of a larger packet */ +#define M_FIRSTFRAG 0x1000 /* packet is first fragment */ +#define M_LASTFRAG 0x2000 /* packet is last fragment */ + +/* external buffer types: mainly for documentation purposes, as it + virtually costs us nothing. */ +#define EXT_CLUSTER 1 /* mbuf cluster */ +#define EXT_SENDFILE 2 /* sendfile(2)'s external buffers */ +#define EXT_DRV_IF_TI 100 /* XXX: if_ti's jumbo frame buffers */ +#define EXT_DRV_IF_WB 101 /* XXX: if_wb's jumbo frame buffers */ +#define EXT_DRV_IF_SK 102 /* XXX: if_sk's jumbo frame buffers */ /* flags copied when copying m_pkthdr */ #define M_COPYFLAGS (M_PKTHDR|M_EOR|M_PROTO1|M_PROTO1|M_PROTO2|M_PROTO3 | \ @@ -293,7 +303,7 @@ panic("mbuf subsystem: out of ref counts!"); \ __mcnt = mext_refcnt_free; \ mext_refcnt_free = __mcnt->next_ref; \ - __mcnt->refcnt = 0; \ + __mcnt->refcnt = 0; \ (m_cnt) = __mcnt; \ mbstat.m_refree--; \ ) @@ -420,19 +430,21 @@ _mm->m_ext.ext_free = NULL; \ _mm->m_ext.ext_args = NULL; \ _mm->m_ext.ext_size = MCLBYTES; \ + _mm->m_ext.ext_type = EXT_CLUSTER; \ MEXT_INIT_REF(_mm); \ } \ } while (0) -#define MEXTADD(m, buf, size, free, args) do { \ +#define MEXTADD(m, buf, size, free, args, flags, type) do { \ struct mbuf *_mm = (m); \ \ - _mm->m_flags |= M_EXT; \ + _mm->m_flags |= (M_EXT | (flags)); \ _mm->m_ext.ext_buf = (caddr_t)(buf); \ _mm->m_data = _mm->m_ext.ext_buf; \ _mm->m_ext.ext_size = (size); \ _mm->m_ext.ext_free = (free); \ _mm->m_ext.ext_args = (args); \ + _mm->m_ext.ext_type = (type); \ MEXT_INIT_REF(_mm); \ } while (0) @@ -450,7 +462,7 @@ \ if (MEXT_IS_REF(_mmm)) \ MEXT_REM_REF(_mmm); \ - else if (_mmm->m_ext.ext_free != NULL) { \ + else if (!(_mmm->m_ext.ext_type == EXT_CLUSTER)) { \ (*(_mmm->m_ext.ext_free))(_mmm->m_ext.ext_buf, \ _mmm->m_ext.ext_args); \ _MEXT_DEALLOC_CNT(_mmm->m_ext.ref_cnt); \ @@ -484,6 +496,15 @@ mmbfree = _mm; \ MMBWAKEUP(); \ ) + +/* + * M_WRITABLE(m) + * Evaluate TRUE if it's safe to write to the mbuf m's data region (this + * can be both the local data payload, or an external buffer area, + * depending on whether M_EXT is set). + */ +#define M_WRITABLE(m) (!((m)->m_flags & M_RDONLY) && (!((m)->m_flags \ + & M_EXT) || !MEXT_IS_REF(m))) /* * Copy mbuf pkthdr from "from" to "to".