Add a debugging utility which dumps that kernel's namecache topology.
[dragonfly.git] / test / debug / ncptrace.c
1 /*
2  * NCPTRACE.C
3  *
4  * cc -I/usr/src/sys ncptrace.c -o /usr/local/bin/ncptrace -lkvm
5  *
6  * ncptrace
7  * ncptrace [path]
8  *
9  * Trace and dump the kernel namecache hierarchy.  If a path is specified
10  * the trace begins there, otherwise the trace begins at the root.
11  *
12  * $DragonFly: src/test/debug/ncptrace.c,v 1.1 2004/10/03 06:12:34 dillon Exp $
13  */
14
15 #define _KERNEL_STRUCTURES_
16 #include <sys/param.h>
17 #include <sys/user.h>
18 #include <sys/malloc.h>
19 #include <sys/signalvar.h>
20 #include <sys/vnode.h>
21 #include <sys/namecache.h>
22
23 #include <vm/vm.h>
24 #include <vm/vm_page.h>
25 #include <vm/vm_kern.h>
26 #include <vm/swap_pager.h>
27 #include <vm/vnode_pager.h>
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <kvm.h>
34 #include <nlist.h>
35
36 struct nlist Nl[] = {
37     { "_rootncp" },
38     { NULL }
39 };
40
41 void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
42 void dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path);
43
44 main(int ac, char **av)
45 {
46     struct namecache *ncptr;
47     kvm_t *kd;
48     int i;
49
50     if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm:")) == NULL) {
51         perror("kvm_open");
52         exit(1);
53     }
54     if (kvm_nlist(kd, Nl) != 0) {
55         perror("kvm_nlist");
56         exit(1);
57     }
58     kkread(kd, Nl[0].n_value, &ncptr, sizeof(ncptr));
59     if (ac == 1) {
60         dumpncp(kd, 0, ncptr, NULL);
61     } else {
62         for (i = 1; i < ac; ++i) {
63             if (av[i][0] != '/')
64                 fprintf(stderr, "%s: path must start at the root\n", av[i]);
65             dumpncp(kd, 0, ncptr, av[i]);
66         }
67     }
68 }
69
70 void
71 dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path)
72 {
73     struct namecache ncp;
74     struct namecache *ncscan;
75     const char *ptr;
76     int haschildren;
77     char name[256];
78
79     kkread(kd, (u_long)ncptr, &ncp, sizeof(ncp));
80     if (ncp.nc_nlen < sizeof(name)) {
81         kkread(kd, (u_long)ncp.nc_name, name, ncp.nc_nlen);
82         name[ncp.nc_nlen] = 0;
83     } else {
84         name[0] = 0;
85     }
86     if (tab == 0) {
87         strcpy(name, "ROOT");
88         if (path)
89             ++path;
90     } else if (ncp.nc_flag & NCF_MOUNTPT) {
91         strcpy(name, "MOUNTGLUE");
92     } else if (name[0] == 0) {
93         strcpy(name, "?");
94         if (path)
95             return;
96     } else if (path) {
97         if ((ptr = strchr(path, '/')) == NULL)
98             ptr = path + strlen(path);
99         if (strlen(name) != ptr - path ||
100             bcmp(name, path, ptr - path) != 0
101         ) {
102             return;
103         }
104         path = ptr;
105         if (*path == '/')
106             ++path;
107         if (*path == 0)
108             path = NULL;
109     }
110
111     if (ncp.nc_list.tqh_first)
112         haschildren = 1;
113     else
114         haschildren = 0;
115
116     if (path) {
117         printf("ELM [ncp=%p par=%p %04x vp=%p] %s\n", 
118                 ncptr, ncp.nc_parent, ncp.nc_flag, 
119                 ncp.nc_vp, name);
120     } else {
121         printf("%*.*s%s [ncp=%p par=%p %04x vp=%p]%s\n", tab, tab, "", name, 
122                 ncptr, ncp.nc_parent, ncp.nc_flag, ncp.nc_vp,
123                 haschildren ? " {" : "");
124     }
125     for (ncscan = ncp.nc_list.tqh_first; ncscan; ncscan = ncp.nc_entry.tqe_next) {
126         kkread(kd, (u_long)ncscan, &ncp, sizeof(ncp));
127         dumpncp(kd, (path ? (tab ? tab : 4) : tab + 4), ncscan, path);
128     }
129     if (haschildren && path == NULL)
130         printf("%*.*s}\n", tab, tab, "");
131 }
132
133 void
134 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
135 {
136     if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
137         perror("kvm_read");
138         exit(1);
139     }
140 }
141