1 /* 2 * SLABINFO.C 3 * 4 * cc -I/usr/src/sys slabinfo.c -o /usr/local/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, SLZone *kslz); 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 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 for (i = 0; i < ncpus; ++i) { 131 kkread(kd, Nl[0].n_value + i * sizeof(struct privatespace), &gd, sizeof(gd)); 132 printf("CPU %02d (NFreeZones=%d) {\n", 133 i, gd.gd_slab.NFreeZones); 134 totalfree += gd.gd_slab.NFreeZones; 135 136 for (j = 0; j < NZONES; ++j) { 137 printf(" Zone %02d {\n", j); 138 totalzones += slzonedump(kd, gd.gd_slab.ZoneAry[j]); 139 printf(" }\n"); 140 } 141 142 printf(" FreeZone {\n"); 143 totalzones += slzonedump(kd, gd.gd_slab.FreeZones); 144 printf(" }\n"); 145 146 printf(" FreeOVZon {\n"); 147 totalzones += slzonedump(kd, gd.gd_slab.FreeOvZones); 148 printf(" }\n"); 149 150 printf("}\n"); 151 } 152 printf("TotalZones %d x 131072 = %jd\n", 153 totalzones, (intmax_t)totalzones * 131072LL); 154 printf("TotalFree %d x 131072 = %jd\n", 155 totalfree, (intmax_t)totalfree * 131072LL); 156 return(0); 157 } 158 159 int 160 slzonedump(kvm_t *kd, SLZone *kslz) 161 { 162 SLZone slz; 163 int count = 0; 164 165 while (kslz) { 166 kkread(kd, (u_long)kslz, &slz, sizeof(slz)); 167 printf("\t{ magic=%08x cpu=%d chunking=%d NFree=%d/%d RCnt=%d}\n", 168 slz.z_Magic, slz.z_Cpu, slz.z_ChunkSize, 169 slz.z_NFree, slz.z_NMax, slz.z_RCount); 170 kslz = slz.z_Next; 171 ++count; 172 } 173 return(count); 174 } 175 176 void 177 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) 178 { 179 if (kvm_read(kd, addr, buf, nbytes) != nbytes) { 180 perror("kvm_read"); 181 exit(1); 182 } 183 } 184