1*2dac8a3eSMatthew Dillon /*
2*2dac8a3eSMatthew Dillon * VMPQINACTIVE.C
3*2dac8a3eSMatthew Dillon *
4*2dac8a3eSMatthew Dillon * cc -I/usr/src/sys vmpqinactive.c -o ~/bin/vmpqinactive -lkvm
5*2dac8a3eSMatthew Dillon *
6*2dac8a3eSMatthew Dillon * vmpqinactive
7*2dac8a3eSMatthew Dillon *
8*2dac8a3eSMatthew Dillon * Calculate how many inactive pages are dirty
9*2dac8a3eSMatthew Dillon *
10*2dac8a3eSMatthew Dillon * Copyright (c) 2004-2020 The DragonFly Project. All rights reserved.
11*2dac8a3eSMatthew Dillon *
12*2dac8a3eSMatthew Dillon * This code is derived from software contributed to The DragonFly Project
13*2dac8a3eSMatthew Dillon * by Matthew Dillon <dillon@backplane.com>
14*2dac8a3eSMatthew Dillon *
15*2dac8a3eSMatthew Dillon * Redistribution and use in source and binary forms, with or without
16*2dac8a3eSMatthew Dillon * modification, are permitted provided that the following conditions
17*2dac8a3eSMatthew Dillon * are met:
18*2dac8a3eSMatthew Dillon *
19*2dac8a3eSMatthew Dillon * 1. Redistributions of source code must retain the above copyright
20*2dac8a3eSMatthew Dillon * notice, this list of conditions and the following disclaimer.
21*2dac8a3eSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
22*2dac8a3eSMatthew Dillon * notice, this list of conditions and the following disclaimer in
23*2dac8a3eSMatthew Dillon * the documentation and/or other materials provided with the
24*2dac8a3eSMatthew Dillon * distribution.
25*2dac8a3eSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
26*2dac8a3eSMatthew Dillon * contributors may be used to endorse or promote products derived
27*2dac8a3eSMatthew Dillon * from this software without specific, prior written permission.
28*2dac8a3eSMatthew Dillon *
29*2dac8a3eSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30*2dac8a3eSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31*2dac8a3eSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32*2dac8a3eSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33*2dac8a3eSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34*2dac8a3eSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
35*2dac8a3eSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36*2dac8a3eSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
37*2dac8a3eSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38*2dac8a3eSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
39*2dac8a3eSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40*2dac8a3eSMatthew Dillon * SUCH DAMAGE.
41*2dac8a3eSMatthew Dillon */
42*2dac8a3eSMatthew Dillon
43*2dac8a3eSMatthew Dillon #define _KERNEL_STRUCTURES_
44*2dac8a3eSMatthew Dillon #include <sys/param.h>
45*2dac8a3eSMatthew Dillon #include <sys/user.h>
46*2dac8a3eSMatthew Dillon #include <sys/malloc.h>
47*2dac8a3eSMatthew Dillon #include <sys/signalvar.h>
48*2dac8a3eSMatthew Dillon #include <sys/vnode.h>
49*2dac8a3eSMatthew Dillon #include <sys/buf.h>
50*2dac8a3eSMatthew Dillon #include <sys/namecache.h>
51*2dac8a3eSMatthew Dillon #include <sys/slaballoc.h>
52*2dac8a3eSMatthew Dillon
53*2dac8a3eSMatthew Dillon #include <vm/vm.h>
54*2dac8a3eSMatthew Dillon #include <vm/vm_page.h>
55*2dac8a3eSMatthew Dillon #include <vm/vm_kern.h>
56*2dac8a3eSMatthew Dillon #include <vm/vm_object.h>
57*2dac8a3eSMatthew Dillon #include <vm/swap_pager.h>
58*2dac8a3eSMatthew Dillon #include <vm/vnode_pager.h>
59*2dac8a3eSMatthew Dillon
60*2dac8a3eSMatthew Dillon #include <stdio.h>
61*2dac8a3eSMatthew Dillon #include <stdlib.h>
62*2dac8a3eSMatthew Dillon #include <string.h>
63*2dac8a3eSMatthew Dillon #include <fcntl.h>
64*2dac8a3eSMatthew Dillon #include <kvm.h>
65*2dac8a3eSMatthew Dillon #include <nlist.h>
66*2dac8a3eSMatthew Dillon #include <getopt.h>
67*2dac8a3eSMatthew Dillon
68*2dac8a3eSMatthew Dillon struct nlist Nl[] = {
69*2dac8a3eSMatthew Dillon { "_vm_page_array" },
70*2dac8a3eSMatthew Dillon { "_vm_page_array_size" },
71*2dac8a3eSMatthew Dillon { "_kernel_object" },
72*2dac8a3eSMatthew Dillon { "_nbuf" },
73*2dac8a3eSMatthew Dillon { "_nswbuf_mem" },
74*2dac8a3eSMatthew Dillon { "_nswbuf_kva" },
75*2dac8a3eSMatthew Dillon { "_nswbuf_raw" },
76*2dac8a3eSMatthew Dillon { "_kernbase" },
77*2dac8a3eSMatthew Dillon { "__end" },
78*2dac8a3eSMatthew Dillon { NULL }
79*2dac8a3eSMatthew Dillon };
80*2dac8a3eSMatthew Dillon
81*2dac8a3eSMatthew Dillon int debugopt;
82*2dac8a3eSMatthew Dillon int verboseopt;
83*2dac8a3eSMatthew Dillon #if 0
84*2dac8a3eSMatthew Dillon struct vm_page **vm_page_buckets;
85*2dac8a3eSMatthew Dillon int vm_page_hash_mask;
86*2dac8a3eSMatthew Dillon #endif
87*2dac8a3eSMatthew Dillon struct vm_page *vm_page_array;
88*2dac8a3eSMatthew Dillon struct vm_object *kernel_object_ptr;
89*2dac8a3eSMatthew Dillon int vm_page_array_size;
90*2dac8a3eSMatthew Dillon long nbuf;
91*2dac8a3eSMatthew Dillon long nswbuf_mem;
92*2dac8a3eSMatthew Dillon long nswbuf_kva;
93*2dac8a3eSMatthew Dillon long nswbuf_raw;
94*2dac8a3eSMatthew Dillon long kern_size;
95*2dac8a3eSMatthew Dillon
96*2dac8a3eSMatthew Dillon void checkpage(kvm_t *kd, vm_page_t mptr, vm_page_t m, struct vm_object *obj);
97*2dac8a3eSMatthew Dillon static void kkread_vmpage(kvm_t *kd, u_long addr, vm_page_t m);
98*2dac8a3eSMatthew Dillon static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
99*2dac8a3eSMatthew Dillon static int kkread_err(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
100*2dac8a3eSMatthew Dillon
101*2dac8a3eSMatthew Dillon #if 0
102*2dac8a3eSMatthew Dillon static void addsltrack(vm_page_t m);
103*2dac8a3eSMatthew Dillon static void dumpsltrack(kvm_t *kd);
104*2dac8a3eSMatthew Dillon #endif
105*2dac8a3eSMatthew Dillon static int unique_object(void *ptr);
106*2dac8a3eSMatthew Dillon
107*2dac8a3eSMatthew Dillon long count_free;
108*2dac8a3eSMatthew Dillon long count_wired; /* total */
109*2dac8a3eSMatthew Dillon long count_wired_vnode;
110*2dac8a3eSMatthew Dillon long count_wired_anon;
111*2dac8a3eSMatthew Dillon long count_wired_in_pmap;
112*2dac8a3eSMatthew Dillon long count_wired_pgtable;
113*2dac8a3eSMatthew Dillon long count_wired_other;
114*2dac8a3eSMatthew Dillon long count_wired_kernel;
115*2dac8a3eSMatthew Dillon long count_wired_obj_other;
116*2dac8a3eSMatthew Dillon
117*2dac8a3eSMatthew Dillon long count_anon;
118*2dac8a3eSMatthew Dillon long count_anon_in_pmap;
119*2dac8a3eSMatthew Dillon long count_vnode;
120*2dac8a3eSMatthew Dillon long count_device;
121*2dac8a3eSMatthew Dillon long count_phys;
122*2dac8a3eSMatthew Dillon long count_kernel;
123*2dac8a3eSMatthew Dillon long count_unknown;
124*2dac8a3eSMatthew Dillon long count_noobj_offqueue;
125*2dac8a3eSMatthew Dillon long count_noobj_onqueue;
126*2dac8a3eSMatthew Dillon
127*2dac8a3eSMatthew Dillon int
main(int ac,char ** av)128*2dac8a3eSMatthew Dillon main(int ac, char **av)
129*2dac8a3eSMatthew Dillon {
130*2dac8a3eSMatthew Dillon const char *corefile = NULL;
131*2dac8a3eSMatthew Dillon const char *sysfile = NULL;
132*2dac8a3eSMatthew Dillon struct vm_page m;
133*2dac8a3eSMatthew Dillon struct vm_object obj;
134*2dac8a3eSMatthew Dillon kvm_t *kd;
135*2dac8a3eSMatthew Dillon int ch;
136*2dac8a3eSMatthew Dillon #if 0
137*2dac8a3eSMatthew Dillon vm_page_t mptr;
138*2dac8a3eSMatthew Dillon int hv;
139*2dac8a3eSMatthew Dillon #endif
140*2dac8a3eSMatthew Dillon int i;
141*2dac8a3eSMatthew Dillon const char *qstr;
142*2dac8a3eSMatthew Dillon const char *ostr;
143*2dac8a3eSMatthew Dillon long pqinactive_clean;
144*2dac8a3eSMatthew Dillon long pqinactive_dirty1;
145*2dac8a3eSMatthew Dillon long pqinactive_dirty2;
146*2dac8a3eSMatthew Dillon long pqinactive_refd;
147*2dac8a3eSMatthew Dillon long pqinactive_ready;
148*2dac8a3eSMatthew Dillon
149*2dac8a3eSMatthew Dillon pqinactive_clean = 0;
150*2dac8a3eSMatthew Dillon pqinactive_dirty1 = 0;
151*2dac8a3eSMatthew Dillon pqinactive_dirty2 = 0;
152*2dac8a3eSMatthew Dillon pqinactive_refd = 0;
153*2dac8a3eSMatthew Dillon pqinactive_ready = 0;
154*2dac8a3eSMatthew Dillon
155*2dac8a3eSMatthew Dillon while ((ch = getopt(ac, av, "M:N:dv")) != -1) {
156*2dac8a3eSMatthew Dillon switch(ch) {
157*2dac8a3eSMatthew Dillon case 'd':
158*2dac8a3eSMatthew Dillon ++debugopt;
159*2dac8a3eSMatthew Dillon break;
160*2dac8a3eSMatthew Dillon case 'v':
161*2dac8a3eSMatthew Dillon ++verboseopt;
162*2dac8a3eSMatthew Dillon break;
163*2dac8a3eSMatthew Dillon case 'M':
164*2dac8a3eSMatthew Dillon corefile = optarg;
165*2dac8a3eSMatthew Dillon break;
166*2dac8a3eSMatthew Dillon case 'N':
167*2dac8a3eSMatthew Dillon sysfile = optarg;
168*2dac8a3eSMatthew Dillon break;
169*2dac8a3eSMatthew Dillon default:
170*2dac8a3eSMatthew Dillon fprintf(stderr, "%s [-M core] [-N system]\n", av[0]);
171*2dac8a3eSMatthew Dillon exit(1);
172*2dac8a3eSMatthew Dillon }
173*2dac8a3eSMatthew Dillon }
174*2dac8a3eSMatthew Dillon ac -= optind;
175*2dac8a3eSMatthew Dillon av += optind;
176*2dac8a3eSMatthew Dillon
177*2dac8a3eSMatthew Dillon if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) {
178*2dac8a3eSMatthew Dillon perror("kvm_open");
179*2dac8a3eSMatthew Dillon exit(1);
180*2dac8a3eSMatthew Dillon }
181*2dac8a3eSMatthew Dillon if (kvm_nlist(kd, Nl) != 0) {
182*2dac8a3eSMatthew Dillon perror("kvm_nlist");
183*2dac8a3eSMatthew Dillon exit(1);
184*2dac8a3eSMatthew Dillon }
185*2dac8a3eSMatthew Dillon
186*2dac8a3eSMatthew Dillon kkread(kd, Nl[0].n_value, &vm_page_array, sizeof(vm_page_array));
187*2dac8a3eSMatthew Dillon kkread(kd, Nl[1].n_value, &vm_page_array_size, sizeof(vm_page_array_size));
188*2dac8a3eSMatthew Dillon kernel_object_ptr = (void *)Nl[2].n_value;
189*2dac8a3eSMatthew Dillon kkread(kd, Nl[3].n_value, &nbuf, sizeof(nbuf));
190*2dac8a3eSMatthew Dillon kkread(kd, Nl[4].n_value, &nswbuf_mem, sizeof(nswbuf_mem));
191*2dac8a3eSMatthew Dillon kkread(kd, Nl[5].n_value, &nswbuf_kva, sizeof(nswbuf_kva));
192*2dac8a3eSMatthew Dillon kkread(kd, Nl[6].n_value, &nswbuf_raw, sizeof(nswbuf_raw));
193*2dac8a3eSMatthew Dillon kern_size = Nl[8].n_value - Nl[7].n_value;
194*2dac8a3eSMatthew Dillon
195*2dac8a3eSMatthew Dillon /*
196*2dac8a3eSMatthew Dillon * Scan the vm_page_array validating all pages with associated objects
197*2dac8a3eSMatthew Dillon */
198*2dac8a3eSMatthew Dillon for (i = 0; i < vm_page_array_size; ++i) {
199*2dac8a3eSMatthew Dillon if (debugopt && (i & 1023) == 0) {
200*2dac8a3eSMatthew Dillon printf("page %d/%d\r", i, vm_page_array_size);
201*2dac8a3eSMatthew Dillon fflush(stdout);
202*2dac8a3eSMatthew Dillon }
203*2dac8a3eSMatthew Dillon kkread_vmpage(kd, (u_long)&vm_page_array[i], &m);
204*2dac8a3eSMatthew Dillon if (m.object) {
205*2dac8a3eSMatthew Dillon kkread(kd, (u_long)m.object, &obj, sizeof(obj));
206*2dac8a3eSMatthew Dillon checkpage(kd, &vm_page_array[i], &m, &obj);
207*2dac8a3eSMatthew Dillon }
208*2dac8a3eSMatthew Dillon if (m.queue >= PQ_HOLD) {
209*2dac8a3eSMatthew Dillon qstr = "HOLD";
210*2dac8a3eSMatthew Dillon } else if (m.queue >= PQ_CACHE) {
211*2dac8a3eSMatthew Dillon qstr = "CACHE";
212*2dac8a3eSMatthew Dillon } else if (m.queue >= PQ_ACTIVE) {
213*2dac8a3eSMatthew Dillon qstr = "ACTIVE";
214*2dac8a3eSMatthew Dillon } else if (m.queue >= PQ_INACTIVE) {
215*2dac8a3eSMatthew Dillon qstr = "INACTIVE";
216*2dac8a3eSMatthew Dillon if (m.dirty || m.wire_count || m.busy_count || m.hold_count ||
217*2dac8a3eSMatthew Dillon (m.flags & PG_NEED_COMMIT)) {
218*2dac8a3eSMatthew Dillon if (m.flags & PG_WINATCFLS)
219*2dac8a3eSMatthew Dillon ++pqinactive_dirty2;
220*2dac8a3eSMatthew Dillon else
221*2dac8a3eSMatthew Dillon ++pqinactive_dirty1;
222*2dac8a3eSMatthew Dillon } else {
223*2dac8a3eSMatthew Dillon ++pqinactive_clean;
224*2dac8a3eSMatthew Dillon if (m.flags & PG_REFERENCED)
225*2dac8a3eSMatthew Dillon ++pqinactive_refd;
226*2dac8a3eSMatthew Dillon else
227*2dac8a3eSMatthew Dillon ++pqinactive_ready;
228*2dac8a3eSMatthew Dillon }
229*2dac8a3eSMatthew Dillon } else if (m.queue >= PQ_FREE) {
230*2dac8a3eSMatthew Dillon qstr = "FREE";
231*2dac8a3eSMatthew Dillon ++count_free;
232*2dac8a3eSMatthew Dillon } else {
233*2dac8a3eSMatthew Dillon qstr = "NONE";
234*2dac8a3eSMatthew Dillon }
235*2dac8a3eSMatthew Dillon if (m.wire_count) {
236*2dac8a3eSMatthew Dillon ++count_wired;
237*2dac8a3eSMatthew Dillon if (m.object == NULL) {
238*2dac8a3eSMatthew Dillon if ((m.flags & PG_MAPPED) &&
239*2dac8a3eSMatthew Dillon (m.flags & PG_WRITEABLE) &&
240*2dac8a3eSMatthew Dillon (m.flags & PG_UNQUEUED)) {
241*2dac8a3eSMatthew Dillon ++count_wired_pgtable;
242*2dac8a3eSMatthew Dillon } else {
243*2dac8a3eSMatthew Dillon ++count_wired_other;
244*2dac8a3eSMatthew Dillon }
245*2dac8a3eSMatthew Dillon } else if (m.object == kernel_object_ptr) {
246*2dac8a3eSMatthew Dillon ++count_wired_kernel;
247*2dac8a3eSMatthew Dillon } else {
248*2dac8a3eSMatthew Dillon switch(obj.type) {
249*2dac8a3eSMatthew Dillon case OBJT_VNODE:
250*2dac8a3eSMatthew Dillon ++count_wired_vnode;
251*2dac8a3eSMatthew Dillon break;
252*2dac8a3eSMatthew Dillon case OBJT_DEFAULT:
253*2dac8a3eSMatthew Dillon case OBJT_SWAP:
254*2dac8a3eSMatthew Dillon if (m.flags & PG_MAPPED)
255*2dac8a3eSMatthew Dillon ++count_wired_in_pmap;
256*2dac8a3eSMatthew Dillon else
257*2dac8a3eSMatthew Dillon ++count_wired_anon;
258*2dac8a3eSMatthew Dillon break;
259*2dac8a3eSMatthew Dillon default:
260*2dac8a3eSMatthew Dillon ++count_wired_obj_other;
261*2dac8a3eSMatthew Dillon break;
262*2dac8a3eSMatthew Dillon }
263*2dac8a3eSMatthew Dillon }
264*2dac8a3eSMatthew Dillon } else
265*2dac8a3eSMatthew Dillon if (m.flags & PG_MAPPED) {
266*2dac8a3eSMatthew Dillon if (m.object && m.object != kernel_object_ptr) {
267*2dac8a3eSMatthew Dillon switch(obj.type) {
268*2dac8a3eSMatthew Dillon case OBJT_DEFAULT:
269*2dac8a3eSMatthew Dillon case OBJT_SWAP:
270*2dac8a3eSMatthew Dillon ++count_anon_in_pmap;
271*2dac8a3eSMatthew Dillon break;
272*2dac8a3eSMatthew Dillon default:
273*2dac8a3eSMatthew Dillon break;
274*2dac8a3eSMatthew Dillon }
275*2dac8a3eSMatthew Dillon }
276*2dac8a3eSMatthew Dillon }
277*2dac8a3eSMatthew Dillon
278*2dac8a3eSMatthew Dillon if (verboseopt) {
279*2dac8a3eSMatthew Dillon printf("page %p obj %p/%-8ju(%016jx) val=%02x dty=%02x hold=%d "
280*2dac8a3eSMatthew Dillon "wire=%-2d act=%-3d busy=%d w/pmapcnt=%d/%d %8s",
281*2dac8a3eSMatthew Dillon &vm_page_array[i],
282*2dac8a3eSMatthew Dillon m.object,
283*2dac8a3eSMatthew Dillon (intmax_t)m.pindex,
284*2dac8a3eSMatthew Dillon (intmax_t)m.pindex * PAGE_SIZE,
285*2dac8a3eSMatthew Dillon m.valid,
286*2dac8a3eSMatthew Dillon m.dirty,
287*2dac8a3eSMatthew Dillon m.hold_count,
288*2dac8a3eSMatthew Dillon m.wire_count,
289*2dac8a3eSMatthew Dillon m.act_count,
290*2dac8a3eSMatthew Dillon m.busy_count,
291*2dac8a3eSMatthew Dillon ((m.flags & PG_WRITEABLE) != 0),
292*2dac8a3eSMatthew Dillon ((m.flags & PG_MAPPED) != 0),
293*2dac8a3eSMatthew Dillon qstr
294*2dac8a3eSMatthew Dillon );
295*2dac8a3eSMatthew Dillon }
296*2dac8a3eSMatthew Dillon
297*2dac8a3eSMatthew Dillon if (m.object == kernel_object_ptr) {
298*2dac8a3eSMatthew Dillon ostr = "kernel";
299*2dac8a3eSMatthew Dillon if (unique_object(m.object))
300*2dac8a3eSMatthew Dillon count_kernel += obj.resident_page_count;
301*2dac8a3eSMatthew Dillon } else if (m.object) {
302*2dac8a3eSMatthew Dillon switch(obj.type) {
303*2dac8a3eSMatthew Dillon case OBJT_DEFAULT:
304*2dac8a3eSMatthew Dillon ostr = "default";
305*2dac8a3eSMatthew Dillon if (unique_object(m.object))
306*2dac8a3eSMatthew Dillon count_anon += obj.resident_page_count;
307*2dac8a3eSMatthew Dillon break;
308*2dac8a3eSMatthew Dillon case OBJT_SWAP:
309*2dac8a3eSMatthew Dillon ostr = "swap";
310*2dac8a3eSMatthew Dillon if (unique_object(m.object))
311*2dac8a3eSMatthew Dillon count_anon += obj.resident_page_count;
312*2dac8a3eSMatthew Dillon break;
313*2dac8a3eSMatthew Dillon case OBJT_VNODE:
314*2dac8a3eSMatthew Dillon ostr = "vnode";
315*2dac8a3eSMatthew Dillon if (unique_object(m.object))
316*2dac8a3eSMatthew Dillon count_vnode += obj.resident_page_count;
317*2dac8a3eSMatthew Dillon break;
318*2dac8a3eSMatthew Dillon case OBJT_DEVICE:
319*2dac8a3eSMatthew Dillon ostr = "device";
320*2dac8a3eSMatthew Dillon if (unique_object(m.object))
321*2dac8a3eSMatthew Dillon count_device += obj.resident_page_count;
322*2dac8a3eSMatthew Dillon break;
323*2dac8a3eSMatthew Dillon case OBJT_PHYS:
324*2dac8a3eSMatthew Dillon ostr = "phys";
325*2dac8a3eSMatthew Dillon if (unique_object(m.object))
326*2dac8a3eSMatthew Dillon count_phys += obj.resident_page_count;
327*2dac8a3eSMatthew Dillon break;
328*2dac8a3eSMatthew Dillon case OBJT_DEAD:
329*2dac8a3eSMatthew Dillon ostr = "dead";
330*2dac8a3eSMatthew Dillon if (unique_object(m.object))
331*2dac8a3eSMatthew Dillon count_unknown += obj.resident_page_count;
332*2dac8a3eSMatthew Dillon break;
333*2dac8a3eSMatthew Dillon default:
334*2dac8a3eSMatthew Dillon if (unique_object(m.object))
335*2dac8a3eSMatthew Dillon count_unknown += obj.resident_page_count;
336*2dac8a3eSMatthew Dillon ostr = "unknown";
337*2dac8a3eSMatthew Dillon break;
338*2dac8a3eSMatthew Dillon }
339*2dac8a3eSMatthew Dillon } else {
340*2dac8a3eSMatthew Dillon ostr = "-";
341*2dac8a3eSMatthew Dillon if (m.queue == PQ_NONE)
342*2dac8a3eSMatthew Dillon ++count_noobj_offqueue;
343*2dac8a3eSMatthew Dillon else if (m.queue - m.pc != PQ_FREE)
344*2dac8a3eSMatthew Dillon ++count_noobj_onqueue;
345*2dac8a3eSMatthew Dillon }
346*2dac8a3eSMatthew Dillon
347*2dac8a3eSMatthew Dillon if (verboseopt) {
348*2dac8a3eSMatthew Dillon printf(" %-7s", ostr);
349*2dac8a3eSMatthew Dillon if (m.busy_count & PBUSY_LOCKED)
350*2dac8a3eSMatthew Dillon printf(" BUSY");
351*2dac8a3eSMatthew Dillon if (m.busy_count & PBUSY_WANTED)
352*2dac8a3eSMatthew Dillon printf(" WANTED");
353*2dac8a3eSMatthew Dillon if (m.flags & PG_WINATCFLS)
354*2dac8a3eSMatthew Dillon printf(" WINATCFLS");
355*2dac8a3eSMatthew Dillon if (m.flags & PG_FICTITIOUS)
356*2dac8a3eSMatthew Dillon printf(" FICTITIOUS");
357*2dac8a3eSMatthew Dillon if (m.flags & PG_WRITEABLE)
358*2dac8a3eSMatthew Dillon printf(" WRITEABLE");
359*2dac8a3eSMatthew Dillon if (m.flags & PG_MAPPED)
360*2dac8a3eSMatthew Dillon printf(" MAPPED");
361*2dac8a3eSMatthew Dillon if (m.flags & PG_NEED_COMMIT)
362*2dac8a3eSMatthew Dillon printf(" NEED_COMMIT");
363*2dac8a3eSMatthew Dillon if (m.flags & PG_REFERENCED)
364*2dac8a3eSMatthew Dillon printf(" REFERENCED");
365*2dac8a3eSMatthew Dillon if (m.flags & PG_CLEANCHK)
366*2dac8a3eSMatthew Dillon printf(" CLEANCHK");
367*2dac8a3eSMatthew Dillon if (m.busy_count & PBUSY_SWAPINPROG)
368*2dac8a3eSMatthew Dillon printf(" SWAPINPROG");
369*2dac8a3eSMatthew Dillon if (m.flags & PG_NOSYNC)
370*2dac8a3eSMatthew Dillon printf(" NOSYNC");
371*2dac8a3eSMatthew Dillon if (m.flags & PG_UNQUEUED)
372*2dac8a3eSMatthew Dillon printf(" UNQUEUED");
373*2dac8a3eSMatthew Dillon if (m.flags & PG_MARKER)
374*2dac8a3eSMatthew Dillon printf(" MARKER");
375*2dac8a3eSMatthew Dillon if (m.flags & PG_RAM)
376*2dac8a3eSMatthew Dillon printf(" RAM");
377*2dac8a3eSMatthew Dillon if (m.flags & PG_SWAPPED)
378*2dac8a3eSMatthew Dillon printf(" SWAPPED");
379*2dac8a3eSMatthew Dillon #if 0
380*2dac8a3eSMatthew Dillon if (m.flags & PG_SLAB)
381*2dac8a3eSMatthew Dillon printf(" SLAB");
382*2dac8a3eSMatthew Dillon #endif
383*2dac8a3eSMatthew Dillon printf("\n");
384*2dac8a3eSMatthew Dillon #if 0
385*2dac8a3eSMatthew Dillon if (m.flags & PG_SLAB)
386*2dac8a3eSMatthew Dillon addsltrack(&m);
387*2dac8a3eSMatthew Dillon #endif
388*2dac8a3eSMatthew Dillon }
389*2dac8a3eSMatthew Dillon }
390*2dac8a3eSMatthew Dillon if (debugopt || verboseopt)
391*2dac8a3eSMatthew Dillon printf("\n");
392*2dac8a3eSMatthew Dillon printf("%8.2fM free\n",
393*2dac8a3eSMatthew Dillon count_free * 4096.0 / 1048576.0);
394*2dac8a3eSMatthew Dillon printf("%8.2fM inactive-clean\n",
395*2dac8a3eSMatthew Dillon pqinactive_clean * 4096.0 / 1048576.0);
396*2dac8a3eSMatthew Dillon printf("%8.2fM inactive-clean-and-referenced\n",
397*2dac8a3eSMatthew Dillon pqinactive_refd * 4096.0 / 1048576.0);
398*2dac8a3eSMatthew Dillon printf("%8.2fM inactive-clean-and-ready\n",
399*2dac8a3eSMatthew Dillon pqinactive_ready * 4096.0 / 1048576.0);
400*2dac8a3eSMatthew Dillon printf("%8.2fM inactive-dirty/first-LRU\n",
401*2dac8a3eSMatthew Dillon pqinactive_dirty1 * 4096.0 / 1048576.0);
402*2dac8a3eSMatthew Dillon printf("%8.2fM inactive-dirty/second-LRU\n",
403*2dac8a3eSMatthew Dillon pqinactive_dirty2 * 4096.0 / 1048576.0);
404*2dac8a3eSMatthew Dillon
405*2dac8a3eSMatthew Dillon printf("%8.2fM wired vnode (in buffer cache)\n",
406*2dac8a3eSMatthew Dillon count_wired_vnode * 4096.0 / 1048576.0);
407*2dac8a3eSMatthew Dillon printf("%8.2fM wired in-pmap (probably vnode pages also in buffer cache)\n",
408*2dac8a3eSMatthew Dillon count_wired_in_pmap * 4096.0 / 1048576.0);
409*2dac8a3eSMatthew Dillon printf("%8.2fM wired pgtable\n",
410*2dac8a3eSMatthew Dillon count_wired_pgtable * 4096.0 / 1048576.0);
411*2dac8a3eSMatthew Dillon printf("%8.2fM wired anon\n",
412*2dac8a3eSMatthew Dillon count_wired_anon * 4096.0 / 1048576.0);
413*2dac8a3eSMatthew Dillon printf("%8.2fM wired kernel_object\n",
414*2dac8a3eSMatthew Dillon count_wired_kernel * 4096.0 / 1048576.0);
415*2dac8a3eSMatthew Dillon
416*2dac8a3eSMatthew Dillon printf("\t%8.2fM vm_page_array\n",
417*2dac8a3eSMatthew Dillon vm_page_array_size * sizeof(struct vm_page) / 1048576.0);
418*2dac8a3eSMatthew Dillon printf("\t%8.2fM buf, swbuf_mem, swbuf_kva, swbuf_raw\n",
419*2dac8a3eSMatthew Dillon (nbuf + nswbuf_mem + nswbuf_kva + nswbuf_raw) *
420*2dac8a3eSMatthew Dillon sizeof(struct buf) / 1048576.0);
421*2dac8a3eSMatthew Dillon printf("\t%8.2fM kernel binary\n", kern_size / 1048576.0);
422*2dac8a3eSMatthew Dillon printf("\t(also add in KMALLOC id kmapinfo, or loosely, vmstat -m)\n");
423*2dac8a3eSMatthew Dillon
424*2dac8a3eSMatthew Dillon printf("%8.2fM wired other (unknown object)\n",
425*2dac8a3eSMatthew Dillon count_wired_obj_other * 4096.0 / 1048576.0);
426*2dac8a3eSMatthew Dillon printf("%8.2fM wired other (no object, probably kernel)\n",
427*2dac8a3eSMatthew Dillon count_wired_other * 4096.0 / 1048576.0);
428*2dac8a3eSMatthew Dillon
429*2dac8a3eSMatthew Dillon printf("%8.2fM WIRED TOTAL\n",
430*2dac8a3eSMatthew Dillon count_wired * 4096.0 / 1048576.0);
431*2dac8a3eSMatthew Dillon
432*2dac8a3eSMatthew Dillon printf("\n");
433*2dac8a3eSMatthew Dillon printf("%8.2fM anonymous (total, includes in-pmap)\n",
434*2dac8a3eSMatthew Dillon count_anon * 4096.0 / 1048576.0);
435*2dac8a3eSMatthew Dillon printf("%8.2fM anonymous memory in-pmap\n",
436*2dac8a3eSMatthew Dillon count_anon_in_pmap * 4096.0 / 1048576.0);
437*2dac8a3eSMatthew Dillon printf("%8.2fM vnode (includes wired)\n",
438*2dac8a3eSMatthew Dillon count_vnode * 4096.0 / 1048576.0);
439*2dac8a3eSMatthew Dillon printf("%8.2fM device\n", count_device * 4096.0 / 1048576.0);
440*2dac8a3eSMatthew Dillon printf("%8.2fM phys\n", count_phys * 4096.0 / 1048576.0);
441*2dac8a3eSMatthew Dillon printf("%8.2fM kernel (includes wired)\n",
442*2dac8a3eSMatthew Dillon count_kernel * 4096.0 / 1048576.0);
443*2dac8a3eSMatthew Dillon printf("%8.2fM unknown\n", count_unknown * 4096.0 / 1048576.0);
444*2dac8a3eSMatthew Dillon printf("%8.2fM no_object, off queue (includes wired w/o object)\n",
445*2dac8a3eSMatthew Dillon count_noobj_offqueue * 4096.0 / 1048576.0);
446*2dac8a3eSMatthew Dillon printf("%8.2fM no_object, on non-free queue (includes wired w/o object)\n",
447*2dac8a3eSMatthew Dillon count_noobj_onqueue * 4096.0 / 1048576.0);
448*2dac8a3eSMatthew Dillon
449*2dac8a3eSMatthew Dillon #if 0
450*2dac8a3eSMatthew Dillon /*
451*2dac8a3eSMatthew Dillon * Scan the vm_page_buckets array validating all pages found
452*2dac8a3eSMatthew Dillon */
453*2dac8a3eSMatthew Dillon for (i = 0; i <= vm_page_hash_mask; ++i) {
454*2dac8a3eSMatthew Dillon if (debugopt) {
455*2dac8a3eSMatthew Dillon printf("index %d\r", i);
456*2dac8a3eSMatthew Dillon fflush(stdout);
457*2dac8a3eSMatthew Dillon }
458*2dac8a3eSMatthew Dillon kkread(kd, (u_long)&vm_page_buckets[i], &mptr, sizeof(mptr));
459*2dac8a3eSMatthew Dillon while (mptr) {
460*2dac8a3eSMatthew Dillon kkread(kd, (u_long)mptr, &m, sizeof(m));
461*2dac8a3eSMatthew Dillon if (m.object) {
462*2dac8a3eSMatthew Dillon kkread(kd, (u_long)m.object, &obj, sizeof(obj));
463*2dac8a3eSMatthew Dillon hv = ((uintptr_t)m.object + m.pindex) ^ obj.hash_rand;
464*2dac8a3eSMatthew Dillon hv &= vm_page_hash_mask;
465*2dac8a3eSMatthew Dillon if (i != hv)
466*2dac8a3eSMatthew Dillon printf("vm_page_buckets[%d] ((struct vm_page *)%p)"
467*2dac8a3eSMatthew Dillon " should be in bucket %d\n", i, mptr, hv);
468*2dac8a3eSMatthew Dillon checkpage(kd, mptr, &m, &obj);
469*2dac8a3eSMatthew Dillon } else {
470*2dac8a3eSMatthew Dillon printf("vm_page_buckets[%d] ((struct vm_page *)%p)"
471*2dac8a3eSMatthew Dillon " has no object\n", i, mptr);
472*2dac8a3eSMatthew Dillon }
473*2dac8a3eSMatthew Dillon mptr = m.hnext;
474*2dac8a3eSMatthew Dillon }
475*2dac8a3eSMatthew Dillon }
476*2dac8a3eSMatthew Dillon #endif
477*2dac8a3eSMatthew Dillon if (debugopt)
478*2dac8a3eSMatthew Dillon printf("\n");
479*2dac8a3eSMatthew Dillon #if 0
480*2dac8a3eSMatthew Dillon dumpsltrack(kd);
481*2dac8a3eSMatthew Dillon #endif
482*2dac8a3eSMatthew Dillon return(0);
483*2dac8a3eSMatthew Dillon }
484*2dac8a3eSMatthew Dillon
485*2dac8a3eSMatthew Dillon /*
486*2dac8a3eSMatthew Dillon * A page with an object.
487*2dac8a3eSMatthew Dillon */
488*2dac8a3eSMatthew Dillon void
checkpage(kvm_t * kd,vm_page_t mptr,vm_page_t m,struct vm_object * obj)489*2dac8a3eSMatthew Dillon checkpage(kvm_t *kd, vm_page_t mptr, vm_page_t m, struct vm_object *obj)
490*2dac8a3eSMatthew Dillon {
491*2dac8a3eSMatthew Dillon #if 0
492*2dac8a3eSMatthew Dillon struct vm_page scan;
493*2dac8a3eSMatthew Dillon vm_page_t scanptr;
494*2dac8a3eSMatthew Dillon int hv;
495*2dac8a3eSMatthew Dillon
496*2dac8a3eSMatthew Dillon hv = ((uintptr_t)m->object + m->pindex) ^ obj->hash_rand;
497*2dac8a3eSMatthew Dillon hv &= vm_page_hash_mask;
498*2dac8a3eSMatthew Dillon kkread(kd, (u_long)&vm_page_buckets[hv], &scanptr, sizeof(scanptr));
499*2dac8a3eSMatthew Dillon while (scanptr) {
500*2dac8a3eSMatthew Dillon if (scanptr == mptr)
501*2dac8a3eSMatthew Dillon break;
502*2dac8a3eSMatthew Dillon kkread(kd, (u_long)scanptr, &scan, sizeof(scan));
503*2dac8a3eSMatthew Dillon scanptr = scan.hnext;
504*2dac8a3eSMatthew Dillon }
505*2dac8a3eSMatthew Dillon if (scanptr) {
506*2dac8a3eSMatthew Dillon if (debugopt > 1)
507*2dac8a3eSMatthew Dillon printf("good checkpage %p bucket %d\n", mptr, hv);
508*2dac8a3eSMatthew Dillon } else {
509*2dac8a3eSMatthew Dillon printf("vm_page_buckets[%d] ((struct vm_page *)%p)"
510*2dac8a3eSMatthew Dillon " page not found in bucket list\n", hv, mptr);
511*2dac8a3eSMatthew Dillon }
512*2dac8a3eSMatthew Dillon #endif
513*2dac8a3eSMatthew Dillon }
514*2dac8a3eSMatthew Dillon
515*2dac8a3eSMatthew Dillon /*
516*2dac8a3eSMatthew Dillon * Acclerate the reading of VM pages
517*2dac8a3eSMatthew Dillon */
518*2dac8a3eSMatthew Dillon #define VPCACHE_SIZE 65536
519*2dac8a3eSMatthew Dillon
520*2dac8a3eSMatthew Dillon static void
kkread_vmpage(kvm_t * kd,u_long addr,vm_page_t m)521*2dac8a3eSMatthew Dillon kkread_vmpage(kvm_t *kd, u_long addr, vm_page_t m)
522*2dac8a3eSMatthew Dillon {
523*2dac8a3eSMatthew Dillon static struct vm_page vpcache[VPCACHE_SIZE];
524*2dac8a3eSMatthew Dillon static u_long vpbeg;
525*2dac8a3eSMatthew Dillon static u_long vpend;
526*2dac8a3eSMatthew Dillon
527*2dac8a3eSMatthew Dillon if (addr < vpbeg || addr >= vpend) {
528*2dac8a3eSMatthew Dillon vpbeg = addr;
529*2dac8a3eSMatthew Dillon vpend = addr + VPCACHE_SIZE * sizeof(*m);
530*2dac8a3eSMatthew Dillon if (vpend > (u_long)(uintptr_t)vm_page_array +
531*2dac8a3eSMatthew Dillon vm_page_array_size * sizeof(*m)) {
532*2dac8a3eSMatthew Dillon vpend = (u_long)(uintptr_t)vm_page_array +
533*2dac8a3eSMatthew Dillon vm_page_array_size * sizeof(*m);
534*2dac8a3eSMatthew Dillon }
535*2dac8a3eSMatthew Dillon kkread(kd, vpbeg, vpcache, vpend - vpbeg);
536*2dac8a3eSMatthew Dillon }
537*2dac8a3eSMatthew Dillon *m = vpcache[(addr - vpbeg) / sizeof(*m)];
538*2dac8a3eSMatthew Dillon }
539*2dac8a3eSMatthew Dillon
540*2dac8a3eSMatthew Dillon static void
kkread(kvm_t * kd,u_long addr,void * buf,size_t nbytes)541*2dac8a3eSMatthew Dillon kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
542*2dac8a3eSMatthew Dillon {
543*2dac8a3eSMatthew Dillon if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
544*2dac8a3eSMatthew Dillon perror("kvm_read");
545*2dac8a3eSMatthew Dillon exit(1);
546*2dac8a3eSMatthew Dillon }
547*2dac8a3eSMatthew Dillon }
548*2dac8a3eSMatthew Dillon
549*2dac8a3eSMatthew Dillon static int
kkread_err(kvm_t * kd,u_long addr,void * buf,size_t nbytes)550*2dac8a3eSMatthew Dillon kkread_err(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
551*2dac8a3eSMatthew Dillon {
552*2dac8a3eSMatthew Dillon if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
553*2dac8a3eSMatthew Dillon return 1;
554*2dac8a3eSMatthew Dillon }
555*2dac8a3eSMatthew Dillon return 0;
556*2dac8a3eSMatthew Dillon }
557*2dac8a3eSMatthew Dillon
558*2dac8a3eSMatthew Dillon struct SLTrack {
559*2dac8a3eSMatthew Dillon struct SLTrack *next;
560*2dac8a3eSMatthew Dillon u_long addr;
561*2dac8a3eSMatthew Dillon };
562*2dac8a3eSMatthew Dillon
563*2dac8a3eSMatthew Dillon #define SLHSIZE 1024
564*2dac8a3eSMatthew Dillon #define SLHMASK (SLHSIZE - 1)
565*2dac8a3eSMatthew Dillon
566*2dac8a3eSMatthew Dillon struct SLTrack *SLHash[SLHSIZE];
567*2dac8a3eSMatthew Dillon
568*2dac8a3eSMatthew Dillon #if 0
569*2dac8a3eSMatthew Dillon static
570*2dac8a3eSMatthew Dillon void
571*2dac8a3eSMatthew Dillon addsltrack(vm_page_t m)
572*2dac8a3eSMatthew Dillon {
573*2dac8a3eSMatthew Dillon struct SLTrack *slt;
574*2dac8a3eSMatthew Dillon u_long addr = (m->pindex * PAGE_SIZE) & ~131071L;
575*2dac8a3eSMatthew Dillon int i;
576*2dac8a3eSMatthew Dillon
577*2dac8a3eSMatthew Dillon if (m->wire_count == 0 || (m->flags & PG_MAPPED) == 0 ||
578*2dac8a3eSMatthew Dillon m->object == NULL)
579*2dac8a3eSMatthew Dillon return;
580*2dac8a3eSMatthew Dillon
581*2dac8a3eSMatthew Dillon i = (addr / 131072) & SLHMASK;
582*2dac8a3eSMatthew Dillon for (slt = SLHash[i]; slt; slt = slt->next) {
583*2dac8a3eSMatthew Dillon if (slt->addr == addr)
584*2dac8a3eSMatthew Dillon break;
585*2dac8a3eSMatthew Dillon }
586*2dac8a3eSMatthew Dillon if (slt == NULL) {
587*2dac8a3eSMatthew Dillon slt = malloc(sizeof(*slt));
588*2dac8a3eSMatthew Dillon slt->addr = addr;
589*2dac8a3eSMatthew Dillon slt->next = SLHash[i];
590*2dac8a3eSMatthew Dillon SLHash[i] = slt;
591*2dac8a3eSMatthew Dillon }
592*2dac8a3eSMatthew Dillon }
593*2dac8a3eSMatthew Dillon #endif
594*2dac8a3eSMatthew Dillon
595*2dac8a3eSMatthew Dillon static
596*2dac8a3eSMatthew Dillon void
dumpsltrack(kvm_t * kd)597*2dac8a3eSMatthew Dillon dumpsltrack(kvm_t *kd)
598*2dac8a3eSMatthew Dillon {
599*2dac8a3eSMatthew Dillon struct SLTrack *slt;
600*2dac8a3eSMatthew Dillon int i;
601*2dac8a3eSMatthew Dillon long total_zones = 0;
602*2dac8a3eSMatthew Dillon long full_zones = 0;
603*2dac8a3eSMatthew Dillon
604*2dac8a3eSMatthew Dillon for (i = 0; i < SLHSIZE; ++i) {
605*2dac8a3eSMatthew Dillon for (slt = SLHash[i]; slt; slt = slt->next) {
606*2dac8a3eSMatthew Dillon SLZone z;
607*2dac8a3eSMatthew Dillon
608*2dac8a3eSMatthew Dillon if (kkread_err(kd, slt->addr, &z, sizeof(z))) {
609*2dac8a3eSMatthew Dillon printf("SLZone 0x%016lx not mapped\n",
610*2dac8a3eSMatthew Dillon slt->addr);
611*2dac8a3eSMatthew Dillon continue;
612*2dac8a3eSMatthew Dillon }
613*2dac8a3eSMatthew Dillon printf("SLZone 0x%016lx { mag=%08x cpu=%-2d NFree=%-3d "
614*2dac8a3eSMatthew Dillon "chunksz=%-5d }\n",
615*2dac8a3eSMatthew Dillon slt->addr,
616*2dac8a3eSMatthew Dillon z.z_Magic,
617*2dac8a3eSMatthew Dillon z.z_Cpu,
618*2dac8a3eSMatthew Dillon z.z_NFree,
619*2dac8a3eSMatthew Dillon z.z_ChunkSize
620*2dac8a3eSMatthew Dillon );
621*2dac8a3eSMatthew Dillon ++total_zones;
622*2dac8a3eSMatthew Dillon if (z.z_NFree == 0)
623*2dac8a3eSMatthew Dillon ++full_zones;
624*2dac8a3eSMatthew Dillon }
625*2dac8a3eSMatthew Dillon }
626*2dac8a3eSMatthew Dillon printf("FullZones/TotalZones: %ld/%ld\n", full_zones, total_zones);
627*2dac8a3eSMatthew Dillon }
628*2dac8a3eSMatthew Dillon
629*2dac8a3eSMatthew Dillon #define HASH_SIZE (1024*1024)
630*2dac8a3eSMatthew Dillon #define HASH_MASK (HASH_SIZE - 1)
631*2dac8a3eSMatthew Dillon
632*2dac8a3eSMatthew Dillon struct dup_entry {
633*2dac8a3eSMatthew Dillon struct dup_entry *next;
634*2dac8a3eSMatthew Dillon void *ptr;
635*2dac8a3eSMatthew Dillon };
636*2dac8a3eSMatthew Dillon
637*2dac8a3eSMatthew Dillon struct dup_entry *dup_hash[HASH_SIZE];
638*2dac8a3eSMatthew Dillon
639*2dac8a3eSMatthew Dillon static int
unique_object(void * ptr)640*2dac8a3eSMatthew Dillon unique_object(void *ptr)
641*2dac8a3eSMatthew Dillon {
642*2dac8a3eSMatthew Dillon struct dup_entry *hen;
643*2dac8a3eSMatthew Dillon int hv;
644*2dac8a3eSMatthew Dillon
645*2dac8a3eSMatthew Dillon hv = (intptr_t)ptr ^ ((intptr_t)ptr >> 20);
646*2dac8a3eSMatthew Dillon hv &= HASH_MASK;
647*2dac8a3eSMatthew Dillon for (hen = dup_hash[hv]; hen; hen = hen->next) {
648*2dac8a3eSMatthew Dillon if (hen->ptr == ptr)
649*2dac8a3eSMatthew Dillon return 0;
650*2dac8a3eSMatthew Dillon }
651*2dac8a3eSMatthew Dillon hen = malloc(sizeof(*hen));
652*2dac8a3eSMatthew Dillon hen->next = dup_hash[hv];
653*2dac8a3eSMatthew Dillon hen->ptr = ptr;
654*2dac8a3eSMatthew Dillon dup_hash[hv] = hen;
655*2dac8a3eSMatthew Dillon
656*2dac8a3eSMatthew Dillon return 1;
657*2dac8a3eSMatthew Dillon }
658