4 * cc -I/usr/src/sys vnodeinfo.c -o /usr/local/bin/vnodeinfo -lkvm
8 * Dump the mountlist and related vnodes.
11 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
13 * This code is derived from software contributed to The DragonFly Project
14 * by Matthew Dillon <dillon@backplane.com>
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in
24 * the documentation and/or other materials provided with the
26 * 3. Neither the name of The DragonFly Project nor the names of its
27 * contributors may be used to endorse or promote products derived
28 * from this software without specific, prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
38 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
39 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
40 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * $DragonFly: src/test/debug/vnodeinfo.c,v 1.8 2005/12/05 16:52:02 dillon Exp $
46 #define _KERNEL_STRUCTURES_
47 #include <sys/param.h>
49 #include <sys/malloc.h>
50 #include <sys/signalvar.h>
51 #include <sys/mount.h>
52 #include <sys/vnode.h>
56 #include <vm/vm_page.h>
57 #include <vm/vm_kern.h>
58 #include <vm/vm_object.h>
59 #include <vm/swap_pager.h>
60 #include <vm/vnode_pager.h>
72 { "_vnode_free_list" },
76 static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
77 static struct mount *dumpmount(kvm_t *kd, struct mount *mp);
78 static struct vnode *dumpvp(kvm_t *kd, struct vnode *vp, int whichlist);
79 static void dumpbufs(kvm_t *kd, void *bufp, const char *id);
80 static int getobjpages(kvm_t *kd, struct vm_object *obj);
81 static int getobjvnpsize(kvm_t *kd, struct vm_object *obj);
86 main(int ac, char **av)
93 const char *corefile = NULL;
94 const char *sysfile = NULL;
96 while ((ch = getopt(ac, av, "bM:N:")) != -1) {
108 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]);
113 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) {
117 if (kvm_nlist(kd, Nl) != 0) {
121 kkread(kd, Nl[0].n_value, &mp, sizeof(mp));
123 mp = dumpmount(kd, mp);
124 kkread(kd, Nl[1].n_value, &vp, sizeof(vp));
125 printf("VNODEFREELIST {\n");
127 vp = dumpvp(kd, vp, 0);
132 static struct mount *
133 dumpmount(kvm_t *kd, struct mount *mp)
138 kkread(kd, (u_long)mp, &mnt, sizeof(mnt));
139 printf("MOUNTPOINT %s on %s {\n",
140 mnt.mnt_stat.f_mntfromname, mnt.mnt_stat.f_mntonname);
141 printf(" lk_flags %08x share %d wait %d excl %d holder = %p\n",
142 mnt.mnt_lock.lk_flags, mnt.mnt_lock.lk_sharecount,
143 mnt.mnt_lock.lk_waitcount, mnt.mnt_lock.lk_exclusivecount,
144 mnt.mnt_lock.lk_lockholder);
145 printf(" mnt_flag %08x mnt_kern_flag %08x\n",
146 mnt.mnt_flag, mnt.mnt_kern_flag);
147 printf(" mnt_nvnodelistsize %d\n", mnt.mnt_nvnodelistsize);
148 printf(" mnt_stat.f_fsid %08x %08x\n", mnt.mnt_stat.f_fsid.val[0],
149 mnt.mnt_stat.f_fsid.val[1]);
150 vp = mnt.mnt_nvnodelist.tqh_first;
152 vp = dumpvp(kd, vp, 1);
156 return(mnt.mnt_list.tqe_next);
160 vtype(enum vtype type)
186 snprintf(buf, sizeof(buf), "%d", (int)type);
190 static struct vnode *
191 dumpvp(kvm_t *kd, struct vnode *vp, int whichlist)
195 kkread(kd, (u_long)vp, &vn, sizeof(vn));
197 printf(" vnode %p usecnt %d holdcnt %d type=%s flags %08x",
198 vp, vn.v_usecount, vn.v_holdcnt, vtype(vn.v_type), vn.v_flag);
200 if ((vn.v_flag & VOBJBUF) && vn.v_object) {
201 int npages = getobjpages(kd, vn.v_object);
202 int vnpsize = getobjvnpsize(kd, vn.v_object);
203 if (npages || vnpsize)
204 printf(" vmobjpgs=%d vnpsize=%d", npages, vnpsize);
207 if (vn.v_flag & VROOT)
209 if (vn.v_flag & VTEXT)
211 if (vn.v_flag & VSYSTEM)
213 if (vn.v_flag & VISTTY)
216 if (vn.v_flag & VXLOCK)
218 if (vn.v_flag & VXWANT)
222 if (vn.v_flag & VRECLAIMED)
223 printf(" VRECLAIMED");
224 if (vn.v_flag & VINACTIVE)
225 printf(" VINACTIVE");
227 if (vn.v_flag & VBWAIT)
229 if (vn.v_flag & VOBJBUF)
231 if (vn.v_flag & VAGE)
233 if (vn.v_flag & VOLOCK)
235 if (vn.v_flag & VOWANT)
238 if (vn.v_flag & VDOOMED)
241 if (vn.v_flag & VFREE)
244 if (vn.v_flag & VINFREE)
247 if (vn.v_flag & VONWORKLST)
248 printf(" VONWORKLST");
249 if (vn.v_flag & VMOUNT)
251 if (vn.v_flag & VOBJDIRTY)
252 printf(" VOBJDIRTY");
256 if (vn.v_lock.lk_sharecount || vn.v_lock.lk_waitcount ||
257 vn.v_lock.lk_exclusivecount || vn.v_lock.lk_lockholder != LK_NOTHREAD) {
258 printf("\tlk_flags %08x share %d wait %d excl %d holder = %p\n",
259 vn.v_lock.lk_flags, vn.v_lock.lk_sharecount,
260 vn.v_lock.lk_waitcount, vn.v_lock.lk_exclusivecount,
261 vn.v_lock.lk_lockholder);
265 if (vn.v_rbclean_tree.rbh_root) {
266 printf("\tCLEAN BUFFERS\n");
267 dumpbufs(kd, vn.v_rbclean_tree.rbh_root, "ROOT");
269 if (vn.v_rbdirty_tree.rbh_root) {
270 printf("\tDIRTY BUFFERS\n");
271 dumpbufs(kd, vn.v_rbdirty_tree.rbh_root, "ROOT");
276 return(vn.v_nmntvnodes.tqe_next);
278 return(vn.v_freelist.tqe_next);
282 dumpbufs(kvm_t *kd, void *bufp, const char *id)
286 kkread(kd, (u_long)bufp, &buf, sizeof(buf));
287 printf("\t %-8s %p lbn %5d fbn %6d\n",
292 if (buf.b_rbnode.rbe_left)
293 dumpbufs(kd, buf.b_rbnode.rbe_left, "LEFT");
294 if (buf.b_rbnode.rbe_right)
295 dumpbufs(kd, buf.b_rbnode.rbe_right, "RIGHT");
300 getobjpages(kvm_t *kd, struct vm_object *obj)
302 struct vm_object vmobj;
304 kkread(kd, (u_long)obj, &vmobj, sizeof(vmobj));
305 return(vmobj.resident_page_count);
310 getobjvnpsize(kvm_t *kd, struct vm_object *obj)
312 struct vm_object vmobj;
314 kkread(kd, (u_long)obj, &vmobj, sizeof(vmobj));
315 return(vmobj.un_pager.vnp.vnp_size);
319 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
321 if (kvm_read(kd, addr, buf, nbytes) != nbytes) {