From fa12c6260b7f066f933c85d72be95bbb048c4518 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 7 Oct 2004 00:05:03 +0000 Subject: [PATCH 1/1] Add vnodeinfo - a program which scans each mount's vnode list and dumps mount and vnode information, plus scans the vnode_free_list and dumps it as well. Give ncptrace the ability to specify a kernel and core file. --- test/debug/ncptrace.c | 22 ++++- test/debug/vnodeinfo.c | 213 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 test/debug/vnodeinfo.c diff --git a/test/debug/ncptrace.c b/test/debug/ncptrace.c index caf569b97f..4d4577f8de 100644 --- a/test/debug/ncptrace.c +++ b/test/debug/ncptrace.c @@ -9,7 +9,7 @@ * Trace and dump the kernel namecache hierarchy. If a path is specified * the trace begins there, otherwise the trace begins at the root. * - * $DragonFly: src/test/debug/ncptrace.c,v 1.2 2004/10/06 05:13:20 dillon Exp $ + * $DragonFly: src/test/debug/ncptrace.c,v 1.3 2004/10/07 00:05:03 dillon Exp $ */ #define _KERNEL_STRUCTURES_ @@ -32,6 +32,7 @@ #include #include #include +#include struct nlist Nl[] = { #ifdef CINV_PARENT @@ -49,9 +50,26 @@ main(int ac, char **av) { struct namecache *ncptr; kvm_t *kd; + const char *corefile = NULL; + const char *sysfile = NULL; + int ch; int i; - if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm:")) == NULL) { + while ((ch = getopt(ac, av, "M:N:")) != -1) { + switch(ch) { + case 'M': + corefile = optarg; + break; + case 'N': + sysfile = optarg; + break; + default: + fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); + exit(1); + } + } + + if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { perror("kvm_open"); exit(1); } diff --git a/test/debug/vnodeinfo.c b/test/debug/vnodeinfo.c new file mode 100644 index 0000000000..39917b7f14 --- /dev/null +++ b/test/debug/vnodeinfo.c @@ -0,0 +1,213 @@ +/* + * VNODEINFO.C + * + * cc -I/usr/src/sys vnodeinfo.c -o /usr/local/bin/vnodeinfo -lkvm + * + * vnodeinfo + * + * Dump the mountlist and related vnodes. + * + * $DragonFly: src/test/debug/vnodeinfo.c,v 1.1 2004/10/07 00:05:03 dillon Exp $ + */ + +#define _KERNEL_STRUCTURES_ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +struct nlist Nl[] = { + { "_mountlist" }, + { "_vnode_free_list" }, + { NULL } +}; + +static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes); +static struct mount *dumpmount(kvm_t *kd, struct mount *mp); +static struct vnode *dumpvp(kvm_t *kd, struct vnode *vp, int whichlist); + +main(int ac, char **av) +{ + struct mount *mp; + struct vnode *vp; + kvm_t *kd; + int i; + int ch; + const char *corefile = NULL; + const char *sysfile = NULL; + + while ((ch = getopt(ac, av, "M:N:")) != -1) { + switch(ch) { + case 'M': + corefile = optarg; + break; + case 'N': + sysfile = optarg; + break; + default: + fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); + exit(1); + } + } + + if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { + perror("kvm_open"); + exit(1); + } + if (kvm_nlist(kd, Nl) != 0) { + perror("kvm_nlist"); + exit(1); + } + kkread(kd, Nl[0].n_value, &mp, sizeof(mp)); + while (mp) + mp = dumpmount(kd, mp); + kkread(kd, Nl[1].n_value, &vp, sizeof(vp)); + printf("VNODEFREELIST {\n"); + while (vp) + vp = dumpvp(kd, vp, 0); + printf("}\n"); + return(0); +} + +static struct mount * +dumpmount(kvm_t *kd, struct mount *mp) +{ + struct mount mnt; + struct vnode *vp; + + kkread(kd, (u_long)mp, &mnt, sizeof(mnt)); + printf("MOUNTPOINT %s on %s {\n", + mnt.mnt_stat.f_mntfromname, mnt.mnt_stat.f_mntonname); + printf(" lk_flags %08x share %d wait %d excl %d holder = %p\n", + mnt.mnt_lock.lk_flags, mnt.mnt_lock.lk_sharecount, + mnt.mnt_lock.lk_waitcount, mnt.mnt_lock.lk_exclusivecount, + mnt.mnt_lock.lk_lockholder); + printf(" mnt_flag %08x mnt_kern_flag %08x\n", + mnt.mnt_flag, mnt.mnt_kern_flag); + printf(" mnt_nvnodelistsize %d\n", mnt.mnt_nvnodelistsize); + vp = mnt.mnt_nvnodelist.tqh_first; + while (vp) + vp = dumpvp(kd, vp, 1); + + printf("}\n"); + + return(mnt.mnt_list.tqe_next); +} + +static const char * +vtype(enum vtype type) +{ + static char buf[32]; + + switch(type) { + case VNON: + return("VNON"); + case VREG: + return("VREG"); + case VDIR: + return("VDIR"); + case VBLK: + return("VBLK"); + case VCHR: + return("VCHR"); + case VLNK: + return("VLNK"); + case VSOCK: + return("VSOCK"); + case VFIFO: + return("VFIFO"); + case VBAD: + return("VBAD"); + default: + break; + } + snprintf(buf, sizeof(buf), "%d", (int)type); + return(buf); +} + +static struct vnode * +dumpvp(kvm_t *kd, struct vnode *vp, int whichlist) +{ + struct vnode vn; + + kkread(kd, (u_long)vp, &vn, sizeof(vn)); + + printf(" vnode %p usecnt %d holdcnt %d type=%s flags %08x", + vp, vn.v_usecount, vn.v_holdcnt, vtype(vn.v_type), vn.v_flag); + if (vn.v_flag & VROOT) + printf(" ROOT"); + if (vn.v_flag & VTEXT) + printf(" TEXT"); + if (vn.v_flag & VSYSTEM) + printf(" SYSTEM"); + if (vn.v_flag & VISTTY) + printf(" ISTTY"); + if (vn.v_flag & VXLOCK) + printf(" XLOCK"); + if (vn.v_flag & VXWANT) + printf(" XWANT"); + if (vn.v_flag & VBWAIT) + printf(" BWAIT"); + if (vn.v_flag & VOBJBUF) + printf(" OBJBUF"); + if (vn.v_flag & VAGE) + printf(" AGE"); + if (vn.v_flag & VOLOCK) + printf(" OLOCK"); + if (vn.v_flag & VOWANT) + printf(" OWANT"); + if (vn.v_flag & VDOOMED) + printf(" DOOMED"); + if (vn.v_flag & VFREE) + printf(" FREE"); + if (vn.v_flag & VINFREE) + printf(" INFREE"); + if (vn.v_flag & VONWORKLST) + printf(" ONWORKLST"); + if (vn.v_flag & VMOUNT) + printf(" MOUNT"); + if (vn.v_flag & VOBJDIRTY) + printf(" OBJDIRTY"); + if (vn.v_flag & VPLACEMARKER) + printf(" PLACEMARKER"); + printf("\n"); + + if (vn.v_lock.lk_sharecount || vn.v_lock.lk_waitcount || + vn.v_lock.lk_exclusivecount || vn.v_lock.lk_lockholder != LK_NOTHREAD) { + printf("\tlk_flags %08x share %d wait %d excl %d holder = %p\n", + vn.v_lock.lk_flags, vn.v_lock.lk_sharecount, + vn.v_lock.lk_waitcount, vn.v_lock.lk_exclusivecount, + vn.v_lock.lk_lockholder); + } + + if (whichlist) + return(vn.v_nmntvnodes.tqe_next); + else + return(vn.v_freelist.tqe_next); +} + +void +kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) +{ + if (kvm_read(kd, addr, buf, nbytes) != nbytes) { + perror("kvm_read"); + exit(1); + } +} + -- 2.41.0