Add vnodeinfo - a program which scans each mount's vnode list and dumps
[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.3 2004/10/07 00:05:03 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 #include <getopt.h>
36
37 struct nlist Nl[] = {
38 #ifdef CINV_PARENT
39     { "_rootncp" },
40 #else
41     { "_rootnamecache" },
42 #endif
43     { NULL }
44 };
45
46 void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
47 void dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path);
48
49 main(int ac, char **av)
50 {
51     struct namecache *ncptr;
52     kvm_t *kd;
53     const char *corefile = NULL;
54     const char *sysfile = NULL;
55     int ch;
56     int i;
57
58     while ((ch = getopt(ac, av, "M:N:")) != -1) {
59         switch(ch) {
60         case 'M':
61             corefile = optarg;
62             break;
63         case 'N':
64             sysfile = optarg;
65             break;
66         default:
67             fprintf(stderr, "%s [-M core] [-N system]\n", av[0]);
68             exit(1);
69         }
70     }
71
72     if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) {
73         perror("kvm_open");
74         exit(1);
75     }
76     if (kvm_nlist(kd, Nl) != 0) {
77         perror("kvm_nlist");
78         exit(1);
79     }
80 #ifdef CINV_PARENT
81     kkread(kd, Nl[0].n_value, &ncptr, sizeof(ncptr));
82 #else
83     ncptr = (void *)Nl[0].n_value;
84 #endif
85     if (ac == 1) {
86         dumpncp(kd, 0, ncptr, NULL);
87     } else {
88         for (i = 1; i < ac; ++i) {
89             if (av[i][0] != '/')
90                 fprintf(stderr, "%s: path must start at the root\n", av[i]);
91             dumpncp(kd, 0, ncptr, av[i]);
92         }
93     }
94 }
95
96 void
97 dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path)
98 {
99     struct namecache ncp;
100     struct namecache *ncscan;
101     const char *ptr;
102     int haschildren;
103     char name[256];
104
105     kkread(kd, (u_long)ncptr, &ncp, sizeof(ncp));
106     if (ncp.nc_nlen < sizeof(name)) {
107         kkread(kd, (u_long)ncp.nc_name, name, ncp.nc_nlen);
108         name[ncp.nc_nlen] = 0;
109     } else {
110         name[0] = 0;
111     }
112     if (tab == 0) {
113         strcpy(name, "ROOT");
114         if (path)
115             ++path;
116     } else if (ncp.nc_flag & NCF_MOUNTPT) {
117         strcpy(name, "MOUNTGLUE");
118     } else if (name[0] == 0) {
119         strcpy(name, "?");
120         if (path)
121             return;
122     } else if (path) {
123         if ((ptr = strchr(path, '/')) == NULL)
124             ptr = path + strlen(path);
125         if (strlen(name) != ptr - path ||
126             bcmp(name, path, ptr - path) != 0
127         ) {
128             return;
129         }
130         path = ptr;
131         if (*path == '/')
132             ++path;
133         if (*path == 0)
134             path = NULL;
135     }
136
137     if (ncp.nc_list.tqh_first)
138         haschildren = 1;
139     else
140         haschildren = 0;
141
142     if (path)
143         printf("ELM ");
144     else
145         printf("%*.*s%s ", tab, tab, "", name);
146     printf("[ncp=%p par=%p %04x vp=%p", 
147             ncptr, ncp.nc_parent, ncp.nc_flag, ncp.nc_vp);
148     if (ncp.nc_timeout)
149         printf(" timo=%d", ncp.nc_timeout);
150     if (ncp.nc_refs)
151         printf(" refs=%d", ncp.nc_refs);
152     if (ncp.nc_exlocks)
153         printf(" LOCKED(%d,td=%p)", ncp.nc_exlocks, ncp.nc_locktd);
154     printf("]");
155
156     if (path) {
157         printf(" %s\n", name);
158     } else {
159         printf("%s\n", haschildren ? " {" : "");
160     }
161     for (ncscan = ncp.nc_list.tqh_first; ncscan; ncscan = ncp.nc_entry.tqe_next) {
162         kkread(kd, (u_long)ncscan, &ncp, sizeof(ncp));
163         dumpncp(kd, (path ? (tab ? tab : 4) : tab + 4), ncscan, path);
164     }
165     if (haschildren && path == NULL)
166         printf("%*.*s}\n", tab, tab, "");
167 }
168
169 void
170 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
171 {
172     if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
173         perror("kvm_read");
174         exit(1);
175     }
176 }
177