Deleted Added
full compact
kern_mbuf.c (152101) kern_mbuf.c (152130)
1/*-
2 * Copyright (c) 2004, 2005,
3 * Bosko Milekic <bmilekic@FreeBSD.org>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2004, 2005,
3 * Bosko Milekic <bmilekic@FreeBSD.org>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/kern/kern_mbuf.c 152101 2005-11-05 19:43:55Z andre $");
29__FBSDID("$FreeBSD: head/sys/kern/kern_mbuf.c 152130 2005-11-06 16:47:59Z glebius $");
30
31#include "opt_mac.h"
32#include "opt_param.h"
33
34#include <sys/param.h>
35#include <sys/mac.h>
36#include <sys/malloc.h>
37#include <sys/systm.h>
38#include <sys/mbuf.h>
39#include <sys/domain.h>
40#include <sys/eventhandler.h>
41#include <sys/kernel.h>
42#include <sys/protosw.h>
43#include <sys/smp.h>
44#include <sys/sysctl.h>
45
46#include <vm/vm.h>
47#include <vm/vm_page.h>
48#include <vm/uma.h>
49#include <vm/uma_int.h>
50#include <vm/uma_dbg.h>
51
52/*
53 * In FreeBSD, Mbufs and Mbuf Clusters are allocated from UMA
54 * Zones.
55 *
56 * Mbuf Clusters (2K, contiguous) are allocated from the Cluster
57 * Zone. The Zone can be capped at kern.ipc.nmbclusters, if the
58 * administrator so desires.
59 *
60 * Mbufs are allocated from a UMA Master Zone called the Mbuf
61 * Zone.
62 *
63 * Additionally, FreeBSD provides a Packet Zone, which it
64 * configures as a Secondary Zone to the Mbuf Master Zone,
65 * thus sharing backend Slab kegs with the Mbuf Master Zone.
66 *
67 * Thus common-case allocations and locking are simplified:
68 *
69 * m_clget() m_getcl()
70 * | |
71 * | .------------>[(Packet Cache)] m_get(), m_gethdr()
72 * | | [ Packet ] |
73 * [(Cluster Cache)] [ Secondary ] [ (Mbuf Cache) ]
74 * [ Cluster Zone ] [ Zone ] [ Mbuf Master Zone ]
75 * | \________ |
76 * [ Cluster Keg ] \ /
77 * | [ Mbuf Keg ]
78 * [ Cluster Slabs ] |
79 * | [ Mbuf Slabs ]
80 * \____________(VM)_________________/
81 *
82 *
83 * Whenever a object is allocated with uma_zalloc() out of the
84 * one of the Zones its _ctor_ function is executed. The same
85 * for any deallocation through uma_zfree() the _dror_ function
86 * is executed.
87 *
88 * Caches are per-CPU and are filled from the Master Zone.
89 *
90 * Whenever a object is allocated from the underlying global
91 * memory pool it gets pre-initialized with the _zinit_ functions.
92 * When the Keg's are overfull objects get decomissioned with
93 * _zfini_ functions and free'd back to the global memory pool.
94 *
95 */
96
97int nmbclusters; /* limits number of mbuf clusters */
98int nmbjumbo9; /* limits number of 9k jumbo clusters */
99int nmbjumbo16; /* limits number of 16k jumbo clusters */
100struct mbstat mbstat;
101
102static void
103tunable_mbinit(void *dummy)
104{
105
106 /* This has to be done before VM init. */
107 nmbclusters = 1024 + maxusers * 64;
108 TUNABLE_INT_FETCH("kern.ipc.nmbclusters", &nmbclusters);
109}
110SYSINIT(tunable_mbinit, SI_SUB_TUNABLES, SI_ORDER_ANY, tunable_mbinit, NULL);
111
112SYSCTL_DECL(_kern_ipc);
113/* XXX: These should be tuneables. Can't change UMA limits on the fly. */
114SYSCTL_INT(_kern_ipc, OID_AUTO, nmbclusters, CTLFLAG_RW, &nmbclusters, 0,
115 "Maximum number of mbuf clusters allowed");
116SYSCTL_INT(_kern_ipc, OID_AUTO, nmbjumbo9, CTLFLAG_RW, &nmbjumbo9, 0,
117 "Maximum number of mbuf 9k jumbo clusters allowed");
118SYSCTL_INT(_kern_ipc, OID_AUTO, nmbjumbo16, CTLFLAG_RW, &nmbjumbo16, 0,
119 "Maximum number of mbuf 16k jumbo clusters allowed");
120SYSCTL_STRUCT(_kern_ipc, OID_AUTO, mbstat, CTLFLAG_RD, &mbstat, mbstat,
121 "Mbuf general information and statistics");
122
123/*
124 * Zones from which we allocate.
125 */
126uma_zone_t zone_mbuf;
127uma_zone_t zone_clust;
128uma_zone_t zone_pack;
129uma_zone_t zone_jumbo9;
130uma_zone_t zone_jumbo16;
131uma_zone_t zone_ext_refcnt;
132
133/*
134 * Local prototypes.
135 */
136static int mb_ctor_mbuf(void *, int, void *, int);
137static int mb_ctor_clust(void *, int, void *, int);
138static int mb_ctor_pack(void *, int, void *, int);
139static void mb_dtor_mbuf(void *, int, void *);
140static void mb_dtor_clust(void *, int, void *);
141static void mb_dtor_pack(void *, int, void *);
142static int mb_zinit_pack(void *, int, int);
143static void mb_zfini_pack(void *, int);
144
145static void mb_reclaim(void *);
146static void mbuf_init(void *);
147
148/* Ensure that MSIZE doesn't break dtom() - it must be a power of 2 */
149CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE);
150
151/*
152 * Initialize FreeBSD Network buffer allocation.
153 */
154SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL)
155static void
156mbuf_init(void *dummy)
157{
158
159 /*
160 * Configure UMA zones for Mbufs, Clusters, and Packets.
161 */
162 zone_mbuf = uma_zcreate(MBUF_MEM_NAME, MSIZE,
163 mb_ctor_mbuf, mb_dtor_mbuf,
164#ifdef INVARIANTS
165 trash_init, trash_fini,
166#else
167 NULL, NULL,
168#endif
169 MSIZE - 1, UMA_ZONE_MAXBUCKET);
170
171 zone_clust = uma_zcreate(MBUF_CLUSTER_MEM_NAME, MCLBYTES,
172 mb_ctor_clust, mb_dtor_clust,
173#ifdef INVARIANTS
174 trash_init, trash_fini,
175#else
176 NULL, NULL,
177#endif
178 UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
179 if (nmbclusters > 0)
180 uma_zone_set_max(zone_clust, nmbclusters);
181
182 zone_pack = uma_zsecond_create(MBUF_PACKET_MEM_NAME, mb_ctor_pack,
183 mb_dtor_pack, mb_zinit_pack, mb_zfini_pack, zone_mbuf);
184
185 /* Make jumbo frame zone too. 9k and 16k. */
186 zone_jumbo9 = uma_zcreate(MBUF_JUMBO9_MEM_NAME, MJUM9BYTES,
187 mb_ctor_clust, mb_dtor_clust,
188#ifdef INVARIANTS
189 trash_init, trash_fini,
190#else
191 NULL, NULL,
192#endif
193 UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
194 if (nmbjumbo9 > 0)
195 uma_zone_set_max(zone_jumbo9, nmbjumbo9);
196
197 zone_jumbo16 = uma_zcreate(MBUF_JUMBO16_MEM_NAME, MJUM16BYTES,
198 mb_ctor_clust, mb_dtor_clust,
199#ifdef INVARIANTS
200 trash_init, trash_fini,
201#else
202 NULL, NULL,
203#endif
204 UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
205 if (nmbjumbo16 > 0)
206 uma_zone_set_max(zone_jumbo16, nmbjumbo16);
207
208 zone_ext_refcnt = uma_zcreate(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int),
209 NULL, NULL,
210 NULL, NULL,
211 UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
212
213 /* uma_prealloc() goes here... */
214
215 /*
216 * Hook event handler for low-memory situation, used to
217 * drain protocols and push data back to the caches (UMA
218 * later pushes it back to VM).
219 */
220 EVENTHANDLER_REGISTER(vm_lowmem, mb_reclaim, NULL,
221 EVENTHANDLER_PRI_FIRST);
222
223 /*
224 * [Re]set counters and local statistics knobs.
225 * XXX Some of these should go and be replaced, but UMA stat
226 * gathering needs to be revised.
227 */
228 mbstat.m_mbufs = 0;
229 mbstat.m_mclusts = 0;
230 mbstat.m_drain = 0;
231 mbstat.m_msize = MSIZE;
232 mbstat.m_mclbytes = MCLBYTES;
233 mbstat.m_minclsize = MINCLSIZE;
234 mbstat.m_mlen = MLEN;
235 mbstat.m_mhlen = MHLEN;
236 mbstat.m_numtypes = MT_NTYPES;
237
238 mbstat.m_mcfail = mbstat.m_mpfail = 0;
239 mbstat.sf_iocnt = 0;
240 mbstat.sf_allocwait = mbstat.sf_allocfail = 0;
241}
242
243/*
244 * Constructor for Mbuf master zone.
245 *
246 * The 'arg' pointer points to a mb_args structure which
247 * contains call-specific information required to support the
248 * mbuf allocation API. See mbuf.h.
249 */
250static int
251mb_ctor_mbuf(void *mem, int size, void *arg, int how)
252{
253 struct mbuf *m;
254 struct mb_args *args;
255#ifdef MAC
256 int error;
257#endif
258 int flags;
259 short type;
260
261#ifdef INVARIANTS
262 trash_ctor(mem, size, arg, how);
263#endif
264 m = (struct mbuf *)mem;
265 args = (struct mb_args *)arg;
266 flags = args->flags;
267 type = args->type;
268
269 /*
270 * The mbuf is initialized later. The caller has the
271 * responseability to setup any MAC labels too.
272 */
273 if (type == MT_NOINIT)
274 return (0);
275
276 m->m_next = NULL;
277 m->m_nextpkt = NULL;
278 m->m_len = 0;
279 m->m_flags = flags;
280 m->m_type = type;
281 if (flags & M_PKTHDR) {
282 m->m_data = m->m_pktdat;
283 m->m_pkthdr.rcvif = NULL;
284 m->m_pkthdr.len = 0;
285 m->m_pkthdr.header = NULL;
286 m->m_pkthdr.csum_flags = 0;
287 m->m_pkthdr.csum_data = 0;
288 SLIST_INIT(&m->m_pkthdr.tags);
289#ifdef MAC
290 /* If the label init fails, fail the alloc */
291 error = mac_init_mbuf(m, how);
292 if (error)
293 return (error);
294#endif
295 } else
296 m->m_data = m->m_dat;
297 return (0);
298}
299
300/*
301 * The Mbuf master zone destructor.
302 */
303static void
304mb_dtor_mbuf(void *mem, int size, void *arg)
305{
306 struct mbuf *m;
307
308 m = (struct mbuf *)mem;
309 if ((m->m_flags & M_PKTHDR) != 0)
310 m_tag_delete_chain(m, NULL);
311 KASSERT((m->m_flags & M_EXT) == 0, ("%s: M_EXT set", __func__));
312#ifdef INVARIANTS
313 trash_dtor(mem, size, arg);
314#endif
315}
316
317/*
318 * The Mbuf Packet zone destructor.
319 */
320static void
321mb_dtor_pack(void *mem, int size, void *arg)
322{
323 struct mbuf *m;
324
325 m = (struct mbuf *)mem;
326 if ((m->m_flags & M_PKTHDR) != 0)
327 m_tag_delete_chain(m, NULL);
328
329 /* Make sure we've got a clean cluster back. */
330 KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__));
331 KASSERT(m->m_ext.ext_buf != NULL, ("%s: ext_buf == NULL", __func__));
332 KASSERT(m->m_ext.ext_free == NULL, ("%s: ext_free != NULL", __func__));
333 KASSERT(m->m_ext.ext_args == NULL, ("%s: ext_args != NULL", __func__));
334 KASSERT(m->m_ext.ext_size == MCLBYTES, ("%s: ext_size != MCLBYTES", __func__));
30
31#include "opt_mac.h"
32#include "opt_param.h"
33
34#include <sys/param.h>
35#include <sys/mac.h>
36#include <sys/malloc.h>
37#include <sys/systm.h>
38#include <sys/mbuf.h>
39#include <sys/domain.h>
40#include <sys/eventhandler.h>
41#include <sys/kernel.h>
42#include <sys/protosw.h>
43#include <sys/smp.h>
44#include <sys/sysctl.h>
45
46#include <vm/vm.h>
47#include <vm/vm_page.h>
48#include <vm/uma.h>
49#include <vm/uma_int.h>
50#include <vm/uma_dbg.h>
51
52/*
53 * In FreeBSD, Mbufs and Mbuf Clusters are allocated from UMA
54 * Zones.
55 *
56 * Mbuf Clusters (2K, contiguous) are allocated from the Cluster
57 * Zone. The Zone can be capped at kern.ipc.nmbclusters, if the
58 * administrator so desires.
59 *
60 * Mbufs are allocated from a UMA Master Zone called the Mbuf
61 * Zone.
62 *
63 * Additionally, FreeBSD provides a Packet Zone, which it
64 * configures as a Secondary Zone to the Mbuf Master Zone,
65 * thus sharing backend Slab kegs with the Mbuf Master Zone.
66 *
67 * Thus common-case allocations and locking are simplified:
68 *
69 * m_clget() m_getcl()
70 * | |
71 * | .------------>[(Packet Cache)] m_get(), m_gethdr()
72 * | | [ Packet ] |
73 * [(Cluster Cache)] [ Secondary ] [ (Mbuf Cache) ]
74 * [ Cluster Zone ] [ Zone ] [ Mbuf Master Zone ]
75 * | \________ |
76 * [ Cluster Keg ] \ /
77 * | [ Mbuf Keg ]
78 * [ Cluster Slabs ] |
79 * | [ Mbuf Slabs ]
80 * \____________(VM)_________________/
81 *
82 *
83 * Whenever a object is allocated with uma_zalloc() out of the
84 * one of the Zones its _ctor_ function is executed. The same
85 * for any deallocation through uma_zfree() the _dror_ function
86 * is executed.
87 *
88 * Caches are per-CPU and are filled from the Master Zone.
89 *
90 * Whenever a object is allocated from the underlying global
91 * memory pool it gets pre-initialized with the _zinit_ functions.
92 * When the Keg's are overfull objects get decomissioned with
93 * _zfini_ functions and free'd back to the global memory pool.
94 *
95 */
96
97int nmbclusters; /* limits number of mbuf clusters */
98int nmbjumbo9; /* limits number of 9k jumbo clusters */
99int nmbjumbo16; /* limits number of 16k jumbo clusters */
100struct mbstat mbstat;
101
102static void
103tunable_mbinit(void *dummy)
104{
105
106 /* This has to be done before VM init. */
107 nmbclusters = 1024 + maxusers * 64;
108 TUNABLE_INT_FETCH("kern.ipc.nmbclusters", &nmbclusters);
109}
110SYSINIT(tunable_mbinit, SI_SUB_TUNABLES, SI_ORDER_ANY, tunable_mbinit, NULL);
111
112SYSCTL_DECL(_kern_ipc);
113/* XXX: These should be tuneables. Can't change UMA limits on the fly. */
114SYSCTL_INT(_kern_ipc, OID_AUTO, nmbclusters, CTLFLAG_RW, &nmbclusters, 0,
115 "Maximum number of mbuf clusters allowed");
116SYSCTL_INT(_kern_ipc, OID_AUTO, nmbjumbo9, CTLFLAG_RW, &nmbjumbo9, 0,
117 "Maximum number of mbuf 9k jumbo clusters allowed");
118SYSCTL_INT(_kern_ipc, OID_AUTO, nmbjumbo16, CTLFLAG_RW, &nmbjumbo16, 0,
119 "Maximum number of mbuf 16k jumbo clusters allowed");
120SYSCTL_STRUCT(_kern_ipc, OID_AUTO, mbstat, CTLFLAG_RD, &mbstat, mbstat,
121 "Mbuf general information and statistics");
122
123/*
124 * Zones from which we allocate.
125 */
126uma_zone_t zone_mbuf;
127uma_zone_t zone_clust;
128uma_zone_t zone_pack;
129uma_zone_t zone_jumbo9;
130uma_zone_t zone_jumbo16;
131uma_zone_t zone_ext_refcnt;
132
133/*
134 * Local prototypes.
135 */
136static int mb_ctor_mbuf(void *, int, void *, int);
137static int mb_ctor_clust(void *, int, void *, int);
138static int mb_ctor_pack(void *, int, void *, int);
139static void mb_dtor_mbuf(void *, int, void *);
140static void mb_dtor_clust(void *, int, void *);
141static void mb_dtor_pack(void *, int, void *);
142static int mb_zinit_pack(void *, int, int);
143static void mb_zfini_pack(void *, int);
144
145static void mb_reclaim(void *);
146static void mbuf_init(void *);
147
148/* Ensure that MSIZE doesn't break dtom() - it must be a power of 2 */
149CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE);
150
151/*
152 * Initialize FreeBSD Network buffer allocation.
153 */
154SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL)
155static void
156mbuf_init(void *dummy)
157{
158
159 /*
160 * Configure UMA zones for Mbufs, Clusters, and Packets.
161 */
162 zone_mbuf = uma_zcreate(MBUF_MEM_NAME, MSIZE,
163 mb_ctor_mbuf, mb_dtor_mbuf,
164#ifdef INVARIANTS
165 trash_init, trash_fini,
166#else
167 NULL, NULL,
168#endif
169 MSIZE - 1, UMA_ZONE_MAXBUCKET);
170
171 zone_clust = uma_zcreate(MBUF_CLUSTER_MEM_NAME, MCLBYTES,
172 mb_ctor_clust, mb_dtor_clust,
173#ifdef INVARIANTS
174 trash_init, trash_fini,
175#else
176 NULL, NULL,
177#endif
178 UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
179 if (nmbclusters > 0)
180 uma_zone_set_max(zone_clust, nmbclusters);
181
182 zone_pack = uma_zsecond_create(MBUF_PACKET_MEM_NAME, mb_ctor_pack,
183 mb_dtor_pack, mb_zinit_pack, mb_zfini_pack, zone_mbuf);
184
185 /* Make jumbo frame zone too. 9k and 16k. */
186 zone_jumbo9 = uma_zcreate(MBUF_JUMBO9_MEM_NAME, MJUM9BYTES,
187 mb_ctor_clust, mb_dtor_clust,
188#ifdef INVARIANTS
189 trash_init, trash_fini,
190#else
191 NULL, NULL,
192#endif
193 UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
194 if (nmbjumbo9 > 0)
195 uma_zone_set_max(zone_jumbo9, nmbjumbo9);
196
197 zone_jumbo16 = uma_zcreate(MBUF_JUMBO16_MEM_NAME, MJUM16BYTES,
198 mb_ctor_clust, mb_dtor_clust,
199#ifdef INVARIANTS
200 trash_init, trash_fini,
201#else
202 NULL, NULL,
203#endif
204 UMA_ALIGN_PTR, UMA_ZONE_REFCNT);
205 if (nmbjumbo16 > 0)
206 uma_zone_set_max(zone_jumbo16, nmbjumbo16);
207
208 zone_ext_refcnt = uma_zcreate(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int),
209 NULL, NULL,
210 NULL, NULL,
211 UMA_ALIGN_PTR, UMA_ZONE_ZINIT);
212
213 /* uma_prealloc() goes here... */
214
215 /*
216 * Hook event handler for low-memory situation, used to
217 * drain protocols and push data back to the caches (UMA
218 * later pushes it back to VM).
219 */
220 EVENTHANDLER_REGISTER(vm_lowmem, mb_reclaim, NULL,
221 EVENTHANDLER_PRI_FIRST);
222
223 /*
224 * [Re]set counters and local statistics knobs.
225 * XXX Some of these should go and be replaced, but UMA stat
226 * gathering needs to be revised.
227 */
228 mbstat.m_mbufs = 0;
229 mbstat.m_mclusts = 0;
230 mbstat.m_drain = 0;
231 mbstat.m_msize = MSIZE;
232 mbstat.m_mclbytes = MCLBYTES;
233 mbstat.m_minclsize = MINCLSIZE;
234 mbstat.m_mlen = MLEN;
235 mbstat.m_mhlen = MHLEN;
236 mbstat.m_numtypes = MT_NTYPES;
237
238 mbstat.m_mcfail = mbstat.m_mpfail = 0;
239 mbstat.sf_iocnt = 0;
240 mbstat.sf_allocwait = mbstat.sf_allocfail = 0;
241}
242
243/*
244 * Constructor for Mbuf master zone.
245 *
246 * The 'arg' pointer points to a mb_args structure which
247 * contains call-specific information required to support the
248 * mbuf allocation API. See mbuf.h.
249 */
250static int
251mb_ctor_mbuf(void *mem, int size, void *arg, int how)
252{
253 struct mbuf *m;
254 struct mb_args *args;
255#ifdef MAC
256 int error;
257#endif
258 int flags;
259 short type;
260
261#ifdef INVARIANTS
262 trash_ctor(mem, size, arg, how);
263#endif
264 m = (struct mbuf *)mem;
265 args = (struct mb_args *)arg;
266 flags = args->flags;
267 type = args->type;
268
269 /*
270 * The mbuf is initialized later. The caller has the
271 * responseability to setup any MAC labels too.
272 */
273 if (type == MT_NOINIT)
274 return (0);
275
276 m->m_next = NULL;
277 m->m_nextpkt = NULL;
278 m->m_len = 0;
279 m->m_flags = flags;
280 m->m_type = type;
281 if (flags & M_PKTHDR) {
282 m->m_data = m->m_pktdat;
283 m->m_pkthdr.rcvif = NULL;
284 m->m_pkthdr.len = 0;
285 m->m_pkthdr.header = NULL;
286 m->m_pkthdr.csum_flags = 0;
287 m->m_pkthdr.csum_data = 0;
288 SLIST_INIT(&m->m_pkthdr.tags);
289#ifdef MAC
290 /* If the label init fails, fail the alloc */
291 error = mac_init_mbuf(m, how);
292 if (error)
293 return (error);
294#endif
295 } else
296 m->m_data = m->m_dat;
297 return (0);
298}
299
300/*
301 * The Mbuf master zone destructor.
302 */
303static void
304mb_dtor_mbuf(void *mem, int size, void *arg)
305{
306 struct mbuf *m;
307
308 m = (struct mbuf *)mem;
309 if ((m->m_flags & M_PKTHDR) != 0)
310 m_tag_delete_chain(m, NULL);
311 KASSERT((m->m_flags & M_EXT) == 0, ("%s: M_EXT set", __func__));
312#ifdef INVARIANTS
313 trash_dtor(mem, size, arg);
314#endif
315}
316
317/*
318 * The Mbuf Packet zone destructor.
319 */
320static void
321mb_dtor_pack(void *mem, int size, void *arg)
322{
323 struct mbuf *m;
324
325 m = (struct mbuf *)mem;
326 if ((m->m_flags & M_PKTHDR) != 0)
327 m_tag_delete_chain(m, NULL);
328
329 /* Make sure we've got a clean cluster back. */
330 KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__));
331 KASSERT(m->m_ext.ext_buf != NULL, ("%s: ext_buf == NULL", __func__));
332 KASSERT(m->m_ext.ext_free == NULL, ("%s: ext_free != NULL", __func__));
333 KASSERT(m->m_ext.ext_args == NULL, ("%s: ext_args != NULL", __func__));
334 KASSERT(m->m_ext.ext_size == MCLBYTES, ("%s: ext_size != MCLBYTES", __func__));
335 KASSERT(m->m_ext.ext_type == EXT_PACKET, ("%s: ext_type != EXT_CLUSTER", __func__));
335 KASSERT(m->m_ext.ext_type == EXT_PACKET, ("%s: ext_type != EXT_PACKET", __func__));
336 KASSERT(*m->m_ext.ref_cnt == 1, ("%s: ref_cnt != 1", __func__));
337#ifdef INVARIANTS
338 trash_dtor(m->m_ext.ext_buf, MCLBYTES, arg);
339#endif
340}
341
342/*
343 * The Cluster and Jumbo[9|16] zone constructor.
344 *
345 * Here the 'arg' pointer points to the Mbuf which we
346 * are configuring cluster storage for. If 'arg' is
347 * empty we allocate just the cluster without setting
348 * the mbuf to it. See mbuf.h.
349 */
350static int
351mb_ctor_clust(void *mem, int size, void *arg, int how)
352{
353 struct mbuf *m;
354 u_int *refcnt;
355 int type = 0;
356
357#ifdef INVARIANTS
358 trash_ctor(mem, size, arg, how);
359#endif
360 m = (struct mbuf *)arg;
361 if (m != NULL) {
362 switch (size) {
363 case MCLBYTES:
364 type = EXT_CLUSTER;
365 break;
366 case MJUM9BYTES:
367 type = EXT_JUMBO9;
368 break;
369 case MJUM16BYTES:
370 type = EXT_JUMBO16;
371 break;
372 default:
373 panic("unknown cluster size");
374 break;
375 }
376 m->m_ext.ext_buf = (caddr_t)mem;
377 m->m_data = m->m_ext.ext_buf;
378 m->m_flags |= M_EXT;
379 m->m_ext.ext_free = NULL;
380 m->m_ext.ext_args = NULL;
381 m->m_ext.ext_size = size;
382 m->m_ext.ext_type = type;
383 m->m_ext.ref_cnt = uma_find_refcnt(zone_clust, mem);
384 *m->m_ext.ref_cnt = 1;
385 } else {
386 refcnt = uma_find_refcnt(zone_clust, mem);
387 *refcnt = 1;
388 }
389 return (0);
390}
391
392/*
393 * The Mbuf Cluster zone destructor.
394 */
395static void
396mb_dtor_clust(void *mem, int size, void *arg)
397{
398
399 KASSERT(*(uma_find_refcnt(zone_clust, mem)) <= 1,
400 ("%s: refcnt incorrect %u", __func__,
401 *(uma_find_refcnt(zone_clust, mem))) );
402#ifdef INVARIANTS
403 trash_dtor(mem, size, arg);
404#endif
405}
406
407/*
408 * The Packet secondary zone's init routine, executed on the
409 * object's transition from mbuf keg slab to zone cache.
410 */
411static int
412mb_zinit_pack(void *mem, int size, int how)
413{
414 struct mbuf *m;
415
416 m = (struct mbuf *)mem; /* m is virgin. */
417 uma_zalloc_arg(zone_clust, m, how);
418 if (m->m_ext.ext_buf == NULL)
419 return (ENOMEM);
420 m->m_ext.ext_type = EXT_PACKET; /* Override. */
421#ifdef INVARIANTS
422 trash_init(m->m_ext.ext_buf, MCLBYTES, how);
423#endif
424 return (0);
425}
426
427/*
428 * The Packet secondary zone's fini routine, executed on the
429 * object's transition from zone cache to keg slab.
430 */
431static void
432mb_zfini_pack(void *mem, int size)
433{
434 struct mbuf *m;
435
436 m = (struct mbuf *)mem;
437#ifdef INVARIANTS
438 trash_fini(m->m_ext.ext_buf, MCLBYTES);
439#endif
440 uma_zfree_arg(zone_clust, m->m_ext.ext_buf, NULL);
441#ifdef INVARIANTS
442 trash_dtor(mem, size, NULL);
443#endif
444}
445
446/*
447 * The "packet" keg constructor.
448 */
449static int
450mb_ctor_pack(void *mem, int size, void *arg, int how)
451{
452 struct mbuf *m;
453 struct mb_args *args;
454#ifdef MAC
455 int error;
456#endif
457 int flags;
458 short type;
459
460 m = (struct mbuf *)mem;
461 args = (struct mb_args *)arg;
462 flags = args->flags;
463 type = args->type;
464
465#ifdef INVARIANTS
466 trash_ctor(m->m_ext.ext_buf, MCLBYTES, arg, how);
467#endif
468 m->m_next = NULL;
469 m->m_nextpkt = NULL;
470 m->m_data = m->m_ext.ext_buf;
471 m->m_len = 0;
472 m->m_flags = (flags | M_EXT);
473 m->m_type = type;
474
475 if (flags & M_PKTHDR) {
476 m->m_pkthdr.rcvif = NULL;
477 m->m_pkthdr.len = 0;
478 m->m_pkthdr.header = NULL;
479 m->m_pkthdr.csum_flags = 0;
480 m->m_pkthdr.csum_data = 0;
481 SLIST_INIT(&m->m_pkthdr.tags);
482#ifdef MAC
483 /* If the label init fails, fail the alloc */
484 error = mac_init_mbuf(m, how);
485 if (error)
486 return (error);
487#endif
488 }
489 /* m_ext is already initialized. */
490
491 return (0);
492}
493
494/*
495 * This is the protocol drain routine.
496 *
497 * No locks should be held when this is called. The drain routines have to
498 * presently acquire some locks which raises the possibility of lock order
499 * reversal.
500 */
501static void
502mb_reclaim(void *junk)
503{
504 struct domain *dp;
505 struct protosw *pr;
506
507 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL,
508 "mb_reclaim()");
509
510 for (dp = domains; dp != NULL; dp = dp->dom_next)
511 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
512 if (pr->pr_drain != NULL)
513 (*pr->pr_drain)();
514}
336 KASSERT(*m->m_ext.ref_cnt == 1, ("%s: ref_cnt != 1", __func__));
337#ifdef INVARIANTS
338 trash_dtor(m->m_ext.ext_buf, MCLBYTES, arg);
339#endif
340}
341
342/*
343 * The Cluster and Jumbo[9|16] zone constructor.
344 *
345 * Here the 'arg' pointer points to the Mbuf which we
346 * are configuring cluster storage for. If 'arg' is
347 * empty we allocate just the cluster without setting
348 * the mbuf to it. See mbuf.h.
349 */
350static int
351mb_ctor_clust(void *mem, int size, void *arg, int how)
352{
353 struct mbuf *m;
354 u_int *refcnt;
355 int type = 0;
356
357#ifdef INVARIANTS
358 trash_ctor(mem, size, arg, how);
359#endif
360 m = (struct mbuf *)arg;
361 if (m != NULL) {
362 switch (size) {
363 case MCLBYTES:
364 type = EXT_CLUSTER;
365 break;
366 case MJUM9BYTES:
367 type = EXT_JUMBO9;
368 break;
369 case MJUM16BYTES:
370 type = EXT_JUMBO16;
371 break;
372 default:
373 panic("unknown cluster size");
374 break;
375 }
376 m->m_ext.ext_buf = (caddr_t)mem;
377 m->m_data = m->m_ext.ext_buf;
378 m->m_flags |= M_EXT;
379 m->m_ext.ext_free = NULL;
380 m->m_ext.ext_args = NULL;
381 m->m_ext.ext_size = size;
382 m->m_ext.ext_type = type;
383 m->m_ext.ref_cnt = uma_find_refcnt(zone_clust, mem);
384 *m->m_ext.ref_cnt = 1;
385 } else {
386 refcnt = uma_find_refcnt(zone_clust, mem);
387 *refcnt = 1;
388 }
389 return (0);
390}
391
392/*
393 * The Mbuf Cluster zone destructor.
394 */
395static void
396mb_dtor_clust(void *mem, int size, void *arg)
397{
398
399 KASSERT(*(uma_find_refcnt(zone_clust, mem)) <= 1,
400 ("%s: refcnt incorrect %u", __func__,
401 *(uma_find_refcnt(zone_clust, mem))) );
402#ifdef INVARIANTS
403 trash_dtor(mem, size, arg);
404#endif
405}
406
407/*
408 * The Packet secondary zone's init routine, executed on the
409 * object's transition from mbuf keg slab to zone cache.
410 */
411static int
412mb_zinit_pack(void *mem, int size, int how)
413{
414 struct mbuf *m;
415
416 m = (struct mbuf *)mem; /* m is virgin. */
417 uma_zalloc_arg(zone_clust, m, how);
418 if (m->m_ext.ext_buf == NULL)
419 return (ENOMEM);
420 m->m_ext.ext_type = EXT_PACKET; /* Override. */
421#ifdef INVARIANTS
422 trash_init(m->m_ext.ext_buf, MCLBYTES, how);
423#endif
424 return (0);
425}
426
427/*
428 * The Packet secondary zone's fini routine, executed on the
429 * object's transition from zone cache to keg slab.
430 */
431static void
432mb_zfini_pack(void *mem, int size)
433{
434 struct mbuf *m;
435
436 m = (struct mbuf *)mem;
437#ifdef INVARIANTS
438 trash_fini(m->m_ext.ext_buf, MCLBYTES);
439#endif
440 uma_zfree_arg(zone_clust, m->m_ext.ext_buf, NULL);
441#ifdef INVARIANTS
442 trash_dtor(mem, size, NULL);
443#endif
444}
445
446/*
447 * The "packet" keg constructor.
448 */
449static int
450mb_ctor_pack(void *mem, int size, void *arg, int how)
451{
452 struct mbuf *m;
453 struct mb_args *args;
454#ifdef MAC
455 int error;
456#endif
457 int flags;
458 short type;
459
460 m = (struct mbuf *)mem;
461 args = (struct mb_args *)arg;
462 flags = args->flags;
463 type = args->type;
464
465#ifdef INVARIANTS
466 trash_ctor(m->m_ext.ext_buf, MCLBYTES, arg, how);
467#endif
468 m->m_next = NULL;
469 m->m_nextpkt = NULL;
470 m->m_data = m->m_ext.ext_buf;
471 m->m_len = 0;
472 m->m_flags = (flags | M_EXT);
473 m->m_type = type;
474
475 if (flags & M_PKTHDR) {
476 m->m_pkthdr.rcvif = NULL;
477 m->m_pkthdr.len = 0;
478 m->m_pkthdr.header = NULL;
479 m->m_pkthdr.csum_flags = 0;
480 m->m_pkthdr.csum_data = 0;
481 SLIST_INIT(&m->m_pkthdr.tags);
482#ifdef MAC
483 /* If the label init fails, fail the alloc */
484 error = mac_init_mbuf(m, how);
485 if (error)
486 return (error);
487#endif
488 }
489 /* m_ext is already initialized. */
490
491 return (0);
492}
493
494/*
495 * This is the protocol drain routine.
496 *
497 * No locks should be held when this is called. The drain routines have to
498 * presently acquire some locks which raises the possibility of lock order
499 * reversal.
500 */
501static void
502mb_reclaim(void *junk)
503{
504 struct domain *dp;
505 struct protosw *pr;
506
507 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL,
508 "mb_reclaim()");
509
510 for (dp = domains; dp != NULL; dp = dp->dom_next)
511 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
512 if (pr->pr_drain != NULL)
513 (*pr->pr_drain)();
514}