Download raw body.
mbuf cluster m_extref_mtx contention
On Wed, Apr 22, 2026 at 04:21:42PM +1000, David Gwynne wrote:
> from another perspective, if the use after free is the result
> mishandling mbufs, then the other diff is more forgiving of a buggy
> behaviour.
I still see stability problems with the extfree proxy diff. It
only happens when doing creating kstack flamegraphs with btrace.
Crash is not reliable, needs several test runs. But I don't see
crashes without the diff. Trying to reproduce and collect more
information.
Stopped at db_enter+0x14: popq %rbp
TID PID UID PRFLAGS PFLAGS CPU COMMAND
365692 20485 0 0x100000 0 12 splicebench
158520 39646 0 0x100000 0 13 splicebench
456824 46846 0 0x100000 0 9 splicebench
22375 7927 0 0x100000 0 11 splicebench
434104 44068 0 0x100000 0 2 splicebench
378795 93654 0 0x100000 0 7 splicebench
333691 25747 0 0x100000 0 5 splicebench
144907 64236 0 0x100000 0 0 splicebench
490277 24953 0 0x14000 0x200 3 softnet7
111587 91554 0 0x14000 0x200 14 softnet6
405206 59298 0 0x14000 0x200 8 softnet5
169965 54014 0 0x14000 0x200 4 softnet4
33162 42840 0 0x14000 0x200 10 softnet3
462975 60233 0 0x14000 0x200 6 softnet2
275559 33456 0 0x14000 0x200 1 softnet1
140656 14600 0 0x14000 0x200 15 softnet0
db_enter() at db_enter+0x14
panic(ffffffff826734e6) at panic+0xd5
__assert(ffffffff826ac5d9,ffffffff8264d8c6,b5,ffffffff82669d25) at __assert+0x29
dal_irq_service_dcn302_create(ffff800002ee0f00) at dal_irq_service_dcn302_create
clockintr_dispatch(ffff8000639e3b00) at clockintr_dispatch+0x259
lapic_clockintr(0,0) at lapic_clockintr+0x43
Xresume_lapic_ltimer() at Xresume_lapic_ltimer+0x2a
acpicpu_idle() at acpicpu_idle+0x131
sched_idle(ffff80005a6a7ff0) at sched_idle+0x24b
end trace frame: 0x0, count: 6
https://www.openbsd.org/ddb.html describes the minimum info required in bug
reports. Insufficient info makes it difficult to find and fix bugs.
ddb{22}> show panic
cpu0: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
*cpu1: uvm_fault(0xffffffff82bb9060, 0x2026734c0, 0, 1) -> e
cpu2: kernel diagnostic assertion "(sih->sih_state & (SIS_PENDING | SIS_RESTART)) == SIS_PENDING" failed: file "/usr/src/sys/kern/kern_softintr.c", line 71
cpu3: kernel diagnostic assertion "(sih->sih_state & (SIS_PENDING | SIS_RESTART)) == SIS_PENDING" failed: file "/usr/src/sys/kern/kern_softintr.c", line 71
cpu4: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu5: kernel diagnostic assertion "(sih->sih_state & (SIS_PENDING | SIS_RESTART)) == SIS_PENDING" failed: file "/usr/src/sys/kern/kern_softintr.c", line 71
cpu6: kernel diagnostic assertion "sb->sb_mb == sb->sb_lastrecord" failed: file "/usr/src/sys/kern/uipc_socket2.c", line 831
cpu7: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu8: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu9: kernel diagnostic assertion "(sih->sih_state & (SIS_PENDING | SIS_RESTART)) == SIS_PENDING" failed: file "/usr/src/sys/kern/kern_softintr.c", line 71
cpu10: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu11: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu12: receive 1: so 0xffff800003c26130, so_type 1, sb_cc 2896
cpu13: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu14: kernel diagnostic assertion "(sih->sih_state & (SIS_PENDING | SIS_RESTART)) == SIS_PENDING" failed: file "/usr/src/sys/kern/kern_softintr.c", line 71
cpu15: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu16: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu17: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu18: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu19: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu20: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu21: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu22: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu23: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu24: kernel diagnostic assertion "(sih->sih_state & (SIS_PENDING | SIS_RESTART)) == SIS_PENDING" failed: file "/usr/src/sys/kern/kern_softintr.c", line 71
cpu25: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu26: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu27: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu28: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu29: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu30: kernel diagnostic assertion "(sih->sih_state & SIS_RESTART) == 0" failed: file "/usr/src/sys/kern/kern_softintr.c", line 181
cpu31: kernel diagnostic assertion "(sih->sih_state & (SIS_PENDING | SIS_RESTART)) == SIS_PENDING" failed: file "/usr/src/sys/kern/kern_softintr.c", line 71
ddb{1}> trace
x86_ipi_db(ffff80005a5eaff0) at x86_ipi_db+0x16
x86_ipi_handler() at x86_ipi_handler+0x80
Xresume_lapic_ipi() at Xresume_lapic_ipi+0x27
x86_bus_space_io_read_1(3f8,5) at x86_bus_space_io_read_1+0x19
comcnputc(800,20) at comcnputc+0x7f
cnputc(20) at cnputc+0x47
db_putchar(70) at db_putchar+0x42a
kprintf() at kprintf+0x10b
db_printf(ffffffff8267d611) at db_printf+0x6d
panic(ffffffff826734e6) at panic+0xf4
__assert(ffffffff826ac5d9,ffffffff8264d8c6,b5,ffffffff82669d25) at __assert+0x29
dal_irq_service_dcn302_create(ffff800002ee0f00) at dal_irq_service_dcn302_create
clockintr_dispatch(ffff800063928ad0) at clockintr_dispatch+0x259
lapic_clockintr(0,0) at lapic_clockintr+0x43
Xresume_lapic_ltimer() at Xresume_lapic_ltimer+0x2a
x86_bus_space_mem_read_4(ffff80005a5e2000,f0) at x86_bus_space_mem_read_4+0x18
acpihpet_delay(1) at acpihpet_delay+0x42
comcnputc(800,20) at comcnputc+0xa2
cnputc(20) at cnputc+0x47
db_putchar(30) at db_putchar+0x42a
kprintf() at kprintf+0x12ff
db_printf(ffffffff82615490) at db_printf+0x6d
fault(ffffffff826d1a49) at fault+0x97
kpageflttrap(ffff800063928f50,2026734c0) at kpageflttrap+0x1aa
kerntrap(ffff800063928f50) at kerntrap+0xcf
alltraps_kern_meltdown() at alltraps_kern_meltdown+0x7b
refcnt_rele(fffffd8e5756e690) at refcnt_rele+0x78
m_extfree_refs(fffffd800b1a8000,800,fffffd8e5756e680) at m_extfree_refs+0x31
m_free(fffffd8085078600) at m_free+0x170
sbdrop(ffff800003c275f0,10f8) at sbdrop+0x8b
tcp_input_solocked(ffff800063929300,ffff80006392930c,fffffd808ab15c00,2,ffff8000639292f8) at tcp_input_solocked+0x2362
tcp_input_mlist(ffffffff82bafad0,2) at tcp_input_mlist+0x7f
if_input_process(ffff80000039c048,ffff8000639293d8,1) at if_input_process+0x272
ifiq_process(ffff800002c86800) at ifiq_process+0xa1
taskq_thread(ffff80000002c080) at taskq_thread+0x129
end trace frame: 0x0, count: -35
ddb{1}> ps
PID TID PPID UID S FLAGS WAIT COMMAND
58050 361454 71109 0 2 0x82 btrace
20485 365692 87224 0 7 0x100000 splicebench
39646 158520 87224 0 7 0x100000 splicebench
46846 456824 87224 0 7 0x100000 splicebench
15574 294431 87224 0 2 0x100000 splicebench
7927 22375 87224 0 7 0x100000 splicebench
93328 507813 87224 0 2 0x100000 splicebench
58465 519843 87224 0 2 0x100000 splicebench
44068 434104 87224 0 7 0x100000 splicebench
93654 378795 87224 0 7 0x100000 splicebench
31731 370468 87224 0 2 0x100000 splicebench
86434 103344 87224 0 2 0x100000 splicebench
27510 81545 87224 0 2 0x100000 splicebench
25747 333691 87224 0 7 0x100000 splicebench
53981 314709 87224 0 3 0x100000 inet splicebench
64236 144907 87224 0 7 0x100000 splicebench
71109 170280 89841 0 3 0x80 nanoslp perl
74634 405119 89841 0 3 0x10008a kqread ssh
87224 21255 89841 0 3 0x100082 kqread splicebench
89841 303793 17337 0 3 0x82 piperd perl
17337 318736 5426 0 3 0x10008a sigsusp ksh
5426 12123 28275 0 3 0x98 kqread sshd-session
28275 273225 70088 0 3 0x92 kqread sshd-session
50805 41303 1 0 3 0x100083 ttyin getty
24529 87335 1 0 3 0x100083 ttyin getty
80654 510830 1 0 3 0x100083 ttyin getty
12695 375538 1 0 3 0x100083 ttyin getty
79672 176039 1 0 3 0x100083 ttyin getty
36233 407260 1 0 3 0x100083 ttyin getty
68084 517278 1 0 3 0x100098 kqread cron
99602 246314 1 99 3 0x1100090 kqread sndiod
7947 118625 1 110 3 0x100090 kqread sndiod
83398 144268 65376 95 3 0x1100092 kqread smtpd
95991 338364 65376 103 3 0x1100092 kqread smtpd
38757 437470 65376 95 3 0x1100092 kqread smtpd
77933 309763 65376 95 3 0x100092 kqread smtpd
66827 14324 65376 95 3 0x1100092 kqread smtpd
68459 268927 65376 95 3 0x1100092 kqread smtpd
65376 74460 1 0 3 0x100080 kqread smtpd
91114 461520 93636 91 3 0x92 kqread snmpd_metrics
65876 362231 93636 91 3 0x1100092 kqread snmpd
93636 21862 1 0 3 0x100080 kqread snmpd
70088 185108 1 0 3 0x88 kqread sshd
52864 91164 0 0 3 0x14200 acct acct
50250 288863 0 0 3 0x14280 nfsidl nfsio
50176 209335 0 0 3 0x14280 nfsidl nfsio
94684 377523 0 0 3 0x14280 nfsidl nfsio
65946 508317 0 0 3 0x14280 nfsidl nfsio
50420 155428 1 0 3 0x100080 kqread ntpd
84238 472656 53678 83 3 0x100092 kqread ntpd
53678 368489 1 83 3 0x1100092 kqread ntpd
75650 368350 36295 74 3 0x1100092 bpf pflogd
36295 256904 1 0 3 0x80 sbwait pflogd
78139 297104 54691 73 3 0x1100090 kqread syslogd
54691 498524 1 0 3 0x100082 sbwait syslogd
44429 76567 1 0 3 0x100080 kqread resolvd
20709 51832 38604 77 3 0x100092 kqread dhcpleased
84502 56883 38604 77 3 0x100092 kqread dhcpleased
38604 171529 1 0 3 0x80 kqread dhcpleased
80043 500292 30287 115 3 0x100092 kqread slaacd
25595 354301 30287 115 3 0x100092 kqread slaacd
30287 36766 1 0 3 0x100080 kqread slaacd
58000 92819 0 0 3 0x14200 bored smr
52409 291605 0 0 3 0x14200 pgzero zerothread
41314 354360 0 0 3 0x14200 aiodoned aiodoned
54456 343610 0 0 3 0x14200 syncer update
67784 394946 0 0 3 0x14200 cleaner cleaner
19316 295810 0 0 3 0x14200 reaper reaper
60601 425075 0 0 3 0x14200 pgdaemon pagedaemon
1544 483302 0 0 3 0x14200 bored wsdisplay0
65239 166868 0 0 3 0x14200 usbtsk usbtask
1101 215935 0 0 3 0x14200 usbatsk usbatsk
42350 400898 0 0 3 0x40014200 acpi0 acpi0
41669 310274 0 0 7 0x40014200 idle31
91470 404675 0 0 7 0x40014200 idle30
95989 90446 0 0 7 0x40014200 idle29
70351 154384 0 0 7 0x40014200 idle28
28814 502486 0 0 7 0x40014200 idle27
48633 69788 0 0 7 0x40014200 idle26
14401 390864 0 0 7 0x40014200 idle25
19695 330551 0 0 7 0x40014200 idle24
55843 470262 0 0 7 0x40014200 idle23
80609 404760 0 0 7 0x40014200 idle22
77537 71178 0 0 7 0x40014200 idle21
51805 37231 0 0 7 0x40014200 idle20
50261 72855 0 0 7 0x40014200 idle19
82735 412108 0 0 7 0x40014200 idle18
42744 363135 0 0 7 0x40014200 idle17
27828 50260 0 0 7 0x40014200 idle16
8054 46800 0 0 3 0x40014200 idle15
76185 398551 0 0 3 0x40014200 idle14
75077 113551 0 0 3 0x40014200 idle13
20685 452403 0 0 3 0x40014200 idle12
7685 492379 0 0 3 0x40014200 idle11
49316 197614 0 0 3 0x40014200 idle10
10436 303108 0 0 3 0x40014200 idle9
60385 172713 0 0 3 0x40014200 idle8
82749 152815 0 0 3 0x40014200 idle7
98174 487337 0 0 3 0x40014200 idle6
30446 79273 0 0 3 0x40014200 idle5
87509 11375 0 0 3 0x40014200 idle4
65756 63368 0 0 3 0x40014200 idle3
99429 430206 0 0 3 0x40014200 idle2
97717 337576 0 0 3 0x40014200 idle1
92097 96322 0 0 3 0x14200 bored sensors
24953 490277 0 0 7 0x14200 softnet7
91554 111587 0 0 7 0x14200 softnet6
59298 405206 0 0 7 0x14200 softnet5
54014 169965 0 0 7 0x14200 softnet4
42840 33162 0 0 7 0x14200 softnet3
60233 462975 0 0 7 0x14200 softnet2
*33456 275559 0 0 7 0x14200 softnet1
14600 140656 0 0 7 0x14200 softnet0
94996 376490 0 0 3 0x14200 bored systqmp
87967 81803 0 0 3 0x14200 bored systq
91939 502639 0 0 3 0x14200 tmoslp softclockmp
67768 365183 0 0 3 0x40014200 tmoslp softclock
28080 21713 0 0 3 0x40014200 idle0
1 17636 0 0 3 0x82 wait init
0 0 -1 0 3 0x10200 scheduler swapper
ddb{1}> show register
rdi 0xffff80005a5eaff0
rsi 0
rbp 0xffff8000639285d0
rbx 0xffffffff82aaf738 ipifunc+0x38
rdx 0
rcx 0x7
rax 0xffffff7f
r8 0
r9 0
r10 0
r11 0x73176215a49ffd46
r12 0x7
r13 0xc
r14 0xffff80005a5eaff0
r15 0
rip 0xffffffff81ee5bd6 x86_ipi_db+0x16
cs 0x8
rflags 0x202
rsp 0xffff8000639285c0
ss 0x10
x86_ipi_db+0x16: leave
bluhm
> Index: kern/uipc_mbuf.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/uipc_mbuf.c,v
> diff -u -p -r1.304 uipc_mbuf.c
> --- kern/uipc_mbuf.c 5 Feb 2026 03:26:00 -0000 1.304
> +++ kern/uipc_mbuf.c 22 Apr 2026 06:04:19 -0000
> @@ -123,9 +123,21 @@ int max_linkhdr; /* largest link-level
> int max_protohdr; /* largest protocol header */
> int max_hdr; /* largest link+protocol header */
>
> -struct mutex m_extref_mtx = MUTEX_INITIALIZER(IPL_NET);
> +struct m_ext_refs {
> + void *arg;
> + u_int free_fn;
> + u_int zero;
> + struct refcnt refs;
> +};
> +
> +static struct pool m_ext_refs_pool;
> +
> +static void m_extfree_refs(caddr_t, u_int, void *);
> +u_int m_extfree_refs_fn;
> +
> +static int m_extref(struct mbuf *, struct mbuf *, int);
> +static void m_extfree(struct mbuf *);
>
> -void m_extfree(struct mbuf *);
> void m_zero(struct mbuf *);
>
> unsigned long mbuf_mem_limit; /* [a] how much memory can be allocated */
> @@ -174,6 +186,8 @@ mbinit(void)
>
> pool_init(&mtagpool, PACKET_TAG_MAXSIZE + sizeof(struct m_tag), 0,
> IPL_NET, 0, "mtagpl", NULL);
> + pool_init(&m_ext_refs_pool, sizeof(struct m_ext_refs), CACHELINESIZE,
> + IPL_NET, 0, "mextrefs", NULL);
>
> for (i = 0; i < nitems(mclsizes); i++) {
> lowbits = mclsizes[i] & ((1 << 10) - 1);
> @@ -193,6 +207,7 @@ mbinit(void)
>
> (void)mextfree_register(m_extfree_pool);
> KASSERT(num_extfree_fns == 1);
> + m_extfree_refs_fn = mextfree_register(m_extfree_refs);
> }
>
> void
> @@ -204,6 +219,7 @@ mbcpuinit(void)
>
> pool_cache_init(&mbpool);
> pool_cache_init(&mtagpool);
> + pool_cache_init(&m_ext_refs_pool);
>
> for (i = 0; i < nitems(mclsizes); i++)
> pool_cache_init(&mclpools[i]);
> @@ -399,6 +415,32 @@ m_extfree_pool(caddr_t buf, u_int size,
> pool_put(pp, buf);
> }
>
> +int
> +m_ext_refs_shared(struct mbuf *m)
> +{
> + struct m_ext_refs *mrefs = m->m_ext.ext_arg;
> +
> + return (refcnt_shared(&mrefs->refs));
> +}
> +
> +static void
> +m_extfree_refs(caddr_t buf, u_int size, void *arg)
> +{
> + struct m_ext_refs *mrefs = arg;
> +
> + if (refcnt_rele(&mrefs->refs)) {
> + if (mrefs->zero)
> + explicit_bzero(buf, size);
> +
> + KASSERT(mrefs->free_fn < num_extfree_fns);
> + KASSERT(mrefs->free_fn != m_extfree_refs_fn);
> +
> + mextfree_fns[mrefs->free_fn](buf, size, mrefs->arg);
> +
> + pool_put(&m_ext_refs_pool, mrefs);
> + }
> +}
> +
> struct mbuf *
> m_free(struct mbuf *m)
> {
> @@ -434,44 +476,33 @@ m_free(struct mbuf *m)
> return (n);
> }
>
> -void
> -m_extref(struct mbuf *o, struct mbuf *n)
> +static int
> +m_extref(struct mbuf *m, struct mbuf *n, int how)
> {
> - int refs = MCLISREFERENCED(o);
> + struct m_ext_refs *mrefs;
>
> - n->m_flags |= o->m_flags & (M_EXT|M_EXTWR);
> + if (m->m_ext.ext_free_fn == m_extfree_refs_fn)
> + mrefs = m->m_ext.ext_arg;
> + else {
> + mrefs = pool_get(&m_ext_refs_pool, how);
> + if (mrefs == NULL)
> + return (ENOMEM);
>
> - if (refs)
> - mtx_enter(&m_extref_mtx);
> - n->m_ext.ext_nextref = o->m_ext.ext_nextref;
> - n->m_ext.ext_prevref = o;
> - o->m_ext.ext_nextref = n;
> - n->m_ext.ext_nextref->m_ext.ext_prevref = n;
> - if (refs)
> - mtx_leave(&m_extref_mtx);
> -
> - MCLREFDEBUGN((n), __FILE__, __LINE__);
> -}
> + refcnt_init(&mrefs->refs);
> + mrefs->arg = m->m_ext.ext_arg;
> + mrefs->free_fn = m->m_ext.ext_free_fn;
> + mrefs->zero = 0;
>
> -static inline u_int
> -m_extunref(struct mbuf *m)
> -{
> - int refs = 0;
> + m->m_ext.ext_arg = mrefs;
> + m->m_ext.ext_free_fn = m_extfree_refs_fn;
> + }
>
> - if (!MCLISREFERENCED(m))
> - return (0);
> + refcnt_take(&mrefs->refs);
>
> - mtx_enter(&m_extref_mtx);
> - if (MCLISREFERENCED(m)) {
> - m->m_ext.ext_nextref->m_ext.ext_prevref =
> - m->m_ext.ext_prevref;
> - m->m_ext.ext_prevref->m_ext.ext_nextref =
> - m->m_ext.ext_nextref;
> - refs = 1;
> - }
> - mtx_leave(&m_extref_mtx);
> + MEXTADD(n, m->m_ext.ext_buf, m->m_ext.ext_size,
> + m->m_flags & M_EXTWR, m_extfree_refs_fn, mrefs);
>
> - return (refs);
> + return (0);
> }
>
> /*
> @@ -487,15 +518,13 @@ mextfree_register(void (*fn)(caddr_t, u_
> return num_extfree_fns++;
> }
>
> -void
> +static void
> m_extfree(struct mbuf *m)
> {
> - if (m_extunref(m) == 0) {
> - KASSERT(m->m_ext.ext_free_fn < num_extfree_fns);
> - mextfree_fns[m->m_ext.ext_free_fn](m->m_ext.ext_buf,
> - m->m_ext.ext_size, m->m_ext.ext_arg);
> - }
> -
> + KASSERT(m->m_ext.ext_free_fn < num_extfree_fns);
> + mextfree_fns[m->m_ext.ext_free_fn](m->m_ext.ext_buf,
> + m->m_ext.ext_size, m->m_ext.ext_arg);
> +
> m->m_flags &= ~(M_EXT|M_EXTWR);
> }
>
> @@ -656,9 +685,9 @@ m_copym(struct mbuf *m0, int off, int le
> }
> n->m_len = min(len, m->m_len - off);
> if (m->m_flags & M_EXT) {
> + if (m_extref(m, n, wait) != 0)
> + goto nospace;
> n->m_data = m->m_data + off;
> - n->m_ext = m->m_ext;
> - MCLADDREFERENCE(m, n);
> } else {
> n->m_data += m->m_data -
> (m->m_flags & M_PKTHDR ? m->m_pktdat : m->m_dat);
> @@ -1089,8 +1118,12 @@ m_split(struct mbuf *m0, int len0, int w
> return (NULL);
> }
> if (m->m_flags & M_EXT) {
> - n->m_ext = m->m_ext;
> - MCLADDREFERENCE(m, n);
> + if (m_extref(m, n, wait) != 0) {
> + m_freem(n);
> + if (m0->m_flags & M_PKTHDR)
> + m0->m_pkthdr.len = olen;
> + return (NULL);
> + }
> n->m_data = m->m_data + len;
> } else {
> m_align(n, remain);
> @@ -1271,13 +1304,17 @@ m_devget(char *buf, int totlen, int off)
> void
> m_zero(struct mbuf *m)
> {
> - if (M_READONLY(m)) {
> - mtx_enter(&m_extref_mtx);
> - if ((m->m_flags & M_EXT) && MCLISREFERENCED(m)) {
> - m->m_ext.ext_nextref->m_flags |= M_ZEROIZE;
> - m->m_ext.ext_prevref->m_flags |= M_ZEROIZE;
> - }
> - mtx_leave(&m_extref_mtx);
> + if (ISSET(m->m_flags, M_EXT) &&
> + m->m_ext.ext_free_fn == m_extfree_refs_fn) {
> + struct m_ext_refs *mrefs = m->m_ext.ext_arg;
> +
> + /*
> + * this variable only transitions in one direction,
> + * so if there is a race it will be toward the same
> + * result and therefore there is no loss.
> + */
> +
> + mrefs->zero = 1;
> return;
> }
>
> @@ -1525,9 +1562,7 @@ m_print(void *v,
> m->m_ext.ext_buf, m->m_ext.ext_size);
> (*pr)("m_ext.ext_free_fn: %u\tm_ext.ext_arg: %p\n",
> m->m_ext.ext_free_fn, m->m_ext.ext_arg);
> - (*pr)("m_ext.ext_nextref: %p\tm_ext.ext_prevref: %p\n",
> - m->m_ext.ext_nextref, m->m_ext.ext_prevref);
> -
> + /* if m_ext.ext_free_fn == m_extfree_refs_fn ? */
> }
> }
>
> Index: sys/mbuf.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/mbuf.h,v
> diff -u -p -r1.269 mbuf.h
> --- sys/mbuf.h 5 Feb 2026 03:26:00 -0000 1.269
> +++ sys/mbuf.h 22 Apr 2026 06:04:19 -0000
> @@ -145,8 +145,6 @@ struct mbuf_ext {
> void *ext_arg;
> u_int ext_free_fn; /* index of free function */
> u_int ext_size; /* size of buffer, for ext_free_fn */
> - struct mbuf *ext_nextref;
> - struct mbuf *ext_prevref;
> #ifdef DEBUG
> const char *ext_ofile;
> const char *ext_nfile;
> @@ -282,13 +280,22 @@ struct mbuf {
> #define MCLREFDEBUGO(m, file, line)
> #endif
>
> -#define MCLISREFERENCED(m) ((m)->m_ext.ext_nextref != (m))
> +int m_ext_refs_shared(struct mbuf *);
>
> -#define MCLADDREFERENCE(o, n) m_extref((o), (n))
> +static inline int
> +m_extreferenced(struct mbuf *m)
> +{
> + extern u_int m_extfree_refs_fn;
> +
> + if (m->m_ext.ext_free_fn != m_extfree_refs_fn)
> + return (0);
> +
> + return (m_ext_refs_shared(m));
> +}
> +
> +#define MCLISREFERENCED(m) m_extreferenced(m)
>
> #define MCLINITREFERENCE(m) do { \
> - (m)->m_ext.ext_prevref = (m); \
> - (m)->m_ext.ext_nextref = (m); \
> MCLREFDEBUGO((m), __FILE__, __LINE__); \
> MCLREFDEBUGN((m), NULL, 0); \
> } while (/* CONSTCOND */ 0)
> @@ -439,7 +446,6 @@ int m_leadingspace(struct mbuf *);
> int m_trailingspace(struct mbuf *);
> void m_align(struct mbuf *, int);
> struct mbuf *m_clget(struct mbuf *, int, u_int);
> -void m_extref(struct mbuf *, struct mbuf *);
> void m_pool_init(struct pool *, u_int, u_int, const char *);
> u_int m_pool_used(void);
> void m_extfree_pool(caddr_t, u_int, void *);
>
mbuf cluster m_extref_mtx contention