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.7 2005/08/28 23:35:35 corecode 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 static int getobjvnpsize(kvm_t *kd, struct vm_object *obj); 80 81 main(int ac, char **av) 82 { 83 struct mount *mp; 84 struct vnode *vp; 85 kvm_t *kd; 86 int i; 87 int ch; 88 const char *corefile = NULL; 89 const char *sysfile = NULL; 90 91 while ((ch = getopt(ac, av, "M:N:")) != -1) { 92 switch(ch) { 93 case 'M': 94 corefile = optarg; 95 break; 96 case 'N': 97 sysfile = optarg; 98 break; 99 default: 100 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); 101 exit(1); 102 } 103 } 104 105 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { 106 perror("kvm_open"); 107 exit(1); 108 } 109 if (kvm_nlist(kd, Nl) != 0) { 110 perror("kvm_nlist"); 111 exit(1); 112 } 113 kkread(kd, Nl[0].n_value, &mp, sizeof(mp)); 114 while (mp) 115 mp = dumpmount(kd, mp); 116 kkread(kd, Nl[1].n_value, &vp, sizeof(vp)); 117 printf("VNODEFREELIST {\n"); 118 while (vp) 119 vp = dumpvp(kd, vp, 0); 120 printf("}\n"); 121 return(0); 122 } 123 124 static struct mount * 125 dumpmount(kvm_t *kd, struct mount *mp) 126 { 127 struct mount mnt; 128 struct vnode *vp; 129 130 kkread(kd, (u_long)mp, &mnt, sizeof(mnt)); 131 printf("MOUNTPOINT %s on %s {\n", 132 mnt.mnt_stat.f_mntfromname, mnt.mnt_stat.f_mntonname); 133 printf(" lk_flags %08x share %d wait %d excl %d holder = %p\n", 134 mnt.mnt_lock.lk_flags, mnt.mnt_lock.lk_sharecount, 135 mnt.mnt_lock.lk_waitcount, mnt.mnt_lock.lk_exclusivecount, 136 mnt.mnt_lock.lk_lockholder); 137 printf(" mnt_flag %08x mnt_kern_flag %08x\n", 138 mnt.mnt_flag, mnt.mnt_kern_flag); 139 printf(" mnt_nvnodelistsize %d\n", mnt.mnt_nvnodelistsize); 140 printf(" mnt_stat.f_fsid %08x %08x\n", mnt.mnt_stat.f_fsid.val[0], 141 mnt.mnt_stat.f_fsid.val[1]); 142 vp = mnt.mnt_nvnodelist.tqh_first; 143 while (vp) 144 vp = dumpvp(kd, vp, 1); 145 146 printf("}\n"); 147 148 return(mnt.mnt_list.tqe_next); 149 } 150 151 static const char * 152 vtype(enum vtype type) 153 { 154 static char buf[32]; 155 156 switch(type) { 157 case VNON: 158 return("VNON"); 159 case VREG: 160 return("VREG"); 161 case VDIR: 162 return("VDIR"); 163 case VBLK: 164 return("VBLK"); 165 case VCHR: 166 return("VCHR"); 167 case VLNK: 168 return("VLNK"); 169 case VSOCK: 170 return("VSOCK"); 171 case VFIFO: 172 return("VFIFO"); 173 case VBAD: 174 return("VBAD"); 175 default: 176 break; 177 } 178 snprintf(buf, sizeof(buf), "%d", (int)type); 179 return(buf); 180 } 181 182 static struct vnode * 183 dumpvp(kvm_t *kd, struct vnode *vp, int whichlist) 184 { 185 struct vnode vn; 186 187 kkread(kd, (u_long)vp, &vn, sizeof(vn)); 188 189 printf(" vnode %p usecnt %d holdcnt %d type=%s flags %08x", 190 vp, vn.v_usecount, vn.v_holdcnt, vtype(vn.v_type), vn.v_flag); 191 192 if ((vn.v_flag & VOBJBUF) && vn.v_object) { 193 int npages = getobjpages(kd, vn.v_object); 194 int vnpsize = getobjvnpsize(kd, vn.v_object); 195 if (npages || vnpsize) 196 printf(" vmobjpgs=%d vnpsize=%d", npages, vnpsize); 197 } 198 199 if (vn.v_flag & VROOT) 200 printf(" VROOT"); 201 if (vn.v_flag & VTEXT) 202 printf(" VTEXT"); 203 if (vn.v_flag & VSYSTEM) 204 printf(" VSYSTEM"); 205 if (vn.v_flag & VISTTY) 206 printf(" VISTTY"); 207 #ifdef VXLOCK 208 if (vn.v_flag & VXLOCK) 209 printf(" VXLOCK"); 210 if (vn.v_flag & VXWANT) 211 printf(" VXWANT"); 212 #endif 213 #ifdef VRECLAIMED 214 if (vn.v_flag & VRECLAIMED) 215 printf(" VRECLAIMED"); 216 if (vn.v_flag & VINACTIVE) 217 printf(" VINACTIVE"); 218 #endif 219 if (vn.v_flag & VBWAIT) 220 printf(" VBWAIT"); 221 if (vn.v_flag & VOBJBUF) 222 printf(" VOBJBUF"); 223 if (vn.v_flag & VAGE) 224 printf(" VAGE"); 225 if (vn.v_flag & VOLOCK) 226 printf(" VOLOCK"); 227 if (vn.v_flag & VOWANT) 228 printf(" VOWANT"); 229 #ifdef VDOOMED 230 if (vn.v_flag & VDOOMED) 231 printf(" VDOOMED"); 232 #endif 233 if (vn.v_flag & VFREE) 234 printf(" VFREE"); 235 #ifdef VINFREE 236 if (vn.v_flag & VINFREE) 237 printf(" VINFREE"); 238 #endif 239 if (vn.v_flag & VONWORKLST) 240 printf(" VONWORKLST"); 241 if (vn.v_flag & VMOUNT) 242 printf(" VMOUNT"); 243 if (vn.v_flag & VOBJDIRTY) 244 printf(" VOBJDIRTY"); 245 246 printf("\n"); 247 248 if (vn.v_lock.lk_sharecount || vn.v_lock.lk_waitcount || 249 vn.v_lock.lk_exclusivecount || vn.v_lock.lk_lockholder != LK_NOTHREAD) { 250 printf("\tlk_flags %08x share %d wait %d excl %d holder = %p\n", 251 vn.v_lock.lk_flags, vn.v_lock.lk_sharecount, 252 vn.v_lock.lk_waitcount, vn.v_lock.lk_exclusivecount, 253 vn.v_lock.lk_lockholder); 254 } 255 256 if (whichlist) 257 return(vn.v_nmntvnodes.tqe_next); 258 else 259 return(vn.v_freelist.tqe_next); 260 } 261 262 static 263 int 264 getobjpages(kvm_t *kd, struct vm_object *obj) 265 { 266 struct vm_object vmobj; 267 268 kkread(kd, (u_long)obj, &vmobj, sizeof(vmobj)); 269 return(vmobj.resident_page_count); 270 } 271 272 static 273 int 274 getobjvnpsize(kvm_t *kd, struct vm_object *obj) 275 { 276 struct vm_object vmobj; 277 278 kkread(kd, (u_long)obj, &vmobj, sizeof(vmobj)); 279 return(vmobj.un_pager.vnp.vnp_size); 280 } 281 282 static void 283 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) 284 { 285 if (kvm_read(kd, addr, buf, nbytes) != nbytes) { 286 perror("kvm_read"); 287 exit(1); 288 } 289 } 290 291