1 /* 2 * Copyright (c) 2008 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/sbin/hammer/cmd_show.c,v 1.6 2008/02/23 03:01:06 dillon Exp $ 35 */ 36 37 #include "hammer.h" 38 39 #define FLAG_TOOFARLEFT 0x0001 40 #define FLAG_TOOFARRIGHT 0x0002 41 #define FLAG_BADTYPE 0x0004 42 43 static void print_btree_node(hammer_off_t node_offset, int depth, int spike, 44 hammer_base_elm_t left_bound, 45 hammer_base_elm_t right_bound); 46 static void print_btree_elm(hammer_btree_elm_t elm, int i, u_int8_t type, 47 int flags, const char *label); 48 static int print_elm_flags(hammer_node_ondisk_t node, hammer_btree_elm_t elm, 49 u_int8_t btype, hammer_base_elm_t left_bound, 50 hammer_base_elm_t right_bound); 51 static void print_bigblock_fill(hammer_off_t offset); 52 53 void 54 hammer_cmd_show(hammer_off_t node_offset, int depth, 55 hammer_base_elm_t left_bound, hammer_base_elm_t right_bound) 56 { 57 struct volume_info *volume; 58 59 if (node_offset == (hammer_off_t)-1) { 60 volume = get_volume(RootVolNo); 61 node_offset = volume->ondisk->vol0_btree_root; 62 if (VerboseOpt) { 63 printf("\trecords=%lld\n", 64 volume->ondisk->vol0_stat_records); 65 } 66 rel_volume(volume); 67 } 68 printf("show %016llx depth %d\n", node_offset, depth); 69 print_btree_node(node_offset, depth, 0, left_bound, right_bound); 70 print_btree_node(node_offset, depth, 1, left_bound, right_bound); 71 } 72 73 static void 74 print_btree_node(hammer_off_t node_offset, int depth, int spike, 75 hammer_base_elm_t left_bound, hammer_base_elm_t right_bound) 76 { 77 struct buffer_info *buffer = NULL; 78 hammer_node_ondisk_t node; 79 hammer_btree_elm_t elm; 80 int i; 81 int flags; 82 83 node = get_node(node_offset, &buffer); 84 85 if (spike == 0) { 86 printf(" NODE %016llx count=%d parent=%016llx " 87 "type=%c depth=%d fill=", 88 node_offset, node->count, node->parent, 89 (node->type ? node->type : '?'), depth); 90 if (VerboseOpt) 91 print_bigblock_fill(node_offset); 92 printf(" {\n"); 93 94 for (i = 0; i < node->count; ++i) { 95 elm = &node->elms[i]; 96 flags = print_elm_flags(node, elm, elm->base.btype, 97 left_bound, right_bound); 98 print_btree_elm(elm, i, node->type, flags, "ELM"); 99 } 100 if (node->type == HAMMER_BTREE_TYPE_INTERNAL) { 101 elm = &node->elms[i]; 102 flags = print_elm_flags(node, elm, 'I', 103 left_bound, right_bound); 104 print_btree_elm(elm, i, node->type, flags, "RBN"); 105 } 106 printf(" }\n"); 107 } 108 109 for (i = 0; i < node->count; ++i) { 110 elm = &node->elms[i]; 111 112 switch(node->type) { 113 case HAMMER_BTREE_TYPE_INTERNAL: 114 if (elm->internal.subtree_offset) { 115 print_btree_node(elm->internal.subtree_offset, 116 depth + 1, spike, 117 &elm[0].base, &elm[1].base); 118 } 119 break; 120 default: 121 break; 122 } 123 } 124 rel_buffer(buffer); 125 } 126 127 static 128 void 129 print_btree_elm(hammer_btree_elm_t elm, int i, u_int8_t type, 130 int flags, const char *label) 131 { 132 char flagstr[8] = { 0, '-', '-', '-', '-', '-', '-', 0 }; 133 134 flagstr[0] = flags ? 'B' : 'G'; 135 if (flags & FLAG_TOOFARLEFT) 136 flagstr[2] = 'L'; 137 if (flags & FLAG_TOOFARRIGHT) 138 flagstr[3] = 'R'; 139 if (flags & FLAG_BADTYPE) 140 flagstr[4] = 'T'; 141 142 printf("%s\t%s %2d %c ", 143 flagstr, label, i, 144 (elm->base.btype ? elm->base.btype : '?')); 145 printf("obj=%016llx key=%016llx rt=%02x ot=%02x\n", 146 elm->base.obj_id, 147 elm->base.key, 148 elm->base.rec_type, 149 elm->base.obj_type); 150 printf("\t tids %016llx:%016llx ", 151 elm->base.create_tid, 152 elm->base.delete_tid); 153 154 switch(type) { 155 case HAMMER_BTREE_TYPE_INTERNAL: 156 printf("suboff=%016llx", elm->internal.subtree_offset); 157 break; 158 case HAMMER_BTREE_TYPE_LEAF: 159 switch(elm->base.btype) { 160 case HAMMER_BTREE_TYPE_RECORD: 161 printf("\n\t "); 162 printf("recoff=%016llx", elm->leaf.rec_offset); 163 printf(" dataoff=%016llx/%d", 164 elm->leaf.data_offset, elm->leaf.data_len); 165 if (VerboseOpt) { 166 printf("\n\t fills="); 167 print_bigblock_fill(elm->leaf.rec_offset); 168 printf(", "); 169 print_bigblock_fill(elm->leaf.data_offset); 170 } 171 break; 172 } 173 break; 174 default: 175 break; 176 } 177 printf("\n"); 178 } 179 180 static 181 int 182 print_elm_flags(hammer_node_ondisk_t node, hammer_btree_elm_t elm, 183 u_int8_t btype, 184 hammer_base_elm_t left_bound, hammer_base_elm_t right_bound) 185 { 186 int flags = 0; 187 188 switch(node->type) { 189 case HAMMER_BTREE_TYPE_INTERNAL: 190 switch(btype) { 191 case HAMMER_BTREE_TYPE_INTERNAL: 192 if (left_bound == NULL || right_bound == NULL) 193 break; 194 if (hammer_btree_cmp(&elm->base, left_bound) < 0) 195 flags |= FLAG_TOOFARLEFT; 196 if (hammer_btree_cmp(&elm->base, right_bound) > 0) 197 flags |= FLAG_TOOFARRIGHT; 198 break; 199 case HAMMER_BTREE_TYPE_LEAF: 200 if (left_bound == NULL || right_bound == NULL) 201 break; 202 if (hammer_btree_cmp(&elm->base, left_bound) < 0) 203 flags |= FLAG_TOOFARLEFT; 204 if (hammer_btree_cmp(&elm->base, right_bound) >= 0) 205 flags |= FLAG_TOOFARRIGHT; 206 break; 207 default: 208 flags |= FLAG_BADTYPE; 209 break; 210 } 211 break; 212 case HAMMER_BTREE_TYPE_LEAF: 213 switch(btype) { 214 case HAMMER_BTREE_TYPE_RECORD: 215 if (left_bound == NULL || right_bound == NULL) 216 break; 217 if (hammer_btree_cmp(&elm->base, left_bound) < 0) 218 flags |= FLAG_TOOFARLEFT; 219 if (hammer_btree_cmp(&elm->base, right_bound) >= 0) 220 flags |= FLAG_TOOFARRIGHT; 221 break; 222 default: 223 flags |= FLAG_BADTYPE; 224 break; 225 } 226 break; 227 default: 228 flags |= FLAG_BADTYPE; 229 break; 230 } 231 return(flags); 232 } 233 234 static 235 void 236 print_bigblock_fill(hammer_off_t offset) 237 { 238 struct hammer_blockmap_layer1 layer1; 239 struct hammer_blockmap_layer2 layer2; 240 int fill; 241 242 blockmap_lookup(offset, &layer1, &layer2); 243 fill = layer2.bytes_free * 100 / HAMMER_LARGEBLOCK_SIZE; 244 fill = 100 - fill; 245 246 printf("z%d:%lld=%d%%", 247 HAMMER_ZONE_DECODE(offset), 248 (offset & ~HAMMER_OFF_ZONE_MASK) / HAMMER_LARGEBLOCK_SIZE, 249 fill 250 ); 251 } 252 253