xref: /haiku/src/add-ons/kernel/file_systems/bfs/Debug.cpp (revision 5cf0a92ad65e29e7c28b460a2802aecc3d421716)
1 /* Debug - debug stuff
2  *
3  * Copyright 2001-2004, Axel Dörfler, axeld@pinc-software.de.
4  * Some code is based on work previously done by Marcus Overhagen.
5  *
6  * This file may be used under the terms of the MIT License.
7  */
8 
9 
10 #include "Debug.h"
11 #include "BPlusTree.h"
12 #include "Inode.h"
13 
14 #include <KernelExport.h>
15 
16 #include <time.h>
17 
18 #define Print __out
19 
20 
21 char *
22 get_tupel(uint32 id)
23 {
24 	static unsigned char tupel[5];
25 
26 	tupel[0] = 0xff & (id >> 24);
27 	tupel[1] = 0xff & (id >> 16);
28 	tupel[2] = 0xff & (id >> 8);
29 	tupel[3] = 0xff & (id);
30 	tupel[4] = 0;
31 	for (int16 i = 0;i < 4;i++) {
32 		if (tupel[i] < ' ' || tupel[i] > 128)
33 			tupel[i] = '.';
34 	}
35 
36 	return (char *)tupel;
37 }
38 
39 
40 void
41 dump_block_run(const char *prefix, const block_run &run)
42 {
43 	Print("%s(%ld, %d, %d)\n", prefix, run.allocation_group, run.start, run.length);
44 }
45 
46 
47 void
48 dump_inode(Inode &inode)
49 {
50 	Print("Inode (%p) {\n", &inode);
51 	Print("\tfVolume = %p\n", inode.fVolume);
52 	Print("\tfBlockNumber = 0x%16Lx\n", inode.BlockNumber());
53 	Print("\tfTree = %p\n", inode.fTree);
54 	Print("\tfAttributes = %p\n", inode.fAttributes);
55 	Print("\tfOldSize = 0x%16Lx\n", inode.fOldSize);
56 	Print("\tfOldLastModified = 0x%16Lx\n", inode.fOldLastModified);
57 	Print("}\n");
58 }
59 
60 
61 void
62 dump_super_block(const disk_super_block *superBlock)
63 {
64 	Print("disk_super_block:\n");
65 	Print("  name           = %s\n", superBlock->name);
66 	Print("  magic1         = %#08lx (%s) %s\n", superBlock->magic1, get_tupel(superBlock->magic1), (superBlock->magic1 == SUPER_BLOCK_MAGIC1 ? "valid" : "INVALID"));
67 	Print("  fs_byte_order  = %#08lx (%s)\n", superBlock->fs_byte_order, get_tupel(superBlock->fs_byte_order));
68 	Print("  block_size     = %lu\n", superBlock->block_size);
69 	Print("  block_shift    = %lu\n", superBlock->block_shift);
70 	Print("  num_blocks     = %Lu\n", superBlock->num_blocks);
71 	Print("  used_blocks    = %Lu\n", superBlock->used_blocks);
72 	Print("  inode_size     = %lu\n", superBlock->inode_size);
73 	Print("  magic2         = %#08lx (%s) %s\n", superBlock->magic2, get_tupel(superBlock->magic2), (superBlock->magic2 == (int)SUPER_BLOCK_MAGIC2 ? "valid" : "INVALID"));
74 	Print("  blocks_per_ag  = %lu\n", superBlock->blocks_per_ag);
75 	Print("  ag_shift       = %lu (%ld bytes)\n", superBlock->ag_shift, 1L << superBlock->ag_shift);
76 	Print("  num_ags        = %lu\n", superBlock->num_ags);
77 	Print("  flags          = %#08lx (%s)\n", superBlock->flags, get_tupel(superBlock->flags));
78 	dump_block_run("  log_blocks     = ", superBlock->log_blocks);
79 	Print("  log_start      = %Lu\n", superBlock->log_start);
80 	Print("  log_end        = %Lu\n", superBlock->log_end);
81 	Print("  magic3         = %#08lx (%s) %s\n", superBlock->magic3, get_tupel(superBlock->magic3), (superBlock->magic3 == SUPER_BLOCK_MAGIC3 ? "valid" : "INVALID"));
82 	dump_block_run("  root_dir       = ", superBlock->root_dir);
83 	dump_block_run("  indices        = ", superBlock->indices);
84 }
85 
86 
87 void
88 dump_data_stream(const data_stream *stream)
89 {
90 	Print("data_stream:\n");
91 	for (int i = 0; i < NUM_DIRECT_BLOCKS; i++) {
92 		if (!stream->direct[i].IsZero()) {
93 			Print("  direct[%02d]                = ",i);
94 			dump_block_run("",stream->direct[i]);
95 		}
96 	}
97 	Print("  max_direct_range          = %Lu\n", stream->max_direct_range);
98 
99 	if (!stream->indirect.IsZero())
100 		dump_block_run("  indirect                  = ", stream->indirect);
101 
102 	Print("  max_indirect_range        = %Lu\n", stream->max_indirect_range);
103 
104 	if (!stream->double_indirect.IsZero())
105 		dump_block_run("  double_indirect           = ", stream->double_indirect);
106 
107 	Print("  max_double_indirect_range = %Lu\n", stream->max_double_indirect_range);
108 	Print("  size                      = %Lu\n", stream->size);
109 }
110 
111 
112 void
113 dump_inode(const bfs_inode *inode)
114 {
115 	Print("inode:\n");
116 	Print("  magic1             = %08lx (%s) %s\n", inode->magic1,
117 		get_tupel(inode->magic1), (inode->magic1 == INODE_MAGIC1 ? "valid" : "INVALID"));
118 	dump_block_run(	"  inode_num          = ", inode->inode_num);
119 	Print("  uid                = %lu\n", inode->uid);
120 	Print("  gid                = %lu\n", inode->gid);
121 	Print("  mode               = %08lx\n", inode->mode);
122 	Print("  flags              = %08lx\n", inode->flags);
123 	Print("  create_time        = %Ld (%Ld)\n", inode->create_time,
124 		inode->create_time >> INODE_TIME_SHIFT);
125 	Print("  last_modified_time = %Ld (%Ld)\n", inode->last_modified_time,
126 		inode->last_modified_time >> INODE_TIME_SHIFT);
127 	dump_block_run(	"  parent             = ", inode->parent);
128 	dump_block_run(	"  attributes         = ", inode->attributes);
129 	Print("  type               = %lu\n", inode->type);
130 	Print("  inode_size         = %lu\n", inode->inode_size);
131 	Print("  etc                = %#08lx\n", inode->etc);
132 	Print("  short_symlink      = %s\n",
133 		S_ISLNK(inode->mode) && (inode->flags & INODE_LONG_SYMLINK) == 0 ?
134 			inode->short_symlink : "-");
135 	dump_data_stream(&(inode->data));
136 	Print("  --\n  pad[0]             = %08lx\n", inode->pad[0]);
137 	Print("  pad[1]             = %08lx\n", inode->pad[1]);
138 	Print("  pad[2]             = %08lx\n", inode->pad[2]);
139 	Print("  pad[3]             = %08lx\n", inode->pad[3]);
140 }
141 
142 
143 void
144 dump_bplustree_header(const bplustree_header *header)
145 {
146 	Print("bplustree_header:\n");
147 	Print("  magic                = %#08lx (%s) %s\n", header->magic,
148 		get_tupel(header->magic), (header->magic == BPLUSTREE_MAGIC ? "valid" : "INVALID"));
149 	Print("  node_size            = %lu\n", header->node_size);
150 	Print("  max_number_of_levels = %lu\n", header->max_number_of_levels);
151 	Print("  data_type            = %lu\n", header->data_type);
152 	Print("  root_node_pointer    = %Ld\n", header->root_node_pointer);
153 	Print("  free_node_pointer    = %Ld\n", header->free_node_pointer);
154 	Print("  maximum_size         = %Lu\n", header->maximum_size);
155 }
156 
157 
158 #define DUMPED_BLOCK_SIZE 16
159 
160 void
161 dump_block(const char *buffer,int size)
162 {
163 	for(int i = 0;i < size;) {
164 		int start = i;
165 
166 		for(;i < start+DUMPED_BLOCK_SIZE;i++) {
167 			if (!(i % 4))
168 				Print(" ");
169 
170 			if (i >= size)
171 				Print("  ");
172 			else
173 				Print("%02x",*(unsigned char *)(buffer+i));
174 		}
175 		Print("  ");
176 
177 		for(i = start;i < start + DUMPED_BLOCK_SIZE;i++) {
178 			if (i < size) {
179 				char c = *(buffer+i);
180 
181 				if (c < 30)
182 					Print(".");
183 				else
184 					Print("%c",c);
185 			} else
186 				break;
187 		}
188 		Print("\n");
189 	}
190 }
191 
192 
193 void
194 dump_bplustree_node(const bplustree_node *node, const bplustree_header *header,
195 	Volume *volume)
196 {
197 	Print("bplustree_node:\n");
198 	Print("  left_link      = %Ld\n", node->left_link);
199 	Print("  right_link     = %Ld\n", node->right_link);
200 	Print("  overflow_link  = %Ld\n", node->overflow_link);
201 	Print("  all_key_count  = %u\n", node->all_key_count);
202 	Print("  all_key_length = %u\n", node->all_key_length);
203 
204 	if (header == NULL)
205 		return;
206 
207 	if (node->all_key_count > node->all_key_length
208 		|| uint32(node->all_key_count * 10) > (uint32)header->node_size
209 		|| node->all_key_count == 0) {
210 		Print("\n");
211 		dump_block((char *)node, header->node_size/*, sizeof(off_t)*/);
212 		return;
213 	}
214 
215 	Print("\n");
216 	for (int32 i = 0;i < node->all_key_count;i++) {
217 		uint16 length;
218 		char buffer[256], *key = (char *)node->KeyAt(i, &length);
219 		if (length > 255 || length == 0) {
220 			Print("  %2ld. Invalid length (%u)!!\n", i, length);
221 			dump_block((char *)node, header->node_size/*, sizeof(off_t)*/);
222 			break;
223 		}
224 		memcpy(buffer, key, length);
225 		buffer[length] = '\0';
226 
227 		off_t *value = node->Values() + i;
228 		if ((uint32)value < (uint32)node || (uint32)value > (uint32)node + header->node_size)
229 			Print("  %2ld. Invalid Offset!!\n", i);
230 		else {
231 			Print("  %2ld. ", i);
232 			if (header->data_type == BPLUSTREE_STRING_TYPE)
233 				Print("\"%s\"", buffer);
234 			else if (header->data_type == BPLUSTREE_INT32_TYPE)
235 				Print("int32 = %ld (0x%lx)", *(int32 *)&buffer, *(int32 *)&buffer);
236 			else if (header->data_type == BPLUSTREE_UINT32_TYPE)
237 				Print("uint32 = %lu (0x%lx)", *(uint32 *)&buffer, *(uint32 *)&buffer);
238 			else if (header->data_type == BPLUSTREE_INT64_TYPE)
239 				Print("int64 = %Ld (0x%Lx)", *(int64 *)&buffer, *(int64 *)&buffer);
240 			else
241 				Print("???");
242 
243 			off_t offset = *value & 0x3fffffffffffffffLL;
244 			Print(" (%d bytes) -> %Ld", length, offset);
245 			if (volume != NULL) {
246 				block_run run = volume->ToBlockRun(offset);
247 				Print(" (%ld, %d)", run.allocation_group, run.start);
248 			}
249 			if (bplustree_node::LinkType(*value) == BPLUSTREE_DUPLICATE_FRAGMENT)
250 				Print(" (duplicate fragment %Ld)\n", *value & 0x3ff);
251 			else if (bplustree_node::LinkType(*value) == BPLUSTREE_DUPLICATE_NODE)
252 				Print(" (duplicate node)\n");
253 			else
254 				Print("\n");
255 		}
256 	}
257 }
258 
259 
260 //	#pragma mark -
261 
262 
263 #ifndef USER
264 
265 static int
266 dbg_inode(int argc, char **argv)
267 {
268 	if (argc < 2) {
269 		kprintf("usage: bfsinode ptr-to-inode\n");
270 		return 0;
271 	}
272 
273 	Inode *inode = (Inode *)parse_expression(argv[1]);
274 	dump_inode(*inode);
275 
276 	return B_OK;
277 }
278 
279 #endif
280 
281 void
282 remove_debugger_commands()
283 {
284 #ifndef USER
285 	remove_debugger_command("bfsinode", dbg_inode);
286 #endif
287 }
288 
289 
290 void
291 add_debugger_commands()
292 {
293 #ifndef USER
294 	add_debugger_command("bfsinode", dbg_inode, "dump an Inode object");
295 #endif
296 }
297 
298