1/* $FreeBSD$ */
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <fcntl.h>
6#include <kvm.h>
7#include <nlist.h>
8#include <sysexits.h>
9#include <sys/uio.h>
10#include <sys/namei.h>
11#include <sys/param.h>
12#include <sys/queue.h>
13#include <sys/time.h>
14#include <sys/vnode.h>
15/*----------------------------------*/
16static u_int crc16_table[16] = {
17    0x0000, 0xCC01, 0xD801, 0x1400,
18    0xF001, 0x3C00, 0x2800, 0xE401,
19    0xA001, 0x6C00, 0x7800, 0xB401,
20    0x5000, 0x9C01, 0x8801, 0x4400
21};
22
23/* XXX Taken from sys/kern/vfs_cache.c */
24struct	namecache {
25	LIST_ENTRY(namecache) nc_hash;
26	LIST_ENTRY(namecache) nc_src;
27	TAILQ_ENTRY(namecache) nc_dst;
28	struct	vnode *nc_dvp;
29	struct	vnode *nc_vp;
30	u_char	nc_flag;
31	u_char	nc_nlen;
32	char	nc_name[0];
33};
34
35static u_short
36wlpsacrc(u_char *buf, u_int len)
37{
38    u_short     crc = 0;
39    int         i, r1;
40
41    for (i = 0; i < len; i++, buf++) {
42        /* lower 4 bits */
43        r1 = crc16_table[crc & 0xF];
44        crc = (crc >> 4) & 0x0FFF;
45        crc = crc ^ r1 ^ crc16_table[*buf & 0xF];
46
47        /* upper 4 bits */
48        r1 = crc16_table[crc & 0xF];
49        crc = (crc >> 4) & 0x0FFF;
50        crc = crc ^ r1 ^ crc16_table[(*buf >> 4) & 0xF];
51    }
52    return(crc);
53}
54
55/*----------------------------------*/
56struct nlist nl[] = {
57	{ "_nchash", 0},
58	{ "_nchashtbl", 0},
59	{ 0, 0 },
60};
61
62int histo[2047];
63int histn[2047];
64int *newbucket;
65
66int
67main(int argc, char **argv)
68{
69	int nchash, i, j, k, kn;
70	int nb, p1, p2;
71	u_long p;
72	LIST_HEAD(nchashhead, namecache) *nchashtbl;
73	struct namecache *nc;
74	struct vnode vn;
75
76	kvm_t *kvm = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0]);
77	if (kvm == NULL)
78		return(EX_OSERR);
79
80	printf("kvm: %p\n", kvm);
81	printf("kvm_nlist: %d\n", kvm_nlist(kvm, nl));
82	kvm_read(kvm, nl[0].n_value, &nchash, sizeof nchash);
83	nchash++;
84	nchashtbl = malloc(nchash * sizeof *nchashtbl);
85	nc = malloc(sizeof *nc + NAME_MAX);
86	newbucket = malloc(nchash * sizeof (int));
87	memset(newbucket, 0, nchash * sizeof (int));
88	kvm_read(kvm, nl[1].n_value, &p, sizeof p);
89	kvm_read(kvm, p, nchashtbl, nchash * sizeof *nchashtbl);
90	for (i=0; i < nchash; i++) {
91#if 0
92		printf("%d\n", i);
93#endif
94		nb=0;
95		p = (u_long)LIST_FIRST(nchashtbl+i);
96		while (p) {
97			nb++;
98			kvm_read(kvm, p, nc, sizeof *nc + NAME_MAX);
99			kvm_read(kvm, (u_long)nc->nc_dvp, &vn, sizeof vn);
100			nc->nc_name[nc->nc_nlen] = '\0';
101			for (j=k=kn=0;nc->nc_name[j];j++) {
102				k+= nc->nc_name[j];
103				kn <<= 1;
104				kn+= nc->nc_name[j];
105			}
106			/*
107			kn = k;
108			*/
109			kn = wlpsacrc(nc->nc_name,nc->nc_nlen);
110
111			/* kn += (u_long)vn.v_data >> 8;  */
112			/* kn += (u_long)nc->nc_dvp >> 7;    */
113			kn += vn.v_id;
114			kn &= (nchash - 1);
115			newbucket[kn]++;
116#if 1
117			printf("%4d  dvp %08x  hash %08x  vp %08x  id %08x  name <%s>\n",
118				i,nc->nc_dvp, k, nc->nc_vp, vn.v_id, nc->nc_name);
119#endif
120			p = (u_long)LIST_NEXT(nc, nc_hash);
121		}
122		histo[nb]++;
123	}
124	for (i=0; i < nchash; i++) {
125		histn[newbucket[i]]++;
126	}
127	p1=p2 = 0;
128	for (i=0;i<30;i++) {
129		p1 += histo[i] * i;
130		p2 += histn[i] * i;
131		if (histo[i] || histn[i])
132			printf("H%02d %4d %4d / %4d %4d\n",i,histo[i], p1 , histn[i], p2);
133	}
134
135	return (0);
136}
137
138