1 /* 2 * VNODEINFO.C 3 * 4 * cc -I/usr/src/sys vnodeinfo.c -o /usr/local/bin/vnodeinfo -lkvm 5 * 6 * vnodeinfo 7 * 8 * Dump the mountlist and related vnodes. 9 * 10 * 11 * Copyright (c) 2004 The DragonFly Project. All rights reserved. 12 * 13 * This code is derived from software contributed to The DragonFly Project 14 * by Matthew Dillon <dillon@backplane.com> 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 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 25 * distribution. 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. 29 * 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 41 * SUCH DAMAGE. 42 * 43 * $DragonFly: src/test/debug/vnodeinfo.c,v 1.4 2004/10/14 20:54:11 dillon Exp $ 44 */ 45 46 #define _KERNEL_STRUCTURES_ 47 #include <sys/param.h> 48 #include <sys/user.h> 49 #include <sys/malloc.h> 50 #include <sys/signalvar.h> 51 #include <sys/mount.h> 52 #include <sys/vnode.h> 53 54 #include <vm/vm.h> 55 #include <vm/vm_page.h> 56 #include <vm/vm_kern.h> 57 #include <vm/vm_object.h> 58 #include <vm/swap_pager.h> 59 #include <vm/vnode_pager.h> 60 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 #include <fcntl.h> 65 #include <kvm.h> 66 #include <nlist.h> 67 #include <getopt.h> 68 69 struct nlist Nl[] = { 70 { "_mountlist" }, 71 { "_vnode_free_list" }, 72 { NULL } 73 }; 74 75 static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes); 76 static struct mount *dumpmount(kvm_t *kd, struct mount *mp); 77 static struct vnode *dumpvp(kvm_t *kd, struct vnode *vp, int whichlist); 78 static int getobjpages(kvm_t *kd, struct vm_object *obj); 79 80 main(int ac, char **av) 81 { 82 struct mount *mp; 83 struct vnode *vp; 84 kvm_t *kd; 85 int i; 86 int ch; 87 const char *corefile = NULL; 88 const char *sysfile = NULL; 89 90 while ((ch = getopt(ac, av, "M:N:")) != -1) { 91 switch(ch) { 92 case 'M': 93 corefile = optarg; 94 break; 95 case 'N': 96 sysfile = optarg; 97 break; 98 default: 99 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); 100 exit(1); 101 } 102 } 103 104 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { 105 perror("kvm_open"); 106 exit(1); 107 } 108 if (kvm_nlist(kd, Nl) != 0) { 109 perror("kvm_nlist"); 110 exit(1); 111 } 112 kkread(kd, Nl[0].n_value, &mp, sizeof(mp)); 113 while (mp) 114 mp = dumpmount(kd, mp); 115 kkread(kd, Nl[1].n_value, &vp, sizeof(vp)); 116 printf("VNODEFREELIST {\n"); 117 while (vp) 118 vp = dumpvp(kd, vp, 0); 119 printf("}\n"); 120 return(0); 121 } 122 123 static struct mount * 124 dumpmount(kvm_t *kd, struct mount *mp) 125 { 126 struct mount mnt; 127 struct vnode *vp; 128 129 kkread(kd, (u_long)mp, &mnt, sizeof(mnt)); 130 printf("MOUNTPOINT %s on %s {\n", 131 mnt.mnt_stat.f_mntfromname, mnt.mnt_stat.f_mntonname); 132 printf(" lk_flags %08x share %d wait %d excl %d holder = %p\n", 133 mnt.mnt_lock.lk_flags, mnt.mnt_lock.lk_sharecount, 134 mnt.mnt_lock.lk_waitcount, mnt.mnt_lock.lk_exclusivecount, 135 mnt.mnt_lock.lk_lockholder); 136 printf(" mnt_flag %08x mnt_kern_flag %08x\n", 137 mnt.mnt_flag, mnt.mnt_kern_flag); 138 printf(" mnt_nvnodelistsize %d\n", mnt.mnt_nvnodelistsize); 139 vp = mnt.mnt_nvnodelist.tqh_first; 140 while (vp) 141 vp = dumpvp(kd, vp, 1); 142 143 printf("}\n"); 144 145 return(mnt.mnt_list.tqe_next); 146 } 147 148 static const char * 149 vtype(enum vtype type) 150 { 151 static char buf[32]; 152 153 switch(type) { 154 case VNON: 155 return("VNON"); 156 case VREG: 157 return("VREG"); 158 case VDIR: 159 return("VDIR"); 160 case VBLK: 161 return("VBLK"); 162 case VCHR: 163 return("VCHR"); 164 case VLNK: 165 return("VLNK"); 166 case VSOCK: 167 return("VSOCK"); 168 case VFIFO: 169 return("VFIFO"); 170 case VBAD: 171 return("VBAD"); 172 default: 173 break; 174 } 175 snprintf(buf, sizeof(buf), "%d", (int)type); 176 return(buf); 177 } 178 179 static struct vnode * 180 dumpvp(kvm_t *kd, struct vnode *vp, int whichlist) 181 { 182 struct vnode vn; 183 184 kkread(kd, (u_long)vp, &vn, sizeof(vn)); 185 186 printf(" vnode %p usecnt %d holdcnt %d type=%s flags %08x", 187 vp, vn.v_usecount, vn.v_holdcnt, vtype(vn.v_type), vn.v_flag); 188 189 if ((vn.v_flag & VOBJBUF) && vn.v_object) { 190 int npages = getobjpages(kd, vn.v_object); 191 if (npages) 192 printf(" vmobjpgs=%d", npages); 193 } 194 195 if (vn.v_flag & VROOT) 196 printf(" VROOT"); 197 if (vn.v_flag & VTEXT) 198 printf(" VTEXT"); 199 if (vn.v_flag & VSYSTEM) 200 printf(" VSYSTEM"); 201 if (vn.v_flag & VISTTY) 202 printf(" VISTTY"); 203 #ifdef VXLOCK 204 if (vn.v_flag & VXLOCK) 205 printf(" VXLOCK"); 206 if (vn.v_flag & VXWANT) 207 printf(" VXWANT"); 208 #endif 209 #ifdef VRECLAIMED 210 if (vn.v_flag & VRECLAIMED) 211 printf(" VRECLAIMED"); 212 if (vn.v_flag & VINACTIVE) 213 printf(" VINACTIVE"); 214 #endif 215 if (vn.v_flag & VBWAIT) 216 printf(" VBWAIT"); 217 if (vn.v_flag & VOBJBUF) 218 printf(" VOBJBUF"); 219 if (vn.v_flag & VAGE) 220 printf(" VAGE"); 221 if (vn.v_flag & VOLOCK) 222 printf(" VOLOCK"); 223 if (vn.v_flag & VOWANT) 224 printf(" VOWANT"); 225 #ifdef VDOOMED 226 if (vn.v_flag & VDOOMED) 227 printf(" VDOOMED"); 228 #endif 229 if (vn.v_flag & VFREE) 230 printf(" VFREE"); 231 #ifdef VINFREE 232 if (vn.v_flag & VINFREE) 233 printf(" VINFREE"); 234 #endif 235 if (vn.v_flag & VONWORKLST) 236 printf(" VONWORKLST"); 237 if (vn.v_flag & VMOUNT) 238 printf(" VMOUNT"); 239 if (vn.v_flag & VOBJDIRTY) 240 printf(" VOBJDIRTY"); 241 if (vn.v_flag & VPLACEMARKER) 242 printf(" VPLACEMARKER"); 243 244 printf("\n"); 245 246 if (vn.v_lock.lk_sharecount || vn.v_lock.lk_waitcount || 247 vn.v_lock.lk_exclusivecount || vn.v_lock.lk_lockholder != LK_NOTHREAD) { 248 printf("\tlk_flags %08x share %d wait %d excl %d holder = %p\n", 249 vn.v_lock.lk_flags, vn.v_lock.lk_sharecount, 250 vn.v_lock.lk_waitcount, vn.v_lock.lk_exclusivecount, 251 vn.v_lock.lk_lockholder); 252 } 253 254 if (whichlist) 255 return(vn.v_nmntvnodes.tqe_next); 256 else 257 return(vn.v_freelist.tqe_next); 258 } 259 260 static 261 int 262 getobjpages(kvm_t *kd, struct vm_object *obj) 263 { 264 struct vm_object vmobj; 265 266 kkread(kd, (u_long)obj, &vmobj, sizeof(vmobj)); 267 return(vmobj.resident_page_count); 268 } 269 270 static void 271 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) 272 { 273 if (kvm_read(kd, addr, buf, nbytes) != nbytes) { 274 perror("kvm_read"); 275 exit(1); 276 } 277 } 278 279