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