1 /* 2 * H2INODES.C 3 * 4 * cc -I/usr/src/sys h2inodes.c -o ~/bin/h2inodes -lkvm 5 * 6 * h2inodes <pfsaddr> 7 * 8 * Copyright (c) 2018 The DragonFly Project. All rights reserved. 9 * 10 * This code is derived from software contributed to The DragonFly Project 11 * by Matthew Dillon <dillon@backplane.com> 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in 21 * the documentation and/or other materials provided with the 22 * distribution. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #include <sys/types.h> 39 #include <sys/user.h> 40 #include <vfs/hammer2/hammer2.h> 41 42 #include <vm/vm.h> 43 #include <vm/vm_page.h> 44 #include <vm/vm_kern.h> 45 #include <vm/swap_pager.h> 46 #include <vm/vnode_pager.h> 47 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <fcntl.h> 52 #include <kvm.h> 53 #include <nlist.h> 54 #include <getopt.h> 55 56 static void h2inumscan(kvm_t *kd, int tab, uintptr_t cp); 57 static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes); 58 59 #if 0 60 struct nlist Nl[] = { 61 { "_rootnch" }, 62 { "_mountlist" }, 63 { NULL } 64 }; 65 #endif 66 67 int 68 main(int ac, char **av) 69 { 70 kvm_t *kd; 71 const char *corefile = NULL; 72 const char *sysfile = NULL; 73 hammer2_pfs_t pmp; 74 uintptr_t base; 75 uintptr_t cp; 76 int ch; 77 78 while ((ch = getopt(ac, av, "M:N:")) != -1) { 79 switch(ch) { 80 case 'M': 81 corefile = optarg; 82 break; 83 case 'N': 84 sysfile = optarg; 85 break; 86 default: 87 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); 88 exit(1); 89 } 90 } 91 ac -= optind; 92 av += optind; 93 94 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { 95 perror("kvm_open"); 96 exit(1); 97 } 98 #if 0 99 if (kvm_nlist(kd, Nl) != 0) { 100 perror("kvm_nlist"); 101 exit(1); 102 } 103 kkread(kd, Nl[0].n_value, &nch, sizeof(nch)); 104 kkread(kd, Nl[1].n_value, &list, sizeof(list)); 105 #endif 106 107 base = strtoul(av[0], NULL, 0); 108 109 kkread(kd, base, &pmp, sizeof(pmp)); 110 cp = (uintptr_t)pmp.inum_tree.rbh_root; 111 if (cp) 112 h2inumscan(kd, 4, cp); 113 printf("\n"); 114 return 0; 115 } 116 117 static 118 void 119 h2inumscan(kvm_t *kd, int tab, uintptr_t cp) 120 { 121 hammer2_inode_t ip; 122 123 kkread(kd, cp, &ip, sizeof(ip)); 124 if (ip.rbnode.rbe_left) 125 h2inumscan(kd, tab, (uintptr_t)ip.rbnode.rbe_left); 126 printf("%*.*s ip %p inum=%ld refs=%08x " 127 "flags=%08x chain0=%p vp=%p\n", 128 tab, tab, "", (void *)cp, ip.meta.inum, ip.refs, 129 ip.flags, ip.cluster.array[0].chain, ip.vp); 130 if (ip.rbnode.rbe_right) 131 h2inumscan(kd, tab, (uintptr_t)ip.rbnode.rbe_right); 132 } 133 134 static void 135 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) 136 { 137 if (kvm_read(kd, addr, buf, nbytes) != nbytes) { 138 perror("kvm_read"); 139 exit(1); 140 } 141 } 142