xref: /dragonfly/test/debug/mbufinfo.c (revision b7cb6098)
1e2184a9eSMatthew Dillon /*
2e2184a9eSMatthew Dillon  * MBUFINFO.C
3e2184a9eSMatthew Dillon  *
4e2184a9eSMatthew Dillon  * cc -I/usr/src/sys mbufinfo.c -o /usr/local/bin/mbufinfo -lkvm
5e2184a9eSMatthew Dillon  *
6e2184a9eSMatthew Dillon  * mbufinfo
7e2184a9eSMatthew Dillon  *
8e2184a9eSMatthew Dillon  * Dump the MBUF_DEBUG mtrack tree.
9e2184a9eSMatthew Dillon  *
10e2184a9eSMatthew Dillon  * Copyright (c) 2010 The DragonFly Project.  All rights reserved.
11e2184a9eSMatthew Dillon  *
12e2184a9eSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
13e2184a9eSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
14e2184a9eSMatthew Dillon  *
15e2184a9eSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
16e2184a9eSMatthew Dillon  * modification, are permitted provided that the following conditions
17e2184a9eSMatthew Dillon  * are met:
18e2184a9eSMatthew Dillon  *
19e2184a9eSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
20e2184a9eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
21e2184a9eSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
22e2184a9eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
23e2184a9eSMatthew Dillon  *    the documentation and/or other materials provided with the
24e2184a9eSMatthew Dillon  *    distribution.
25e2184a9eSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
26e2184a9eSMatthew Dillon  *    contributors may be used to endorse or promote products derived
27e2184a9eSMatthew Dillon  *    from this software without specific, prior written permission.
28e2184a9eSMatthew Dillon  *
29e2184a9eSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30e2184a9eSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31e2184a9eSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32e2184a9eSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
33e2184a9eSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34e2184a9eSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
35e2184a9eSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36e2184a9eSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
37e2184a9eSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38e2184a9eSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
39e2184a9eSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40e2184a9eSMatthew Dillon  * SUCH DAMAGE.
41e2184a9eSMatthew Dillon  */
42e2184a9eSMatthew Dillon 
43e2184a9eSMatthew Dillon #define _KERNEL_STRUCTURES
44e2184a9eSMatthew Dillon #define MBUF_DEBUG
45e2184a9eSMatthew Dillon #include <sys/param.h>
46e2184a9eSMatthew Dillon #include <sys/user.h>
47e2184a9eSMatthew Dillon #include <sys/malloc.h>
48e2184a9eSMatthew Dillon #include <sys/signalvar.h>
49e2184a9eSMatthew Dillon #include <sys/namecache.h>
50e2184a9eSMatthew Dillon #include <sys/mount.h>
51e2184a9eSMatthew Dillon #include <sys/vnode.h>
52e2184a9eSMatthew Dillon #include <sys/buf.h>
53e2184a9eSMatthew Dillon #include <sys/mbuf.h>
54e2184a9eSMatthew Dillon #include <sys/tree.h>
55e2184a9eSMatthew Dillon 
56e2184a9eSMatthew Dillon #include <vm/vm.h>
57e2184a9eSMatthew Dillon #include <vm/vm_page.h>
58e2184a9eSMatthew Dillon #include <vm/vm_kern.h>
59e2184a9eSMatthew Dillon #include <vm/vm_object.h>
60e2184a9eSMatthew Dillon #include <vm/swap_pager.h>
61e2184a9eSMatthew Dillon #include <vm/vnode_pager.h>
62e2184a9eSMatthew Dillon 
63e2184a9eSMatthew Dillon #include <vfs/ufs/quota.h>
64e2184a9eSMatthew Dillon #include <vfs/ufs/inode.h>
65e2184a9eSMatthew Dillon 
66e2184a9eSMatthew Dillon #include <stdio.h>
67e2184a9eSMatthew Dillon #include <stdlib.h>
68e2184a9eSMatthew Dillon #include <string.h>
69e2184a9eSMatthew Dillon #include <fcntl.h>
70e2184a9eSMatthew Dillon #include <kvm.h>
71*b7cb6098SMatthew Dillon #include <ctype.h>
72e2184a9eSMatthew Dillon #include <nlist.h>
73e2184a9eSMatthew Dillon #include <getopt.h>
74e2184a9eSMatthew Dillon 
75e2184a9eSMatthew Dillon struct mbtrack {
76e2184a9eSMatthew Dillon         RB_ENTRY(mbtrack) rb_node;
77e2184a9eSMatthew Dillon 	int trackid;
78e2184a9eSMatthew Dillon 	struct mbuf *m;
79e2184a9eSMatthew Dillon };
80e2184a9eSMatthew Dillon 
81e2184a9eSMatthew Dillon RB_HEAD(mbuf_rb_tree, mbtrack);
82e2184a9eSMatthew Dillon RB_PROTOTYPE2(mbuf_rb_tree, mbtrack, rb_node, mbtrack_cmp, struct mbuf *);
83e2184a9eSMatthew Dillon 
84e2184a9eSMatthew Dillon struct nlist Nl[] = {
85e2184a9eSMatthew Dillon     { "_mbuf_track_root" },
86e2184a9eSMatthew Dillon     { NULL }
87e2184a9eSMatthew Dillon };
88e2184a9eSMatthew Dillon 
89e2184a9eSMatthew Dillon static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
90e2184a9eSMatthew Dillon static void dumpmb(kvm_t *kd, struct mbtrack *mtp);
91e2184a9eSMatthew Dillon static void dumpmbdata(kvm_t *kd, char *data, int len);
92e2184a9eSMatthew Dillon 
93e2184a9eSMatthew Dillon struct mbuf_rb_tree tree;
94e2184a9eSMatthew Dillon 
95e2184a9eSMatthew Dillon int tracks[256];
96e2184a9eSMatthew Dillon int count_cluster;
97e2184a9eSMatthew Dillon int count_ext;
98e2184a9eSMatthew Dillon int count_noncluster;
99e2184a9eSMatthew Dillon int count_data_bytes;
100e2184a9eSMatthew Dillon int count_buffer_space;
101e2184a9eSMatthew Dillon 
102e2184a9eSMatthew Dillon int VerboseOpt;
103e2184a9eSMatthew Dillon 
104e2184a9eSMatthew Dillon int
main(int ac,char ** av)105e2184a9eSMatthew Dillon main(int ac, char **av)
106e2184a9eSMatthew Dillon {
107e2184a9eSMatthew Dillon     kvm_t *kd;
108e2184a9eSMatthew Dillon     int i;
109e2184a9eSMatthew Dillon     int ch;
110e2184a9eSMatthew Dillon     const char *corefile = NULL;
111e2184a9eSMatthew Dillon     const char *sysfile = NULL;
112e2184a9eSMatthew Dillon 
113e2184a9eSMatthew Dillon     while ((ch = getopt(ac, av, "vM:N:")) != -1) {
114e2184a9eSMatthew Dillon 	switch(ch) {
115e2184a9eSMatthew Dillon 	case 'M':
116e2184a9eSMatthew Dillon 	    corefile = optarg;
117e2184a9eSMatthew Dillon 	    break;
118e2184a9eSMatthew Dillon 	case 'N':
119e2184a9eSMatthew Dillon 	    sysfile = optarg;
120e2184a9eSMatthew Dillon 	    break;
121e2184a9eSMatthew Dillon 	case 'v':
122e2184a9eSMatthew Dillon 	    ++VerboseOpt;
123e2184a9eSMatthew Dillon 	    break;
124e2184a9eSMatthew Dillon 	default:
125e2184a9eSMatthew Dillon 	    fprintf(stderr, "%s [-M core] [-N system]\n", av[0]);
126e2184a9eSMatthew Dillon 	    exit(1);
127e2184a9eSMatthew Dillon 	}
128e2184a9eSMatthew Dillon     }
129e2184a9eSMatthew Dillon 
130e2184a9eSMatthew Dillon     if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) {
131e2184a9eSMatthew Dillon 	perror("kvm_open");
132e2184a9eSMatthew Dillon 	exit(1);
133e2184a9eSMatthew Dillon     }
134e2184a9eSMatthew Dillon     if (kvm_nlist(kd, Nl) != 0) {
135e2184a9eSMatthew Dillon 	perror("kvm_nlist");
136e2184a9eSMatthew Dillon 	exit(1);
137e2184a9eSMatthew Dillon     }
138e2184a9eSMatthew Dillon     kkread(kd, Nl[0].n_value, &tree, sizeof(tree));
139e2184a9eSMatthew Dillon     if (tree.rbh_root)
140e2184a9eSMatthew Dillon 	dumpmb(kd, tree.rbh_root);
141e2184a9eSMatthew Dillon 
142e2184a9eSMatthew Dillon     printf("Histogram:\n");
143e2184a9eSMatthew Dillon     for (i = 0; i < 256; ++i) {
144e2184a9eSMatthew Dillon 	if (tracks[i]) {
145e2184a9eSMatthew Dillon 		printf("%d\t%d\n", i, tracks[i]);
146e2184a9eSMatthew Dillon 	}
147e2184a9eSMatthew Dillon     }
148e2184a9eSMatthew Dillon     printf("clusters: %d\n", count_cluster);
149e2184a9eSMatthew Dillon     printf("normal:   %d\n", count_noncluster);
150e2184a9eSMatthew Dillon     printf("external: %d\n", count_ext);
151e2184a9eSMatthew Dillon     printf("data:     %d\n", count_data_bytes);
152e2184a9eSMatthew Dillon     printf("bufspace: %d\n", count_buffer_space);
153e2184a9eSMatthew Dillon     return(0);
154e2184a9eSMatthew Dillon }
155e2184a9eSMatthew Dillon 
156e2184a9eSMatthew Dillon static void
dumpmb(kvm_t * kd,struct mbtrack * mtp)157e2184a9eSMatthew Dillon dumpmb(kvm_t *kd, struct mbtrack *mtp)
158e2184a9eSMatthew Dillon {
159e2184a9eSMatthew Dillon     struct mbtrack mt;
160e2184a9eSMatthew Dillon     struct mbuf mb;
161e2184a9eSMatthew Dillon 
162e2184a9eSMatthew Dillon     kkread(kd, (long)mtp, &mt, sizeof(mt));
163e2184a9eSMatthew Dillon 
164e2184a9eSMatthew Dillon     if (mt.rb_node.rbe_left)
165e2184a9eSMatthew Dillon 	dumpmb(kd, mt.rb_node.rbe_left);
166e2184a9eSMatthew Dillon 
167e2184a9eSMatthew Dillon     if (VerboseOpt)
168e2184a9eSMatthew Dillon 	    printf("mbuf %p track %d\n", mt.m, mt.trackid);
169e2184a9eSMatthew Dillon     if (mt.trackid >= 0 && mt.trackid < 256)
170e2184a9eSMatthew Dillon 	++tracks[mt.trackid];
171e2184a9eSMatthew Dillon     if (mt.m) {
172e2184a9eSMatthew Dillon 	kkread(kd, (long)mt.m, &mb, sizeof(mb));
173e2184a9eSMatthew Dillon 	if (mb.m_flags & M_EXT_CLUSTER)
174e2184a9eSMatthew Dillon 		++count_cluster;
175e2184a9eSMatthew Dillon 	else if (mb.m_flags & M_EXT)
176e2184a9eSMatthew Dillon 		++count_ext;
177e2184a9eSMatthew Dillon 	else
178e2184a9eSMatthew Dillon 		++count_noncluster;
179e2184a9eSMatthew Dillon 	count_data_bytes += mb.m_len;
180e2184a9eSMatthew Dillon 	if (mb.m_flags & M_EXT) {
181e2184a9eSMatthew Dillon 		count_buffer_space += mb.m_ext.ext_size;
182e2184a9eSMatthew Dillon 	} else {
183e2184a9eSMatthew Dillon 		count_buffer_space += MLEN;
184e2184a9eSMatthew Dillon 	}
185e2184a9eSMatthew Dillon 	if (VerboseOpt) {
186e2184a9eSMatthew Dillon 		dumpmbdata(kd, mb.m_data, mb.m_len);
187e2184a9eSMatthew Dillon 	}
188e2184a9eSMatthew Dillon     }
189e2184a9eSMatthew Dillon 
190e2184a9eSMatthew Dillon     if (mt.rb_node.rbe_right)
191e2184a9eSMatthew Dillon 	dumpmb(kd, mt.rb_node.rbe_right);
192e2184a9eSMatthew Dillon }
193e2184a9eSMatthew Dillon 
194e2184a9eSMatthew Dillon static void
dumpmbdata(kvm_t * kd,char * data,int len)195e2184a9eSMatthew Dillon dumpmbdata(kvm_t *kd, char *data, int len)
196e2184a9eSMatthew Dillon {
197e2184a9eSMatthew Dillon     char buf[256];
198e2184a9eSMatthew Dillon     int i;
199e2184a9eSMatthew Dillon     int j;
200e2184a9eSMatthew Dillon     int n;
201e2184a9eSMatthew Dillon     int count;
202e2184a9eSMatthew Dillon 
203e2184a9eSMatthew Dillon     for (n = 0; n < len; n += count) {
204e2184a9eSMatthew Dillon 	count = len - n;
205e2184a9eSMatthew Dillon 	if (count > sizeof(buf))
206e2184a9eSMatthew Dillon 		count = sizeof(buf);
207e2184a9eSMatthew Dillon 	kkread(kd, (long)data + n, buf, count);
208e2184a9eSMatthew Dillon 	for (i = 0; i < count; ++i) {
209e2184a9eSMatthew Dillon 	    if ((n + i) % 16 == 0) {
210e2184a9eSMatthew Dillon 		printf("    %04x ", n + i);
211e2184a9eSMatthew Dillon 	    }
212e2184a9eSMatthew Dillon 	    printf(" %02x", (unsigned char)buf[i]);
213e2184a9eSMatthew Dillon 	    if ((n + i) % 16 == 15 || i + 1 == count) {
214e2184a9eSMatthew Dillon 		printf(" ");
215e2184a9eSMatthew Dillon 		for (j = i & ~15; j <= i; ++j)
216e2184a9eSMatthew Dillon 		    printf("%c", isprint(buf[j]) ? buf[j] : '.');
217e2184a9eSMatthew Dillon 		printf("\n");
218e2184a9eSMatthew Dillon 	    }
219e2184a9eSMatthew Dillon 	}
220e2184a9eSMatthew Dillon 	printf("\n");
221e2184a9eSMatthew Dillon     }
222e2184a9eSMatthew Dillon }
223e2184a9eSMatthew Dillon 
224e2184a9eSMatthew Dillon static void
kkread(kvm_t * kd,u_long addr,void * buf,size_t nbytes)225e2184a9eSMatthew Dillon kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
226e2184a9eSMatthew Dillon {
227e2184a9eSMatthew Dillon     if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
228e2184a9eSMatthew Dillon         perror("kvm_read");
229e2184a9eSMatthew Dillon         exit(1);
230e2184a9eSMatthew Dillon     }
231e2184a9eSMatthew Dillon }
232