1099a0e58SBosko Milekic /*- 2099a0e58SBosko Milekic * Copyright (c) 2004 3099a0e58SBosko Milekic * Bosko Milekic <bmilekic@FreeBSD.org>. 4099a0e58SBosko Milekic * All rights reserved. 5099a0e58SBosko Milekic * 6099a0e58SBosko Milekic * Redistribution and use in source and binary forms, with or without 7099a0e58SBosko Milekic * modification, are permitted provided that the following conditions 8099a0e58SBosko Milekic * are met: 9099a0e58SBosko Milekic * 1. Redistributions of source code must retain the above copyright 10099a0e58SBosko Milekic * notice unmodified, this list of conditions and the following 11099a0e58SBosko Milekic * disclaimer. 12099a0e58SBosko Milekic * 2. Redistributions in binary form must reproduce the above copyright 13099a0e58SBosko Milekic * notice, this list of conditions and the following disclaimer in the 14099a0e58SBosko Milekic * documentation and/or other materials provided with the distribution. 15099a0e58SBosko Milekic * 3. Neither the name of the author nor the names of contributors may be 16099a0e58SBosko Milekic * used to endorse or promote products derived from this software 17099a0e58SBosko Milekic * without specific prior written permission. 18099a0e58SBosko Milekic * 19099a0e58SBosko Milekic * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20099a0e58SBosko Milekic * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21099a0e58SBosko Milekic * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22099a0e58SBosko Milekic * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23099a0e58SBosko Milekic * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24099a0e58SBosko Milekic * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25099a0e58SBosko Milekic * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26099a0e58SBosko Milekic * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27099a0e58SBosko Milekic * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28099a0e58SBosko Milekic * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29099a0e58SBosko Milekic * SUCH DAMAGE. 30099a0e58SBosko Milekic */ 31099a0e58SBosko Milekic 32099a0e58SBosko Milekic #include <sys/cdefs.h> 33099a0e58SBosko Milekic __FBSDID("$FreeBSD$"); 34099a0e58SBosko Milekic 35099a0e58SBosko Milekic #include "opt_mac.h" 36099a0e58SBosko Milekic #include "opt_param.h" 37099a0e58SBosko Milekic 38099a0e58SBosko Milekic #include <sys/param.h> 39099a0e58SBosko Milekic #include <sys/mac.h> 40099a0e58SBosko Milekic #include <sys/malloc.h> 41099a0e58SBosko Milekic #include <sys/systm.h> 42099a0e58SBosko Milekic #include <sys/mbuf.h> 43099a0e58SBosko Milekic #include <sys/domain.h> 44099a0e58SBosko Milekic #include <sys/eventhandler.h> 45099a0e58SBosko Milekic #include <sys/kernel.h> 46099a0e58SBosko Milekic #include <sys/protosw.h> 47099a0e58SBosko Milekic #include <sys/smp.h> 48099a0e58SBosko Milekic #include <sys/sysctl.h> 49099a0e58SBosko Milekic 50099a0e58SBosko Milekic #include <vm/vm.h> 51099a0e58SBosko Milekic #include <vm/vm_page.h> 52099a0e58SBosko Milekic #include <vm/uma.h> 53099a0e58SBosko Milekic 54099a0e58SBosko Milekic /* 55099a0e58SBosko Milekic * In FreeBSD, Mbufs and Mbuf Clusters are allocated from UMA 56099a0e58SBosko Milekic * Zones. 57099a0e58SBosko Milekic * 58099a0e58SBosko Milekic * Mbuf Clusters (2K, contiguous) are allocated from the Cluster 59099a0e58SBosko Milekic * Zone. The Zone can be capped at kern.ipc.nmbclusters, if the 60099a0e58SBosko Milekic * administrator so desires. 61099a0e58SBosko Milekic * 62099a0e58SBosko Milekic * Mbufs are allocated from a UMA Master Zone called the Mbuf 63099a0e58SBosko Milekic * Zone. 64099a0e58SBosko Milekic * 65099a0e58SBosko Milekic * Additionally, FreeBSD provides a Packet Zone, which it 66099a0e58SBosko Milekic * configures as a Secondary Zone to the Mbuf Master Zone, 67099a0e58SBosko Milekic * thus sharing backend Slab kegs with the Mbuf Master Zone. 68099a0e58SBosko Milekic * 69099a0e58SBosko Milekic * Thus common-case allocations and locking are simplified: 70099a0e58SBosko Milekic * 71099a0e58SBosko Milekic * m_clget() m_getcl() 72099a0e58SBosko Milekic * | | 73099a0e58SBosko Milekic * | .------------>[(Packet Cache)] m_get(), m_gethdr() 74099a0e58SBosko Milekic * | | [ Packet ] | 75099a0e58SBosko Milekic * [(Cluster Cache)] [ Secondary ] [ (Mbuf Cache) ] 76099a0e58SBosko Milekic * [ Cluster Zone ] [ Zone ] [ Mbuf Master Zone ] 77099a0e58SBosko Milekic * | \________ | 78099a0e58SBosko Milekic * [ Cluster Keg ] \ / 79099a0e58SBosko Milekic * | [ Mbuf Keg ] 80099a0e58SBosko Milekic * [ Cluster Slabs ] | 81099a0e58SBosko Milekic * | [ Mbuf Slabs ] 82099a0e58SBosko Milekic * \____________(VM)_________________/ 83099a0e58SBosko Milekic */ 84099a0e58SBosko Milekic 85099a0e58SBosko Milekic int nmbclusters; 86099a0e58SBosko Milekic struct mbstat mbstat; 87099a0e58SBosko Milekic 88099a0e58SBosko Milekic static void 89099a0e58SBosko Milekic tunable_mbinit(void *dummy) 90099a0e58SBosko Milekic { 91099a0e58SBosko Milekic 92099a0e58SBosko Milekic /* This has to be done before VM init. */ 93099a0e58SBosko Milekic nmbclusters = 1024 + maxusers * 64; 94099a0e58SBosko Milekic TUNABLE_INT_FETCH("kern.ipc.nmbclusters", &nmbclusters); 95099a0e58SBosko Milekic } 96099a0e58SBosko Milekic SYSINIT(tunable_mbinit, SI_SUB_TUNABLES, SI_ORDER_ANY, tunable_mbinit, NULL); 97099a0e58SBosko Milekic 98099a0e58SBosko Milekic SYSCTL_DECL(_kern_ipc); 99099a0e58SBosko Milekic SYSCTL_INT(_kern_ipc, OID_AUTO, nmbclusters, CTLFLAG_RW, &nmbclusters, 0, 100099a0e58SBosko Milekic "Maximum number of mbuf clusters allowed"); 101099a0e58SBosko Milekic SYSCTL_STRUCT(_kern_ipc, OID_AUTO, mbstat, CTLFLAG_RD, &mbstat, mbstat, 102099a0e58SBosko Milekic "Mbuf general information and statistics"); 103099a0e58SBosko Milekic 104099a0e58SBosko Milekic /* 105099a0e58SBosko Milekic * Zones from which we allocate. 106099a0e58SBosko Milekic */ 107099a0e58SBosko Milekic uma_zone_t zone_mbuf; 108099a0e58SBosko Milekic uma_zone_t zone_clust; 109099a0e58SBosko Milekic uma_zone_t zone_pack; 110099a0e58SBosko Milekic 111099a0e58SBosko Milekic /* 112099a0e58SBosko Milekic * Local prototypes. 113099a0e58SBosko Milekic */ 114b23f72e9SBrian Feldman static int mb_ctor_mbuf(void *, int, void *, int); 115b23f72e9SBrian Feldman static int mb_ctor_clust(void *, int, void *, int); 116b23f72e9SBrian Feldman static int mb_ctor_pack(void *, int, void *, int); 117099a0e58SBosko Milekic static void mb_dtor_mbuf(void *, int, void *); 118099a0e58SBosko Milekic static void mb_dtor_clust(void *, int, void *); /* XXX */ 119099a0e58SBosko Milekic static void mb_dtor_pack(void *, int, void *); /* XXX */ 120b23f72e9SBrian Feldman static int mb_init_pack(void *, int, int); 121099a0e58SBosko Milekic static void mb_fini_pack(void *, int); 122099a0e58SBosko Milekic 123099a0e58SBosko Milekic static void mb_reclaim(void *); 124099a0e58SBosko Milekic static void mbuf_init(void *); 125099a0e58SBosko Milekic 126a04946cfSBrian Somers /* Ensure that MSIZE doesn't break dtom() - it must be a power of 2 */ 127a04946cfSBrian Somers CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE); 128a04946cfSBrian Somers 129099a0e58SBosko Milekic /* 130099a0e58SBosko Milekic * Initialize FreeBSD Network buffer allocation. 131099a0e58SBosko Milekic */ 132099a0e58SBosko Milekic SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL) 133099a0e58SBosko Milekic static void 134099a0e58SBosko Milekic mbuf_init(void *dummy) 135099a0e58SBosko Milekic { 136099a0e58SBosko Milekic 137099a0e58SBosko Milekic /* 138099a0e58SBosko Milekic * Configure UMA zones for Mbufs, Clusters, and Packets. 139099a0e58SBosko Milekic */ 140099a0e58SBosko Milekic zone_mbuf = uma_zcreate("Mbuf", MSIZE, mb_ctor_mbuf, mb_dtor_mbuf, 141a04946cfSBrian Somers NULL, NULL, MSIZE - 1, UMA_ZONE_MAXBUCKET); 142099a0e58SBosko Milekic zone_clust = uma_zcreate("MbufClust", MCLBYTES, mb_ctor_clust, 143099a0e58SBosko Milekic mb_dtor_clust, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_REFCNT); 144099a0e58SBosko Milekic if (nmbclusters > 0) 145099a0e58SBosko Milekic uma_zone_set_max(zone_clust, nmbclusters); 146099a0e58SBosko Milekic zone_pack = uma_zsecond_create("Packet", mb_ctor_pack, mb_dtor_pack, 147099a0e58SBosko Milekic mb_init_pack, mb_fini_pack, zone_mbuf); 148099a0e58SBosko Milekic 149099a0e58SBosko Milekic /* uma_prealloc() goes here */ 150099a0e58SBosko Milekic 151099a0e58SBosko Milekic /* 152099a0e58SBosko Milekic * Hook event handler for low-memory situation, used to 153099a0e58SBosko Milekic * drain protocols and push data back to the caches (UMA 154099a0e58SBosko Milekic * later pushes it back to VM). 155099a0e58SBosko Milekic */ 156099a0e58SBosko Milekic EVENTHANDLER_REGISTER(vm_lowmem, mb_reclaim, NULL, 157099a0e58SBosko Milekic EVENTHANDLER_PRI_FIRST); 158099a0e58SBosko Milekic 159099a0e58SBosko Milekic /* 160099a0e58SBosko Milekic * [Re]set counters and local statistics knobs. 161099a0e58SBosko Milekic * XXX Some of these should go and be replaced, but UMA stat 162099a0e58SBosko Milekic * gathering needs to be revised. 163099a0e58SBosko Milekic */ 164099a0e58SBosko Milekic mbstat.m_mbufs = 0; 165099a0e58SBosko Milekic mbstat.m_mclusts = 0; 166099a0e58SBosko Milekic mbstat.m_drain = 0; 167099a0e58SBosko Milekic mbstat.m_msize = MSIZE; 168099a0e58SBosko Milekic mbstat.m_mclbytes = MCLBYTES; 169099a0e58SBosko Milekic mbstat.m_minclsize = MINCLSIZE; 170099a0e58SBosko Milekic mbstat.m_mlen = MLEN; 171099a0e58SBosko Milekic mbstat.m_mhlen = MHLEN; 172099a0e58SBosko Milekic mbstat.m_numtypes = MT_NTYPES; 173099a0e58SBosko Milekic 174099a0e58SBosko Milekic mbstat.m_mcfail = mbstat.m_mpfail = 0; 175099a0e58SBosko Milekic mbstat.sf_iocnt = 0; 176099a0e58SBosko Milekic mbstat.sf_allocwait = mbstat.sf_allocfail = 0; 177099a0e58SBosko Milekic } 178099a0e58SBosko Milekic 179099a0e58SBosko Milekic /* 180099a0e58SBosko Milekic * Constructor for Mbuf master zone. 181099a0e58SBosko Milekic * 182099a0e58SBosko Milekic * The 'arg' pointer points to a mb_args structure which 183099a0e58SBosko Milekic * contains call-specific information required to support the 184099a0e58SBosko Milekic * mbuf allocation API. 185099a0e58SBosko Milekic */ 186b23f72e9SBrian Feldman static int 187b23f72e9SBrian Feldman mb_ctor_mbuf(void *mem, int size, void *arg, int how) 188099a0e58SBosko Milekic { 189099a0e58SBosko Milekic struct mbuf *m; 190099a0e58SBosko Milekic struct mb_args *args; 191b23f72e9SBrian Feldman #ifdef MAC 192b23f72e9SBrian Feldman int error; 193b23f72e9SBrian Feldman #endif 194099a0e58SBosko Milekic int flags; 195099a0e58SBosko Milekic short type; 196099a0e58SBosko Milekic 197099a0e58SBosko Milekic m = (struct mbuf *)mem; 198099a0e58SBosko Milekic args = (struct mb_args *)arg; 199099a0e58SBosko Milekic flags = args->flags; 200099a0e58SBosko Milekic type = args->type; 201099a0e58SBosko Milekic 202099a0e58SBosko Milekic m->m_type = type; 203099a0e58SBosko Milekic m->m_next = NULL; 204099a0e58SBosko Milekic m->m_nextpkt = NULL; 2056bc72ab9SBosko Milekic m->m_flags = flags; 206099a0e58SBosko Milekic if (flags & M_PKTHDR) { 207099a0e58SBosko Milekic m->m_data = m->m_pktdat; 208099a0e58SBosko Milekic m->m_pkthdr.rcvif = NULL; 209099a0e58SBosko Milekic m->m_pkthdr.csum_flags = 0; 210099a0e58SBosko Milekic SLIST_INIT(&m->m_pkthdr.tags); 211099a0e58SBosko Milekic #ifdef MAC 212099a0e58SBosko Milekic /* If the label init fails, fail the alloc */ 213b23f72e9SBrian Feldman error = mac_init_mbuf(m, how); 214b23f72e9SBrian Feldman if (error) 215b23f72e9SBrian Feldman return (error); 216099a0e58SBosko Milekic #endif 2176bc72ab9SBosko Milekic } else 218099a0e58SBosko Milekic m->m_data = m->m_dat; 219099a0e58SBosko Milekic mbstat.m_mbufs += 1; /* XXX */ 220b23f72e9SBrian Feldman return (0); 221099a0e58SBosko Milekic } 222099a0e58SBosko Milekic 223099a0e58SBosko Milekic /* 224099a0e58SBosko Milekic * The Mbuf master zone and Packet secondary zone destructor. 225099a0e58SBosko Milekic */ 226099a0e58SBosko Milekic static void 227099a0e58SBosko Milekic mb_dtor_mbuf(void *mem, int size, void *arg) 228099a0e58SBosko Milekic { 229099a0e58SBosko Milekic struct mbuf *m; 230099a0e58SBosko Milekic 231099a0e58SBosko Milekic m = (struct mbuf *)mem; 232099a0e58SBosko Milekic if ((m->m_flags & M_PKTHDR) != 0) 233099a0e58SBosko Milekic m_tag_delete_chain(m, NULL); 234099a0e58SBosko Milekic mbstat.m_mbufs -= 1; /* XXX */ 235099a0e58SBosko Milekic } 236099a0e58SBosko Milekic 237099a0e58SBosko Milekic /* XXX Only because of stats */ 238099a0e58SBosko Milekic static void 239099a0e58SBosko Milekic mb_dtor_pack(void *mem, int size, void *arg) 240099a0e58SBosko Milekic { 241099a0e58SBosko Milekic struct mbuf *m; 242099a0e58SBosko Milekic 243099a0e58SBosko Milekic m = (struct mbuf *)mem; 244099a0e58SBosko Milekic if ((m->m_flags & M_PKTHDR) != 0) 245099a0e58SBosko Milekic m_tag_delete_chain(m, NULL); 246099a0e58SBosko Milekic mbstat.m_mbufs -= 1; /* XXX */ 247099a0e58SBosko Milekic mbstat.m_mclusts -= 1; /* XXX */ 248099a0e58SBosko Milekic } 249099a0e58SBosko Milekic 250099a0e58SBosko Milekic /* 251099a0e58SBosko Milekic * The Cluster zone constructor. 252099a0e58SBosko Milekic * 253099a0e58SBosko Milekic * Here the 'arg' pointer points to the Mbuf which we 254099a0e58SBosko Milekic * are configuring cluster storage for. 255099a0e58SBosko Milekic */ 256b23f72e9SBrian Feldman static int 257b23f72e9SBrian Feldman mb_ctor_clust(void *mem, int size, void *arg, int how) 258099a0e58SBosko Milekic { 259099a0e58SBosko Milekic struct mbuf *m; 260099a0e58SBosko Milekic 261099a0e58SBosko Milekic m = (struct mbuf *)arg; 262099a0e58SBosko Milekic m->m_ext.ext_buf = (caddr_t)mem; 263099a0e58SBosko Milekic m->m_data = m->m_ext.ext_buf; 264099a0e58SBosko Milekic m->m_flags |= M_EXT; 265099a0e58SBosko Milekic m->m_ext.ext_free = NULL; 266099a0e58SBosko Milekic m->m_ext.ext_args = NULL; 267099a0e58SBosko Milekic m->m_ext.ext_size = MCLBYTES; 268099a0e58SBosko Milekic m->m_ext.ext_type = EXT_CLUSTER; 269099a0e58SBosko Milekic m->m_ext.ref_cnt = (u_int *)uma_find_refcnt(zone_clust, 270099a0e58SBosko Milekic m->m_ext.ext_buf); 271099a0e58SBosko Milekic *(m->m_ext.ref_cnt) = 1; 272099a0e58SBosko Milekic mbstat.m_mclusts += 1; /* XXX */ 273b23f72e9SBrian Feldman return (0); 274099a0e58SBosko Milekic } 275099a0e58SBosko Milekic 276099a0e58SBosko Milekic /* XXX */ 277099a0e58SBosko Milekic static void 278099a0e58SBosko Milekic mb_dtor_clust(void *mem, int size, void *arg) 279099a0e58SBosko Milekic { 280099a0e58SBosko Milekic mbstat.m_mclusts -= 1; /* XXX */ 281099a0e58SBosko Milekic } 282099a0e58SBosko Milekic 283099a0e58SBosko Milekic /* 284099a0e58SBosko Milekic * The Packet secondary zone's init routine, executed on the 285099a0e58SBosko Milekic * object's transition from keg slab to zone cache. 286099a0e58SBosko Milekic */ 287b23f72e9SBrian Feldman static int 288b23f72e9SBrian Feldman mb_init_pack(void *mem, int size, int how) 289099a0e58SBosko Milekic { 290099a0e58SBosko Milekic struct mbuf *m; 291099a0e58SBosko Milekic 292099a0e58SBosko Milekic m = (struct mbuf *)mem; 293099a0e58SBosko Milekic m->m_ext.ext_buf = NULL; 294b23f72e9SBrian Feldman uma_zalloc_arg(zone_clust, m, how); 295b23f72e9SBrian Feldman if (m->m_ext.ext_buf == NULL) 296b23f72e9SBrian Feldman return (ENOMEM); 297099a0e58SBosko Milekic mbstat.m_mclusts -= 1; /* XXX */ 298b23f72e9SBrian Feldman return (0); 299099a0e58SBosko Milekic } 300099a0e58SBosko Milekic 301099a0e58SBosko Milekic /* 302099a0e58SBosko Milekic * The Packet secondary zone's fini routine, executed on the 303099a0e58SBosko Milekic * object's transition from zone cache to keg slab. 304099a0e58SBosko Milekic */ 305099a0e58SBosko Milekic static void 306099a0e58SBosko Milekic mb_fini_pack(void *mem, int size) 307099a0e58SBosko Milekic { 308099a0e58SBosko Milekic struct mbuf *m; 309099a0e58SBosko Milekic 310099a0e58SBosko Milekic m = (struct mbuf *)mem; 311099a0e58SBosko Milekic uma_zfree_arg(zone_clust, m->m_ext.ext_buf, NULL); 312099a0e58SBosko Milekic m->m_ext.ext_buf = NULL; 313099a0e58SBosko Milekic mbstat.m_mclusts += 1; /* XXX */ 314099a0e58SBosko Milekic } 315099a0e58SBosko Milekic 316099a0e58SBosko Milekic /* 317099a0e58SBosko Milekic * The "packet" keg constructor. 318099a0e58SBosko Milekic */ 319b23f72e9SBrian Feldman static int 320b23f72e9SBrian Feldman mb_ctor_pack(void *mem, int size, void *arg, int how) 321099a0e58SBosko Milekic { 322099a0e58SBosko Milekic struct mbuf *m; 323099a0e58SBosko Milekic struct mb_args *args; 324b23f72e9SBrian Feldman #ifdef MAC 325b23f72e9SBrian Feldman int error; 326b23f72e9SBrian Feldman #endif 327b23f72e9SBrian Feldman int flags; 328099a0e58SBosko Milekic short type; 329099a0e58SBosko Milekic 330099a0e58SBosko Milekic m = (struct mbuf *)mem; 331099a0e58SBosko Milekic args = (struct mb_args *)arg; 332099a0e58SBosko Milekic flags = args->flags; 333099a0e58SBosko Milekic type = args->type; 334099a0e58SBosko Milekic 335099a0e58SBosko Milekic m->m_type = type; 336099a0e58SBosko Milekic m->m_next = NULL; 3376bc72ab9SBosko Milekic m->m_nextpkt = NULL; 338099a0e58SBosko Milekic m->m_data = m->m_ext.ext_buf; 339099a0e58SBosko Milekic m->m_flags = flags|M_EXT; 340099a0e58SBosko Milekic m->m_ext.ext_free = NULL; 341099a0e58SBosko Milekic m->m_ext.ext_args = NULL; 342099a0e58SBosko Milekic m->m_ext.ext_size = MCLBYTES; 343099a0e58SBosko Milekic m->m_ext.ext_type = EXT_PACKET; 344099a0e58SBosko Milekic *(m->m_ext.ref_cnt) = 1; 345099a0e58SBosko Milekic 346099a0e58SBosko Milekic if (flags & M_PKTHDR) { 347099a0e58SBosko Milekic m->m_pkthdr.rcvif = NULL; 348099a0e58SBosko Milekic m->m_pkthdr.csum_flags = 0; 349099a0e58SBosko Milekic SLIST_INIT(&m->m_pkthdr.tags); 350099a0e58SBosko Milekic #ifdef MAC 351099a0e58SBosko Milekic /* If the label init fails, fail the alloc */ 352b23f72e9SBrian Feldman error = mac_init_mbuf(m, how); 353b23f72e9SBrian Feldman if (error) 354b23f72e9SBrian Feldman return (error); 355099a0e58SBosko Milekic #endif 356099a0e58SBosko Milekic } 357099a0e58SBosko Milekic mbstat.m_mbufs += 1; /* XXX */ 358099a0e58SBosko Milekic mbstat.m_mclusts += 1; /* XXX */ 359b23f72e9SBrian Feldman return (0); 360099a0e58SBosko Milekic } 361099a0e58SBosko Milekic 362099a0e58SBosko Milekic /* 363099a0e58SBosko Milekic * This is the protocol drain routine. 364099a0e58SBosko Milekic * 365099a0e58SBosko Milekic * No locks should be held when this is called. The drain routines have to 366099a0e58SBosko Milekic * presently acquire some locks which raises the possibility of lock order 367099a0e58SBosko Milekic * reversal. 368099a0e58SBosko Milekic */ 369099a0e58SBosko Milekic static void 370099a0e58SBosko Milekic mb_reclaim(void *junk) 371099a0e58SBosko Milekic { 372099a0e58SBosko Milekic struct domain *dp; 373099a0e58SBosko Milekic struct protosw *pr; 374099a0e58SBosko Milekic 375099a0e58SBosko Milekic WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL, 376099a0e58SBosko Milekic "mb_reclaim()"); 377099a0e58SBosko Milekic 378099a0e58SBosko Milekic mbstat.m_drain++; 379099a0e58SBosko Milekic for (dp = domains; dp != NULL; dp = dp->dom_next) 380099a0e58SBosko Milekic for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 381099a0e58SBosko Milekic if (pr->pr_drain != NULL) 382099a0e58SBosko Milekic (*pr->pr_drain)(); 383099a0e58SBosko Milekic } 384