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 /*----------------------------------*/ 16 static 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 */ 24 struct 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 35 static u_short 36 wlpsacrc(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 /*----------------------------------*/ 56 struct nlist nl[] = { 57 { "_nchash", 0}, 58 { "_nchashtbl", 0}, 59 { 0, 0 }, 60 }; 61 62 int histo[2047]; 63 int histn[2047]; 64 int *newbucket; 65 66 int 67 main(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