Add a debugging utility which dumps that kernel's namecache topology.
authorMatthew Dillon <dillon@dragonflybsd.org>
Sun, 3 Oct 2004 06:12:34 +0000 (06:12 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sun, 3 Oct 2004 06:12:34 +0000 (06:12 +0000)
test/debug/ncptrace.c [new file with mode: 0644]

diff --git a/test/debug/ncptrace.c b/test/debug/ncptrace.c
new file mode 100644 (file)
index 0000000..06e4712
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * NCPTRACE.C
+ *
+ * cc -I/usr/src/sys ncptrace.c -o /usr/local/bin/ncptrace -lkvm
+ *
+ * ncptrace
+ * ncptrace [path]
+ *
+ * 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.1 2004/10/03 06:12:34 dillon Exp $
+ */
+
+#define _KERNEL_STRUCTURES_
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/malloc.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
+#include <sys/namecache.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_kern.h>
+#include <vm/swap_pager.h>
+#include <vm/vnode_pager.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <nlist.h>
+
+struct nlist Nl[] = {
+    { "_rootncp" },
+    { NULL }
+};
+
+void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
+void dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path);
+
+main(int ac, char **av)
+{
+    struct namecache *ncptr;
+    kvm_t *kd;
+    int i;
+
+    if ((kd = kvm_open(NULL, NULL, 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, &ncptr, sizeof(ncptr));
+    if (ac == 1) {
+       dumpncp(kd, 0, ncptr, NULL);
+    } else {
+       for (i = 1; i < ac; ++i) {
+           if (av[i][0] != '/')
+               fprintf(stderr, "%s: path must start at the root\n", av[i]);
+           dumpncp(kd, 0, ncptr, av[i]);
+       }
+    }
+}
+
+void
+dumpncp(kvm_t *kd, int tab, struct namecache *ncptr, const char *path)
+{
+    struct namecache ncp;
+    struct namecache *ncscan;
+    const char *ptr;
+    int haschildren;
+    char name[256];
+
+    kkread(kd, (u_long)ncptr, &ncp, sizeof(ncp));
+    if (ncp.nc_nlen < sizeof(name)) {
+       kkread(kd, (u_long)ncp.nc_name, name, ncp.nc_nlen);
+       name[ncp.nc_nlen] = 0;
+    } else {
+       name[0] = 0;
+    }
+    if (tab == 0) {
+       strcpy(name, "ROOT");
+       if (path)
+           ++path;
+    } else if (ncp.nc_flag & NCF_MOUNTPT) {
+       strcpy(name, "MOUNTGLUE");
+    } else if (name[0] == 0) {
+       strcpy(name, "?");
+       if (path)
+           return;
+    } else if (path) {
+       if ((ptr = strchr(path, '/')) == NULL)
+           ptr = path + strlen(path);
+       if (strlen(name) != ptr - path ||
+           bcmp(name, path, ptr - path) != 0
+       ) {
+           return;
+       }
+       path = ptr;
+       if (*path == '/')
+           ++path;
+       if (*path == 0)
+           path = NULL;
+    }
+
+    if (ncp.nc_list.tqh_first)
+       haschildren = 1;
+    else
+       haschildren = 0;
+
+    if (path) {
+       printf("ELM [ncp=%p par=%p %04x vp=%p] %s\n", 
+               ncptr, ncp.nc_parent, ncp.nc_flag, 
+               ncp.nc_vp, name);
+    } else {
+       printf("%*.*s%s [ncp=%p par=%p %04x vp=%p]%s\n", tab, tab, "", name, 
+               ncptr, ncp.nc_parent, ncp.nc_flag, ncp.nc_vp,
+               haschildren ? " {" : "");
+    }
+    for (ncscan = ncp.nc_list.tqh_first; ncscan; ncscan = ncp.nc_entry.tqe_next) {
+       kkread(kd, (u_long)ncscan, &ncp, sizeof(ncp));
+       dumpncp(kd, (path ? (tab ? tab : 4) : tab + 4), ncscan, path);
+    }
+    if (haschildren && path == NULL)
+       printf("%*.*s}\n", tab, tab, "");
+}
+
+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);
+    }
+}
+