1 /* 2 * SLABINFO.C 3 * 4 * cc -I/usr/src/sys slabinfo.c -o ~/bin/slabinfo -lkvm 5 * 6 * slabinfo 7 * 8 * dump kernel slab allocator pcpu data and chains 9 * 10 * Copyright (c) 2012 The DragonFly Project. All rights reserved. 11 * 12 * This code is derived from software contributed to The DragonFly Project 13 * by Matthew Dillon <dillon@backplane.com> 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in 23 * the documentation and/or other materials provided with the 24 * distribution. 25 * 3. Neither the name of The DragonFly Project nor the names of its 26 * contributors may be used to endorse or promote products derived 27 * from this software without specific, prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 32 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 33 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 34 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 35 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 36 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 37 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 38 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 39 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 * SUCH DAMAGE. 41 */ 42 43 #define _KERNEL_STRUCTURES 44 #include <sys/param.h> 45 #include <sys/user.h> 46 #include <sys/malloc.h> 47 #include <sys/signalvar.h> 48 #include <sys/vnode.h> 49 #include <sys/namecache.h> 50 #include <sys/globaldata.h> 51 #include <machine/globaldata.h> 52 #include <sys/slaballoc.h> 53 54 #include <vm/vm.h> 55 #include <vm/vm_page.h> 56 #include <vm/vm_kern.h> 57 #include <vm/vm_page.h> 58 #include <vm/vm_object.h> 59 #include <vm/swap_pager.h> 60 #include <vm/vnode_pager.h> 61 62 #include <stdio.h> 63 #include <stdlib.h> 64 #include <string.h> 65 #include <fcntl.h> 66 #include <kvm.h> 67 #include <nlist.h> 68 #include <getopt.h> 69 70 struct nlist Nl[] = { 71 { "_CPU_prvspace" }, 72 { "_ncpus" }, 73 { NULL } 74 }; 75 76 int debugopt; 77 int verboseopt; 78 79 int slzonedump(kvm_t *kd, SLZoneList *list); 80 void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes); 81 82 int 83 main(int ac, char **av) 84 { 85 const char *corefile = NULL; 86 const char *sysfile = NULL; 87 kvm_t *kd; 88 int ch; 89 int i; 90 int j; 91 int ncpus; 92 int totalzones; 93 int totalfree; 94 struct globaldata gd; 95 struct privatespace **psary; 96 97 while ((ch = getopt(ac, av, "M:N:dv")) != -1) { 98 switch(ch) { 99 case 'd': 100 ++debugopt; 101 break; 102 case 'v': 103 ++verboseopt; 104 break; 105 case 'M': 106 corefile = optarg; 107 break; 108 case 'N': 109 sysfile = optarg; 110 break; 111 default: 112 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); 113 exit(1); 114 } 115 } 116 ac -= optind; 117 av += optind; 118 119 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { 120 perror("kvm_open"); 121 exit(1); 122 } 123 if (kvm_nlist(kd, Nl) != 0) { 124 perror("kvm_nlist"); 125 exit(1); 126 } 127 128 kkread(kd, Nl[1].n_value, &ncpus, sizeof(int)); 129 totalzones = 0; 130 totalfree = 0; 131 132 psary = malloc(sizeof(void *) * ncpus); 133 kkread(kd, Nl[0].n_value, psary, sizeof(void *) * ncpus); 134 135 for (i = 0; i < ncpus; ++i) { 136 kkread(kd, (long)psary[i], &gd, sizeof(gd)); 137 printf("CPU %02d (NFreeZones=%d) {\n", 138 i, gd.gd_slab.NFreeZones); 139 totalfree += gd.gd_slab.NFreeZones; 140 141 for (j = 0; j < NZONES; ++j) { 142 printf(" Zone %02d {\n", j); 143 totalzones += slzonedump(kd, &gd.gd_slab.ZoneAry[j]); 144 printf(" }\n"); 145 } 146 147 printf(" FreeZone {\n"); 148 totalzones += slzonedump(kd, &gd.gd_slab.FreeZones); 149 printf(" }\n"); 150 151 printf(" FreeOVZon {\n"); 152 totalzones += slzonedump(kd, &gd.gd_slab.FreeOvZones); 153 printf(" }\n"); 154 155 printf("}\n"); 156 } 157 printf("TotalZones %d x 131072 = %jd\n", 158 totalzones, (intmax_t)totalzones * 131072LL); 159 printf("TotalFree %d x 131072 = %jd\n", 160 totalfree, (intmax_t)totalfree * 131072LL); 161 return(0); 162 } 163 164 int 165 slzonedump(kvm_t *kd, SLZoneList *list) 166 { 167 SLZone slz; 168 SLZone *kslz; 169 int count = 0; 170 171 kslz = TAILQ_FIRST(list); 172 173 while (kslz) { 174 kkread(kd, (u_long)kslz, &slz, sizeof(slz)); 175 printf("\t{ magic=%08x cpu=%d chunking=%d NFree=%d/%d RCnt=%d}\n", 176 slz.z_Magic, slz.z_Cpu, slz.z_ChunkSize, 177 slz.z_NFree, slz.z_NMax, slz.z_RCount); 178 kslz = TAILQ_NEXT(&slz, z_Entry); 179 ++count; 180 } 181 return(count); 182 } 183 184 void 185 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) 186 { 187 if (kvm_read(kd, addr, buf, nbytes) != nbytes) { 188 perror("kvm_read"); 189 exit(1); 190 } 191 } 192