1 /* 2 * H2CHAINS.C 3 * 4 * cc -I/usr/src/sys h2chains.c -o ~/bin/h2chains -lkvm 5 * 6 * h2chains <hmpaddr> 7 * 8 * Copyright (c) 2017 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 h2chainscan(kvm_t *kd, int tab, uintptr_t cp, 57 uintptr_t pcp, int pflags); 58 static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes); 59 60 #if 0 61 struct nlist Nl[] = { 62 { "_rootnch" }, 63 { "_mountlist" }, 64 { NULL } 65 }; 66 #endif 67 68 int 69 main(int ac, char **av) 70 { 71 kvm_t *kd; 72 const char *corefile = NULL; 73 const char *sysfile = NULL; 74 hammer2_dev_t hmp; 75 uintptr_t base; 76 uintptr_t cp; 77 int ch; 78 79 while ((ch = getopt(ac, av, "M:N:")) != -1) { 80 switch(ch) { 81 case 'M': 82 corefile = optarg; 83 break; 84 case 'N': 85 sysfile = optarg; 86 break; 87 default: 88 fprintf(stderr, "%s [-M core] [-N system]\n", av[0]); 89 exit(1); 90 } 91 } 92 ac -= optind; 93 av += optind; 94 95 if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) { 96 perror("kvm_open"); 97 exit(1); 98 } 99 #if 0 100 if (kvm_nlist(kd, Nl) != 0) { 101 perror("kvm_nlist"); 102 exit(1); 103 } 104 kkread(kd, Nl[0].n_value, &nch, sizeof(nch)); 105 kkread(kd, Nl[1].n_value, &list, sizeof(list)); 106 #endif 107 108 base = strtoul(av[0], NULL, 0); 109 110 kkread(kd, base, &hmp, sizeof(hmp)); 111 cp = (uintptr_t)hmp.vchain.core.rbtree.rbh_root; 112 printf("VCHAIN %08x\n", hmp.vchain.flags); 113 if (cp) 114 h2chainscan(kd, 4, cp, 115 base + offsetof(struct hammer2_dev, vchain), 116 hmp.vchain.flags); 117 printf("\n"); 118 119 cp = (uintptr_t)hmp.fchain.core.rbtree.rbh_root; 120 printf("FCHAIN %08x\n", hmp.fchain.flags); 121 if (cp) 122 h2chainscan(kd, 4, cp, 123 base + offsetof(struct hammer2_dev, fchain), 124 hmp.fchain.flags); 125 126 return 0; 127 } 128 129 static 130 void 131 h2chainscan(kvm_t *kd, int tab, uintptr_t cp, uintptr_t pcp, int pflags) 132 { 133 hammer2_chain_t chain; 134 135 kkread(kd, cp, &chain, sizeof(chain)); 136 if (chain.rbnode.rbe_left) 137 h2chainscan(kd, tab, (uintptr_t)chain.rbnode.rbe_left, 138 pcp, pflags); 139 140 printf("%*.*s chain %p type %02x lock %p dio %p " 141 "off/pbase=%016jx/%016jx flags %08x ", 142 tab, tab, "", 143 (void *)cp, chain.bref.type, chain.lock.mtx_owner, chain.dio, 144 chain.bref.data_off & ~(hammer2_off_t)0x0F, 145 chain.bref.data_off & ~(hammer2_off_t)65535, 146 chain.flags); 147 if (chain.flags & HAMMER2_CHAIN_ONFLUSH) 148 printf("F"); 149 if (chain.flags & HAMMER2_CHAIN_MODIFIED) 150 printf("M"); 151 if (chain.flags & (HAMMER2_CHAIN_ONFLUSH|HAMMER2_CHAIN_MODIFIED)) { 152 if ((pflags & HAMMER2_CHAIN_ONFLUSH) == 0) 153 printf(" FAIL"); 154 } 155 if ((uintptr_t)chain.parent != pcp) 156 printf(" FAIL2"); 157 printf("\n"); 158 if (chain.core.rbtree.rbh_root) 159 h2chainscan(kd, tab + 4, 160 (uintptr_t)chain.core.rbtree.rbh_root, 161 cp, chain.flags); 162 163 if (chain.rbnode.rbe_right) 164 h2chainscan(kd, tab, (uintptr_t)chain.rbnode.rbe_right, 165 pcp, pflags); 166 167 } 168 169 static void 170 kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes) 171 { 172 if (kvm_read(kd, addr, buf, nbytes) != nbytes) { 173 perror("kvm_read"); 174 exit(1); 175 } 176 } 177