]>
Commit | Line | Data |
---|---|---|
b7080c8e | 1 | /* |
fdfd5971 | 2 | * Copyright (c) 2008-2010 Apple Inc. All rights reserved. |
b7080c8e | 3 | * |
9c859447 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
b7080c8e | 5 | * |
9c859447 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
b7080c8e | 14 | * |
9c859447 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
b7080c8e A |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
9c859447 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
b7080c8e | 25 | * |
9c859447 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
b7080c8e A |
27 | */ |
28 | /* | |
29 | * Copyright (c) 1983, 1988, 1993 | |
30 | * The Regents of the University of California. All rights reserved. | |
31 | * | |
32 | * Redistribution and use in source and binary forms, with or without | |
33 | * modification, are permitted provided that the following conditions | |
34 | * are met: | |
35 | * 1. Redistributions of source code must retain the above copyright | |
36 | * notice, this list of conditions and the following disclaimer. | |
37 | * 2. Redistributions in binary form must reproduce the above copyright | |
38 | * notice, this list of conditions and the following disclaimer in the | |
39 | * documentation and/or other materials provided with the distribution. | |
40 | * 3. All advertising materials mentioning features or use of this software | |
41 | * must display the following acknowledgement: | |
42 | * This product includes software developed by the University of | |
43 | * California, Berkeley and its contributors. | |
44 | * 4. Neither the name of the University nor the names of its contributors | |
45 | * may be used to endorse or promote products derived from this software | |
46 | * without specific prior written permission. | |
47 | * | |
48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
58 | * SUCH DAMAGE. | |
59 | */ | |
60 | ||
61 | ||
62 | #include <sys/param.h> | |
b7080c8e A |
63 | #include <sys/socket.h> |
64 | #include <sys/mbuf.h> | |
2b484d24 | 65 | #include <sys/sysctl.h> |
b7080c8e A |
66 | |
67 | #include <stdio.h> | |
fdfd5971 | 68 | #include <string.h> |
b8dff150 A |
69 | #include <stdlib.h> |
70 | #include <errno.h> | |
b7080c8e | 71 | #include "netstat.h" |
b7080c8e A |
72 | |
73 | #define YES 1 | |
74 | typedef int bool; | |
75 | ||
76 | struct mbstat mbstat; | |
77 | ||
78 | static struct mbtypes { | |
79 | int mt_type; | |
80 | char *mt_name; | |
81 | } mbtypes[] = { | |
82 | { MT_DATA, "data" }, | |
83 | { MT_OOBDATA, "oob data" }, | |
84 | { MT_CONTROL, "ancillary data" }, | |
85 | { MT_HEADER, "packet headers" }, | |
86 | { MT_SOCKET, "socket structures" }, /* XXX */ | |
87 | { MT_PCB, "protocol control blocks" }, /* XXX */ | |
88 | { MT_RTABLE, "routing table entries" }, /* XXX */ | |
89 | { MT_HTABLE, "IMP host table entries" }, /* XXX */ | |
90 | { MT_ATABLE, "address resolution tables" }, | |
91 | { MT_FTABLE, "fragment reassembly queue headers" }, /* XXX */ | |
92 | { MT_SONAME, "socket names and addresses" }, | |
93 | { MT_SOOPTS, "socket options" }, | |
94 | { MT_RIGHTS, "access rights" }, | |
95 | { MT_IFADDR, "interface addresses" }, /* XXX */ | |
b8dff150 | 96 | { MT_TAG, "packet tags" }, /* XXX */ |
b7080c8e A |
97 | { 0, 0 } |
98 | }; | |
99 | ||
100 | int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(short); | |
101 | bool seen[256]; /* "have we seen this type yet?" */ | |
102 | ||
b8dff150 A |
103 | mb_stat_t *mb_stat; |
104 | unsigned int njcl, njclbytes; | |
fdfd5971 A |
105 | mleak_stat_t *mleak_stat; |
106 | struct mleak_table table; | |
b8dff150 A |
107 | |
108 | #define KERN_IPC_MB_STAT "kern.ipc.mb_stat" | |
109 | #define KERN_IPC_NJCL "kern.ipc.njcl" | |
110 | #define KERN_IPC_NJCL_BYTES "kern.ipc.njclbytes" | |
fdfd5971 A |
111 | #define KERN_IPC_MLEAK_TABLE "kern.ipc.mleak_table" |
112 | #define KERN_IPC_MLEAK_TOP_TRACE "kern.ipc.mleak_top_trace" | |
b8dff150 A |
113 | |
114 | #define MB_STAT_HDR1 "\ | |
115 | class buf active ctotal total cache cached uncached memory\n\ | |
116 | name size bufs bufs bufs state bufs bufs usage\n\ | |
117 | ---------- ----- -------- -------- -------- ----- -------- -------- ---------\n\ | |
118 | " | |
119 | ||
120 | #define MB_STAT_HDR2 "\n\ | |
121 | class waiter notify purge wretry nwretry failure\n\ | |
122 | name count count count count count count\n\ | |
123 | ---------- -------- -------- -------- -------- -------- --------\n\ | |
124 | " | |
125 | ||
fdfd5971 A |
126 | #define MB_LEAK_HDR "\n\ |
127 | calltrace [1] calltrace [2] calltrace [3] calltrace [4] calltrace [5] \n\ | |
128 | ------------------ ------------------ ------------------ ------------------ ------------------ \n\ | |
129 | " | |
130 | ||
131 | #define MB_LEAK_SPACING " " | |
b8dff150 A |
132 | static const char *mbpr_state(int); |
133 | static const char *mbpr_mem(u_int32_t); | |
134 | static int mbpr_getdata(void); | |
135 | ||
b7080c8e A |
136 | /* |
137 | * Print mbuf statistics. | |
138 | */ | |
139 | void | |
2b484d24 | 140 | mbpr(void) |
b7080c8e | 141 | { |
342c141e | 142 | unsigned long totmem = 0, totfree = 0, totmbufs, totused, totreturned = 0; |
b8dff150 A |
143 | double totpct; |
144 | u_int32_t m_msize, m_mbufs = 0, m_clfree = 0, m_bigclfree = 0; | |
145 | u_int32_t m_mbufclfree = 0, m_mbufbigclfree = 0; | |
146 | u_int32_t m_16kclusters = 0, m_16kclfree = 0, m_mbuf16kclfree = 0; | |
2b484d24 A |
147 | int i; |
148 | struct mbtypes *mp; | |
b8dff150 | 149 | mb_class_stat_t *cp; |
b7080c8e | 150 | |
b8dff150 | 151 | if (mbpr_getdata() != 0) |
b7080c8e | 152 | return; |
b8dff150 A |
153 | |
154 | m_msize = mbstat.m_msize; | |
155 | cp = &mb_stat->mbs_class[0]; | |
156 | for (i = 0; i < mb_stat->mbs_cnt; i++, cp++) { | |
157 | if (cp->mbcl_size == m_msize) { | |
158 | m_mbufs = cp->mbcl_active; | |
159 | } else if (cp->mbcl_size == mbstat.m_mclbytes) { | |
160 | m_clfree = cp->mbcl_total - cp->mbcl_active; | |
161 | } else if (cp->mbcl_size == mbstat.m_bigmclbytes) { | |
162 | m_bigclfree = cp->mbcl_total - cp->mbcl_active; | |
163 | } else if (njcl > 0 && cp->mbcl_size == njclbytes) { | |
164 | m_16kclfree = cp->mbcl_total - cp->mbcl_active; | |
165 | m_16kclusters = cp->mbcl_total; | |
166 | } else if (cp->mbcl_size == (m_msize + mbstat.m_mclbytes)) { | |
167 | m_mbufclfree = cp->mbcl_total - cp->mbcl_active; | |
168 | } else if (cp->mbcl_size == (m_msize + mbstat.m_bigmclbytes)) { | |
169 | m_mbufbigclfree = cp->mbcl_total - cp->mbcl_active; | |
170 | } else if (njcl > 0 && cp->mbcl_size == (m_msize + njclbytes)) { | |
171 | m_mbuf16kclfree = cp->mbcl_total - cp->mbcl_active; | |
172 | } | |
b7080c8e | 173 | } |
b8dff150 A |
174 | |
175 | /* adjust free counts to include composite caches */ | |
176 | m_clfree += m_mbufclfree; | |
177 | m_bigclfree += m_mbufbigclfree; | |
178 | m_16kclfree += m_mbuf16kclfree; | |
179 | ||
180 | cp = &mb_stat->mbs_class[0]; | |
181 | for (i = 0; i < mb_stat->mbs_cnt; i++, cp++) { | |
182 | u_int32_t mem; | |
183 | ||
184 | mem = cp->mbcl_ctotal * cp->mbcl_size; | |
185 | totmem += mem; | |
342c141e | 186 | totreturned += cp->mbcl_release_cnt; |
b8dff150 A |
187 | totfree += (cp->mbcl_mc_cached + cp->mbcl_infree) * |
188 | cp->mbcl_size; | |
189 | if (mflag > 1) { | |
190 | if (i == 0) | |
191 | printf(MB_STAT_HDR1); | |
192 | ||
193 | if (njcl == 0 && | |
194 | cp->mbcl_size > (m_msize + mbstat.m_bigmclbytes)) | |
195 | continue; | |
196 | ||
197 | printf("%-10s %5u %8u %8u %8u %5s %8u %8u %9s\n", | |
198 | cp->mbcl_cname, cp->mbcl_size, cp->mbcl_active, | |
199 | cp->mbcl_ctotal, cp->mbcl_total, | |
200 | mbpr_state(cp->mbcl_mc_state), cp->mbcl_mc_cached, | |
201 | cp->mbcl_infree, mbpr_mem(mem)); | |
202 | } | |
203 | } | |
204 | ||
205 | cp = &mb_stat->mbs_class[0]; | |
206 | for (i = 0; i < mb_stat->mbs_cnt; i++, cp++) { | |
207 | if (mflag > 2) { | |
208 | if (i == 0) | |
209 | printf(MB_STAT_HDR2); | |
210 | ||
211 | if (njcl == 0 && | |
212 | cp->mbcl_size > (m_msize + mbstat.m_bigmclbytes)) | |
213 | continue; | |
214 | ||
215 | printf("%-10s %8u %8llu %8llu %8u %8u %8llu\n", | |
216 | cp->mbcl_cname, cp->mbcl_mc_waiter_cnt, | |
217 | cp->mbcl_notified, cp->mbcl_purge_cnt, | |
218 | cp->mbcl_mc_wretry_cnt, cp->mbcl_mc_nwretry_cnt, | |
219 | cp->mbcl_fail_cnt); | |
220 | } | |
221 | } | |
222 | ||
223 | if (mflag > 1) | |
224 | printf("\n"); | |
b7080c8e A |
225 | |
226 | totmbufs = 0; | |
227 | for (mp = mbtypes; mp->mt_name; mp++) | |
228 | totmbufs += mbstat.m_mtypes[mp->mt_type]; | |
b8dff150 A |
229 | /* |
230 | * These stats are not updated atomically in the kernel; | |
231 | * adjust the total as neeeded. | |
232 | */ | |
233 | if (totmbufs > m_mbufs) | |
234 | totmbufs = m_mbufs; | |
235 | printf("%lu/%u mbufs in use:\n", totmbufs, m_mbufs); | |
b7080c8e A |
236 | for (mp = mbtypes; mp->mt_name; mp++) |
237 | if (mbstat.m_mtypes[mp->mt_type]) { | |
238 | seen[mp->mt_type] = YES; | |
239 | printf("\t%u mbufs allocated to %s\n", | |
240 | mbstat.m_mtypes[mp->mt_type], mp->mt_name); | |
241 | } | |
242 | seen[MT_FREE] = YES; | |
243 | for (i = 0; i < nmbtypes; i++) | |
244 | if (!seen[i] && mbstat.m_mtypes[i]) { | |
245 | printf("\t%u mbufs allocated to <mbuf type %d>\n", | |
246 | mbstat.m_mtypes[i], i); | |
247 | } | |
b8dff150 A |
248 | if ((m_mbufs - totmbufs) > 0) |
249 | printf("\t%lu mbufs allocated to caches\n", | |
250 | m_mbufs - totmbufs); | |
251 | printf("%u/%u mbuf 2KB clusters in use\n", | |
252 | (unsigned int)(mbstat.m_clusters - m_clfree), | |
b7080c8e | 253 | (unsigned int)mbstat.m_clusters); |
2b484d24 | 254 | printf("%u/%u mbuf 4KB clusters in use\n", |
b8dff150 | 255 | (unsigned int)(mbstat.m_bigclusters - m_bigclfree), |
2b484d24 | 256 | (unsigned int)mbstat.m_bigclusters); |
b8dff150 A |
257 | if (njcl > 0) { |
258 | printf("%u/%u mbuf %uKB clusters in use\n", | |
259 | m_16kclusters - m_16kclfree, m_16kclusters, | |
260 | njclbytes/1024); | |
261 | } | |
262 | totused = totmem - totfree; | |
263 | if (totmem == 0) | |
264 | totpct = 0; | |
265 | else if (totused < (ULONG_MAX/100)) | |
266 | totpct = (totused * 100)/(double)totmem; | |
267 | else { | |
268 | u_long totmem1 = totmem/100; | |
269 | u_long totused1 = totused/100; | |
270 | totpct = (totused1 * 100)/(double)totmem1; | |
271 | } | |
272 | printf("%lu KB allocated to network (%.1f%% in use)\n", | |
273 | totmem / 1024, totpct); | |
342c141e | 274 | printf("%lu KB returned to the system\n", totreturned / 1024); |
b8dff150 A |
275 | |
276 | printf("%u requests for memory denied\n", (unsigned int)mbstat.m_drops); | |
b7080c8e | 277 | printf("%u requests for memory delayed\n", (unsigned int)mbstat.m_wait); |
b8dff150 A |
278 | printf("%u calls to drain routines\n", (unsigned int)mbstat.m_drain); |
279 | ||
280 | free(mb_stat); | |
fdfd5971 A |
281 | mb_stat = NULL; |
282 | ||
283 | if (mleak_stat != NULL) { | |
284 | mleak_trace_stat_t *mltr; | |
285 | ||
286 | printf("\nmbuf leak detection table:\n"); | |
287 | printf("\ttotal captured: %u (one per %u)\n" | |
288 | "\ttotal allocs outstanding: %llu\n" | |
289 | "\tnew hash recorded: %llu allocs, %llu traces\n" | |
290 | "\thash collisions: %llu allocs, %llu traces\n" | |
291 | "\toverwrites: %llu allocs, %llu traces\n" | |
292 | "\tlock conflicts: %llu\n\n", | |
293 | table.mleak_capture / table.mleak_sample_factor, | |
294 | table.mleak_sample_factor, | |
295 | table.outstanding_allocs, | |
296 | table.alloc_recorded, table.trace_recorded, | |
297 | table.alloc_collisions, table.trace_collisions, | |
298 | table.alloc_overwrites, table.trace_overwrites, | |
299 | table.total_conflicts); | |
300 | ||
301 | printf("top %d outstanding traces:\n", mleak_stat->ml_cnt); | |
302 | for (i = 0; i < mleak_stat->ml_cnt; i++) { | |
303 | mltr = &mleak_stat->ml_trace[i]; | |
304 | printf("[%d] %llu outstanding alloc(s), " | |
305 | "%llu hit(s), %llu collision(s)\n", (i + 1), | |
306 | mltr->mltr_allocs, mltr->mltr_hitcount, | |
307 | mltr->mltr_collisions); | |
308 | } | |
309 | ||
310 | printf(MB_LEAK_HDR); | |
311 | for (i = 0; i < MLEAK_STACK_DEPTH; i++) { | |
312 | int j; | |
313 | ||
314 | printf("%2d: ", (i + 1)); | |
315 | for (j = 0; j < mleak_stat->ml_cnt; j++) { | |
316 | mltr = &mleak_stat->ml_trace[j]; | |
317 | if (i < mltr->mltr_depth) { | |
318 | if (mleak_stat->ml_isaddr64) { | |
319 | printf("0x%0llx ", | |
320 | mltr->mltr_addr[i]); | |
321 | } else { | |
322 | printf("0x%08x ", | |
323 | (u_int32_t)mltr->mltr_addr[i]); | |
324 | } | |
325 | } else { | |
326 | printf(MB_LEAK_SPACING); | |
327 | } | |
328 | } | |
329 | printf("\n"); | |
330 | } | |
331 | free(mleak_stat); | |
332 | mleak_stat = NULL; | |
333 | } | |
b8dff150 A |
334 | } |
335 | ||
336 | static const char * | |
337 | mbpr_state(int state) | |
338 | { | |
339 | char *msg = "?"; | |
340 | ||
341 | switch (state) { | |
342 | case MCS_DISABLED: | |
343 | msg = "dis"; | |
344 | break; | |
345 | ||
346 | case MCS_ONLINE: | |
347 | msg = "on"; | |
348 | break; | |
349 | ||
350 | case MCS_PURGING: | |
351 | msg = "purge"; | |
352 | break; | |
353 | ||
354 | case MCS_OFFLINE: | |
355 | msg = "off"; | |
356 | break; | |
357 | } | |
358 | return (msg); | |
359 | } | |
360 | ||
361 | static const char * | |
362 | mbpr_mem(u_int32_t bytes) | |
363 | { | |
364 | static char buf[33]; | |
365 | double mem = bytes; | |
366 | ||
367 | if (mem < 1024) { | |
368 | (void) snprintf(buf, sizeof (buf), "%d", (int)mem); | |
369 | } else if ((mem /= 1024) < 1024) { | |
370 | (void) snprintf(buf, sizeof (buf), "%.1f KB", mem); | |
371 | } else { | |
372 | mem /= 1024; | |
373 | (void) snprintf(buf, sizeof (buf), "%.1f MB", mem); | |
374 | } | |
375 | return (buf); | |
376 | } | |
377 | ||
378 | static int | |
379 | mbpr_getdata(void) | |
380 | { | |
381 | size_t len; | |
382 | int error = -1; | |
383 | ||
384 | if (nmbtypes != 256) { | |
385 | (void) fprintf(stderr, | |
386 | "netstat: unexpected change to mbstat; check source\n"); | |
387 | goto done; | |
388 | } | |
389 | ||
390 | len = sizeof(mbstat); | |
391 | if (sysctlbyname("kern.ipc.mbstat", &mbstat, &len, 0, 0) == -1) | |
392 | goto done; | |
393 | ||
394 | if (sysctlbyname(KERN_IPC_MB_STAT, NULL, &len, 0, 0) == -1) { | |
395 | (void) fprintf(stderr, | |
396 | "Error retrieving length for %s\n", KERN_IPC_MB_STAT); | |
397 | goto done; | |
398 | } | |
399 | ||
400 | mb_stat = calloc(1, len); | |
401 | if (mb_stat == NULL) { | |
402 | (void) fprintf(stderr, | |
403 | "Error allocating %lu bytes for sysctl data\n", len); | |
404 | goto done; | |
405 | } | |
406 | ||
407 | if (sysctlbyname(KERN_IPC_MB_STAT, mb_stat, &len, 0, 0) == -1) { | |
408 | (void) fprintf(stderr, | |
409 | "Error %d getting %s\n", errno, KERN_IPC_MB_STAT); | |
410 | goto done; | |
411 | } | |
412 | ||
413 | if (mb_stat->mbs_cnt == 0) { | |
414 | (void) fprintf(stderr, | |
415 | "Invalid mbuf class count (%d)\n", mb_stat->mbs_cnt); | |
416 | goto done; | |
417 | } | |
418 | ||
fdfd5971 A |
419 | /* mbuf leak detection! */ |
420 | if (mflag > 3) { | |
421 | errno = 0; | |
422 | len = sizeof (table); | |
423 | if (sysctlbyname(KERN_IPC_MLEAK_TABLE, &table, &len, 0, 0) == | |
424 | -1 && errno != ENXIO) { | |
425 | (void) fprintf(stderr, "error %d getting %s\n", errno, | |
426 | KERN_IPC_MLEAK_TABLE); | |
427 | goto done; | |
428 | } else if (errno == ENXIO) { | |
429 | (void) fprintf(stderr, "mbuf leak detection is not " | |
430 | "enabled in the kernel.\n"); | |
431 | goto skip; | |
432 | } | |
433 | ||
434 | if (sysctlbyname(KERN_IPC_MLEAK_TOP_TRACE, NULL, &len, | |
435 | 0, 0) == -1) { | |
436 | (void) fprintf(stderr, "Error retrieving length for " | |
437 | "%s: %d\n", KERN_IPC_MB_STAT, errno); | |
438 | goto done; | |
439 | } | |
440 | ||
441 | mleak_stat = calloc(1, len); | |
442 | if (mleak_stat == NULL) { | |
443 | (void) fprintf(stderr, "Error allocating %lu bytes " | |
444 | "for sysctl data\n", len); | |
445 | goto done; | |
446 | } | |
447 | ||
448 | if (sysctlbyname(KERN_IPC_MLEAK_TOP_TRACE, mleak_stat, &len, | |
449 | 0, 0) == -1) { | |
450 | (void) fprintf(stderr, "error %d getting %s\n", errno, | |
451 | KERN_IPC_MLEAK_TOP_TRACE); | |
452 | goto done; | |
453 | } | |
454 | } | |
455 | ||
456 | skip: | |
b8dff150 A |
457 | len = sizeof (njcl); |
458 | (void) sysctlbyname(KERN_IPC_NJCL, &njcl, &len, 0, 0); | |
459 | len = sizeof (njclbytes); | |
460 | (void) sysctlbyname(KERN_IPC_NJCL_BYTES, &njclbytes, &len, 0, 0); | |
461 | ||
462 | error = 0; | |
463 | ||
464 | done: | |
fdfd5971 | 465 | if (error != 0 && mb_stat != NULL) { |
b8dff150 | 466 | free(mb_stat); |
fdfd5971 A |
467 | mb_stat = NULL; |
468 | } | |
469 | ||
470 | if (error != 0 && mleak_stat != NULL) { | |
471 | free(mleak_stat); | |
472 | mleak_stat = NULL; | |
473 | } | |
b8dff150 A |
474 | |
475 | return (error); | |
b7080c8e | 476 | } |