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_object.h> 58 #include <vm/swap_pager.h> 59 #include <vm/vnode_pager.h> 60 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 #include <fcntl.h> 65 #include <kvm.h> 66 #include <nlist.h> 67 #include <getopt.h> 68 69 struct nlist Nl[] = { 70 { "_CPU_prvspace" }, 71 { "_ncpus" }, 72 { NULL } 73 }; 74 75 int debugopt; 76 int verboseopt; 77 78 int slzonedump(kvm_t *kd, SLZoneList *list); 79 void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes); 80 81 int 82 main(int ac, char **av) 83 { 84 const char *corefile = NULL; 85 const char *sysfile = NULL; 86 kvm_t *kd; 87 int ch; 88 int i; 89 int j; 90 int ncpus; 91 int totalzones; 92 int totalfree; 93 struct globaldata gd; 94 struct privatespace **psary; 95 96 while ((ch = getopt(ac, av, "M:N:dv")) != -1) { 97 switch(ch) { 98 case 'd': 99 ++debugopt; 100 break; 101 case 'v': 102 ++verboseopt; 103 break; 104 case 'M': 105 corefile = optarg; 106 break; 107 case 'N': 108 sysfile = optarg; 109 break; 110 default: 111 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); 112 exit(1); 113 } 114 } 115 ac -= optind; 116 av += optind; 117 118 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { 119 perror("kvm_open"); 120 exit(1); 121 } 122 if (kvm_nlist(kd, Nl) != 0) { 123 perror("kvm_nlist"); 124 exit(1); 125 } 126 127 kkread(kd, Nl[1].n_value, &ncpus, sizeof(int)); 128 totalzones = 0; 129 totalfree = 0; 130 131 psary = malloc(sizeof(void *) * ncpus); 132 kkread(kd, Nl[0].n_value, psary, sizeof(void *) * ncpus); 133 134 for (i = 0; i < ncpus; ++i) { 135 kkread(kd, (long)psary[i], &gd, sizeof(gd)); 136 printf("CPU %02d (NFreeZones=%d) {\n", 137 i, gd.gd_slab.NFreeZones); 138 totalfree += gd.gd_slab.NFreeZones; 139 140 for (j = 0; j < NZONES; ++j) { 141 printf(" Zone %02d {\n", j); 142 totalzones += slzonedump(kd, &gd.gd_slab.ZoneAry[j]); 143 printf(" }\n"); 144 } 145 146 printf(" FreeZone {\n"); 147 totalzones += slzonedump(kd, &gd.gd_slab.FreeZones); 148 printf(" }\n"); 149 150 printf(" FreeOVZon {\n"); 151 totalzones += slzonedump(kd, &gd.gd_slab.FreeOvZones); 152 printf(" }\n"); 153 154 printf("}\n"); 155 } 156 printf("TotalZones %d x 131072 = %jd\n", 157 totalzones, (intmax_t)totalzones * 131072LL); 158 printf("TotalFree %d x 131072 = %jd\n", 159 totalfree, (intmax_t)totalfree * 131072LL); 160 return(0); 161 } 162 163 int 164 slzonedump(kvm_t *kd, SLZoneList *list) 165 { 166 SLZone slz; 167 SLZone *kslz; 168 int count = 0; 169 170 kslz = TAILQ_FIRST(list); 171 172 while (kslz) { 173 kkread(kd, (u_long)kslz, &slz, sizeof(slz)); 174 printf("\t{ magic=%08x cpu=%d chunking=%d NFree=%d/%d RCnt=%d}\n", 175 slz.z_Magic, slz.z_Cpu, slz.z_ChunkSize, 176 slz.z_NFree, slz.z_NMax, slz.z_RCount); 177 kslz = TAILQ_NEXT(&slz, z_Entry); 178 ++count; 179 } 180 return(count); 181 } 182 183 void 184 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) 185 { 186 if (kvm_read(kd, addr, buf, nbytes) != nbytes) { 187 perror("kvm_read"); 188 exit(1); 189 } 190 } 191