xref: /openbmc/linux/fs/jffs2/debug.c (revision e0c8e42f)
1 /*
2  * JFFS2 -- Journalling Flash File System, Version 2.
3  *
4  * Copyright (C) 2001-2003 Red Hat, Inc.
5  *
6  * Created by David Woodhouse <dwmw2@infradead.org>
7  *
8  * For licensing information, see the file 'LICENCE' in this directory.
9  *
10  * $Id: debug.c,v 1.7 2005/07/24 15:14:14 dedekind Exp $
11  *
12  */
13 #include <linux/kernel.h>
14 #include <linux/pagemap.h>
15 #include <linux/crc32.h>
16 #include <linux/jffs2.h>
17 #include "nodelist.h"
18 #include "debug.h"
19 
20 #ifdef JFFS2_DBG_PARANOIA_CHECKS
21 /*
22  * Check the fragtree.
23  */
24 void
25 __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
26 {
27 	down(&f->sem);
28 	__jffs2_dbg_fragtree_paranoia_check_nolock(f);
29 	up(&f->sem);
30 }
31 
32 void
33 __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
34 {
35 	struct jffs2_node_frag *frag;
36 	int bitched = 0;
37 
38 	for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
39 		struct jffs2_full_dnode *fn = frag->node;
40 
41 		if (!fn || !fn->raw)
42 			continue;
43 
44 		if (ref_flags(fn->raw) == REF_PRISTINE) {
45 			if (fn->frags > 1) {
46 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
47 						ref_offset(fn->raw), fn->frags);
48 				bitched = 1;
49 			}
50 
51 			/* A hole node which isn't multi-page should be garbage-collected
52 			   and merged anyway, so we just check for the frag size here,
53 			   rather than mucking around with actually reading the node
54 			   and checking the compression type, which is the real way
55 			   to tell a hole node. */
56 			if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
57 					&& frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
58 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag "
59 						"in the same page. Tell dwmw2.\n", ref_offset(fn->raw));
60 				bitched = 1;
61 			}
62 
63 			if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
64 					&& frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
65 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
66 						"non-hole frag in the same page. Tell dwmw2.\n",
67 					       ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
68 				bitched = 1;
69 			}
70 		}
71 	}
72 
73 	if (bitched) {
74 		JFFS2_ERROR("fragtree is corrupted.\n");
75 		__jffs2_dbg_dump_fragtree_nolock(f);
76 		BUG();
77 	}
78 }
79 
80 /*
81  * Check if the flash contains all 0xFF before we start writing.
82  */
83 void
84 __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
85 				    uint32_t ofs, int len)
86 {
87 	size_t retlen;
88 	int ret, i;
89 	unsigned char *buf;
90 
91 	buf = kmalloc(len, GFP_KERNEL);
92 	if (!buf)
93 		return;
94 
95 	ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
96 	if (ret || (retlen != len)) {
97 		JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
98 				len, ret, retlen);
99 		kfree(buf);
100 		return;
101 	}
102 
103 	ret = 0;
104 	for (i = 0; i < len; i++)
105 		if (buf[i] != 0xff)
106 			ret = 1;
107 
108 	if (ret) {
109 		JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data "
110 			"already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i);
111 		__jffs2_dbg_dump_buffer(buf, len, ofs);
112 		kfree(buf);
113 		BUG();
114 	}
115 
116 	kfree(buf);
117 }
118 
119 /*
120  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
121  */
122 void
123 __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
124 				struct jffs2_eraseblock *jeb)
125 {
126 	spin_lock(&c->erase_completion_lock);
127 	__jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
128 	spin_unlock(&c->erase_completion_lock);
129 }
130 
131 void
132 __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
133 				       struct jffs2_eraseblock *jeb)
134 {
135 	uint32_t my_used_size = 0;
136 	uint32_t my_unchecked_size = 0;
137 	uint32_t my_dirty_size = 0;
138 	struct jffs2_raw_node_ref *ref2 = jeb->first_node;
139 
140 	while (ref2) {
141 		uint32_t totlen = ref_totlen(c, jeb, ref2);
142 
143 		if (ref2->flash_offset < jeb->offset ||
144 				ref2->flash_offset > jeb->offset + c->sector_size) {
145 			JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
146 				ref_offset(ref2), jeb->offset);
147 			goto error;
148 
149 		}
150 		if (ref_flags(ref2) == REF_UNCHECKED)
151 			my_unchecked_size += totlen;
152 		else if (!ref_obsolete(ref2))
153 			my_used_size += totlen;
154 		else
155 			my_dirty_size += totlen;
156 
157 		if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
158 			JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
159 				"last_node is at %#08x (mem %p).\n",
160 				ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
161 				ref_offset(jeb->last_node), jeb->last_node);
162 			goto error;
163 		}
164 		ref2 = ref2->next_phys;
165 	}
166 
167 	if (my_used_size != jeb->used_size) {
168 		JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
169 			my_used_size, jeb->used_size);
170 		goto error;
171 	}
172 
173 	if (my_unchecked_size != jeb->unchecked_size) {
174 		JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
175 			my_unchecked_size, jeb->unchecked_size);
176 		goto error;
177 	}
178 
179 #if 0
180 	/* This should work when we implement ref->__totlen elemination */
181 	if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
182 		JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
183 			my_dirty_size, jeb->dirty_size + jeb->wasted_size);
184 		goto error;
185 	}
186 
187 	if (jeb->free_size == 0
188 		&& my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
189 		JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
190 			my_used_size + my_unchecked_size + my_dirty_size,
191 			c->sector_size);
192 		goto error;
193 	}
194 #endif
195 
196 	return;
197 
198 error:
199 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
200 	__jffs2_dbg_dump_jeb_nolock(jeb);
201 	__jffs2_dbg_dump_block_lists_nolock(c);
202 	BUG();
203 
204 }
205 #endif /* JFFS2_DBG_PARANOIA_CHECKS */
206 
207 #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
208 /*
209  * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
210  */
211 void
212 __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
213 			   struct jffs2_eraseblock *jeb)
214 {
215 	spin_lock(&c->erase_completion_lock);
216 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
217 	spin_unlock(&c->erase_completion_lock);
218 }
219 
220 void
221 __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
222 				  struct jffs2_eraseblock *jeb)
223 {
224 	struct jffs2_raw_node_ref *ref;
225 	int i = 0;
226 
227 	JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset);
228 	if (!jeb->first_node) {
229 		JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset);
230 		return;
231 	}
232 
233 	printk(JFFS2_DBG_LVL);
234 	for (ref = jeb->first_node; ; ref = ref->next_phys) {
235 		printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
236 		if (ref->next_phys)
237 			printk("->");
238 		else
239 			break;
240 		if (++i == 4) {
241 			i = 0;
242 			printk("\n" JFFS2_DBG_LVL);
243 		}
244 	}
245 	printk("\n");
246 }
247 
248 /*
249  * Dump an eraseblock's space accounting.
250  */
251 void
252 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
253 {
254 	spin_lock(&c->erase_completion_lock);
255 	__jffs2_dbg_dump_jeb_nolock(jeb);
256 	spin_unlock(&c->erase_completion_lock);
257 }
258 
259 void
260 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
261 {
262 	if (!jeb)
263 		return;
264 
265 	JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n",
266 			jeb->offset);
267 
268 	printk(JFFS2_DBG_LVL "used_size: %#08x\n",	jeb->used_size);
269 	printk(JFFS2_DBG_LVL "dirty_size: %#08x\n",	jeb->dirty_size);
270 	printk(JFFS2_DBG_LVL "wasted_size: %#08x\n",	jeb->wasted_size);
271 	printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n",	jeb->unchecked_size);
272 	printk(JFFS2_DBG_LVL "free_size: %#08x\n",	jeb->free_size);
273 }
274 
275 void
276 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
277 {
278 	spin_lock(&c->erase_completion_lock);
279 	__jffs2_dbg_dump_block_lists_nolock(c);
280 	spin_unlock(&c->erase_completion_lock);
281 }
282 
283 void
284 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
285 {
286 	JFFS2_DEBUG("dump JFFS2 blocks lists:\n");
287 
288 	printk(JFFS2_DBG_LVL "flash_size: %#08x\n",	c->flash_size);
289 	printk(JFFS2_DBG_LVL "used_size: %#08x\n",	c->used_size);
290 	printk(JFFS2_DBG_LVL "dirty_size: %#08x\n",	c->dirty_size);
291 	printk(JFFS2_DBG_LVL "wasted_size: %#08x\n",	c->wasted_size);
292 	printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n",	c->unchecked_size);
293 	printk(JFFS2_DBG_LVL "free_size: %#08x\n",	c->free_size);
294 	printk(JFFS2_DBG_LVL "erasing_size: %#08x\n",	c->erasing_size);
295 	printk(JFFS2_DBG_LVL "bad_size: %#08x\n",	c->bad_size);
296 	printk(JFFS2_DBG_LVL "sector_size: %#08x\n",	c->sector_size);
297 	printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n",
298 				c->sector_size * c->resv_blocks_write);
299 
300 	if (c->nextblock)
301 		printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
302 			"unchecked %#08x, free %#08x)\n",
303 			c->nextblock->offset, c->nextblock->used_size,
304 			c->nextblock->dirty_size, c->nextblock->wasted_size,
305 			c->nextblock->unchecked_size, c->nextblock->free_size);
306 	else
307 		printk(JFFS2_DBG_LVL "nextblock: NULL\n");
308 
309 	if (c->gcblock)
310 		printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
311 			"unchecked %#08x, free %#08x)\n",
312 			c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
313 			c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
314 	else
315 		printk(JFFS2_DBG_LVL "gcblock: NULL\n");
316 
317 	if (list_empty(&c->clean_list)) {
318 		printk(JFFS2_DBG_LVL "clean_list: empty\n");
319 	} else {
320 		struct list_head *this;
321 		int numblocks = 0;
322 		uint32_t dirty = 0;
323 
324 		list_for_each(this, &c->clean_list) {
325 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
326 			numblocks ++;
327 			dirty += jeb->wasted_size;
328 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
329 				printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
330 					"unchecked %#08x, free %#08x)\n",
331 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
332 					jeb->unchecked_size, jeb->free_size);
333 			}
334 		}
335 
336 		printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
337 			numblocks, dirty, dirty / numblocks);
338 	}
339 
340 	if (list_empty(&c->very_dirty_list)) {
341 		printk(JFFS2_DBG_LVL "very_dirty_list: empty\n");
342 	} else {
343 		struct list_head *this;
344 		int numblocks = 0;
345 		uint32_t dirty = 0;
346 
347 		list_for_each(this, &c->very_dirty_list) {
348 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
349 
350 			numblocks ++;
351 			dirty += jeb->dirty_size;
352 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
353 				printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
354 					"unchecked %#08x, free %#08x)\n",
355 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
356 					jeb->unchecked_size, jeb->free_size);
357 			}
358 		}
359 
360 		printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
361 			numblocks, dirty, dirty / numblocks);
362 	}
363 
364 	if (list_empty(&c->dirty_list)) {
365 		printk(JFFS2_DBG_LVL "dirty_list: empty\n");
366 	} else {
367 		struct list_head *this;
368 		int numblocks = 0;
369 		uint32_t dirty = 0;
370 
371 		list_for_each(this, &c->dirty_list) {
372 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
373 
374 			numblocks ++;
375 			dirty += jeb->dirty_size;
376 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
377 				printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
378 					"unchecked %#08x, free %#08x)\n",
379 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
380 					jeb->unchecked_size, jeb->free_size);
381 			}
382 		}
383 
384 		printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n",
385 			numblocks, dirty, dirty / numblocks);
386 	}
387 
388 	if (list_empty(&c->erasable_list)) {
389 		printk(JFFS2_DBG_LVL "erasable_list: empty\n");
390 	} else {
391 		struct list_head *this;
392 
393 		list_for_each(this, &c->erasable_list) {
394 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
395 
396 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
397 				printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
398 					"unchecked %#08x, free %#08x)\n",
399 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
400 					jeb->unchecked_size, jeb->free_size);
401 			}
402 		}
403 	}
404 
405 	if (list_empty(&c->erasing_list)) {
406 		printk(JFFS2_DBG_LVL "erasing_list: empty\n");
407 	} else {
408 		struct list_head *this;
409 
410 		list_for_each(this, &c->erasing_list) {
411 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
412 
413 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
414 				printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
415 					"unchecked %#08x, free %#08x)\n",
416 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
417 					jeb->unchecked_size, jeb->free_size);
418 			}
419 		}
420 	}
421 
422 	if (list_empty(&c->erase_pending_list)) {
423 		printk(JFFS2_DBG_LVL "erase_pending_list: empty\n");
424 	} else {
425 		struct list_head *this;
426 
427 		list_for_each(this, &c->erase_pending_list) {
428 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
429 
430 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
431 				printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
432 					"unchecked %#08x, free %#08x)\n",
433 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
434 					jeb->unchecked_size, jeb->free_size);
435 			}
436 		}
437 	}
438 
439 	if (list_empty(&c->erasable_pending_wbuf_list)) {
440 		printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n");
441 	} else {
442 		struct list_head *this;
443 
444 		list_for_each(this, &c->erasable_pending_wbuf_list) {
445 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
446 
447 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
448 				printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
449 					"wasted %#08x, unchecked %#08x, free %#08x)\n",
450 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
451 					jeb->unchecked_size, jeb->free_size);
452 			}
453 		}
454 	}
455 
456 	if (list_empty(&c->free_list)) {
457 		printk(JFFS2_DBG_LVL "free_list: empty\n");
458 	} else {
459 		struct list_head *this;
460 
461 		list_for_each(this, &c->free_list) {
462 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
463 
464 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
465 				printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
466 					"unchecked %#08x, free %#08x)\n",
467 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
468 					jeb->unchecked_size, jeb->free_size);
469 			}
470 		}
471 	}
472 
473 	if (list_empty(&c->bad_list)) {
474 		printk(JFFS2_DBG_LVL "bad_list: empty\n");
475 	} else {
476 		struct list_head *this;
477 
478 		list_for_each(this, &c->bad_list) {
479 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
480 
481 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
482 				printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
483 					"unchecked %#08x, free %#08x)\n",
484 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
485 					jeb->unchecked_size, jeb->free_size);
486 			}
487 		}
488 	}
489 
490 	if (list_empty(&c->bad_used_list)) {
491 		printk(JFFS2_DBG_LVL "bad_used_list: empty\n");
492 	} else {
493 		struct list_head *this;
494 
495 		list_for_each(this, &c->bad_used_list) {
496 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
497 
498 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
499 				printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
500 					"unchecked %#08x, free %#08x)\n",
501 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
502 					jeb->unchecked_size, jeb->free_size);
503 			}
504 		}
505 	}
506 }
507 
508 void
509 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
510 {
511 	down(&f->sem);
512 	jffs2_dbg_dump_fragtree_nolock(f);
513 	up(&f->sem);
514 }
515 
516 void
517 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
518 {
519 	struct jffs2_node_frag *this = frag_first(&f->fragtree);
520 	uint32_t lastofs = 0;
521 	int buggy = 0;
522 
523 	JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino);
524 	while(this) {
525 		if (this->node)
526 			printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
527 				"right (%p), parent (%p)\n",
528 				this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
529 				ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
530 				frag_parent(this));
531 		else
532 			printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
533 				this->ofs, this->ofs+this->size, this, frag_left(this),
534 				frag_right(this), frag_parent(this));
535 		if (this->ofs != lastofs)
536 			buggy = 1;
537 		lastofs = this->ofs + this->size;
538 		this = frag_next(this);
539 	}
540 
541 	if (f->metadata)
542 		printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
543 
544 	if (buggy) {
545 		JFFS2_ERROR("frag tree got a hole in it.\n");
546 		BUG();
547 	}
548 }
549 
550 #define JFFS2_BUFDUMP_BYTES_PER_LINE	32
551 void
552 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
553 {
554 	int skip;
555 	int i;
556 
557 	JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n",
558 		offs, offs + len, len);
559 	i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
560 	offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
561 
562 	if (skip != 0)
563 		printk(JFFS2_DBG_LVL "%#08x: ", offs);
564 
565 	while (skip--)
566 		printk("   ");
567 
568 	while (i < len) {
569 		if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
570 			if (i != 0)
571 				printk("\n");
572 			offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
573 			printk(JFFS2_DBG_LVL "%0#8x: ", offs);
574 		}
575 
576 		printk("%02x ", buf[i]);
577 
578 		i += 1;
579 	}
580 
581 	printk("\n");
582 }
583 
584 /*
585  * Dump a JFFS2 node.
586  */
587 void
588 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
589 {
590 	union jffs2_node_union node;
591 	int len = sizeof(union jffs2_node_union);
592 	size_t retlen;
593 	uint32_t crc;
594 	int ret;
595 
596 	JFFS2_DEBUG("dump node at offset %#08x.\n", ofs);
597 
598 	ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
599 	if (ret || (retlen != len)) {
600 		JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
601 			len, ret, retlen);
602 		return;
603 	}
604 
605 	printk(JFFS2_DBG_LVL "magic:\t%#04x\n",
606 		je16_to_cpu(node.u.magic));
607 	printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n",
608 		je16_to_cpu(node.u.nodetype));
609 	printk(JFFS2_DBG_LVL "totlen:\t%#08x\n",
610 		je32_to_cpu(node.u.totlen));
611 	printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n",
612 		je32_to_cpu(node.u.hdr_crc));
613 
614 	crc = crc32(0, &node.u, sizeof(node.u) - 4);
615 	if (crc != je32_to_cpu(node.u.hdr_crc)) {
616 		JFFS2_ERROR("wrong common header CRC.\n");
617 		return;
618 	}
619 
620 	if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
621 		je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
622 	{
623 		JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
624 			je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
625 		return;
626 	}
627 
628 	switch(je16_to_cpu(node.u.nodetype)) {
629 
630 	case JFFS2_NODETYPE_INODE:
631 
632 		printk(JFFS2_DBG_LVL "the node is inode node\n");
633 		printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
634 				je32_to_cpu(node.i.ino));
635 		printk(JFFS2_DBG_LVL "version:\t%#08x\n",
636 				je32_to_cpu(node.i.version));
637 		printk(JFFS2_DBG_LVL "mode:\t%#08x\n",
638 				node.i.mode.m);
639 		printk(JFFS2_DBG_LVL "uid:\t%#04x\n",
640 				je16_to_cpu(node.i.uid));
641 		printk(JFFS2_DBG_LVL "gid:\t%#04x\n",
642 				je16_to_cpu(node.i.gid));
643 		printk(JFFS2_DBG_LVL "isize:\t%#08x\n",
644 				je32_to_cpu(node.i.isize));
645 		printk(JFFS2_DBG_LVL "atime:\t%#08x\n",
646 				je32_to_cpu(node.i.atime));
647 		printk(JFFS2_DBG_LVL "mtime:\t%#08x\n",
648 				je32_to_cpu(node.i.mtime));
649 		printk(JFFS2_DBG_LVL "ctime:\t%#08x\n",
650 				je32_to_cpu(node.i.ctime));
651 		printk(JFFS2_DBG_LVL "offset:\t%#08x\n",
652 				je32_to_cpu(node.i.offset));
653 		printk(JFFS2_DBG_LVL "csize:\t%#08x\n",
654 				je32_to_cpu(node.i.csize));
655 		printk(JFFS2_DBG_LVL "dsize:\t%#08x\n",
656 				je32_to_cpu(node.i.dsize));
657 		printk(JFFS2_DBG_LVL "compr:\t%#02x\n",
658 				node.i.compr);
659 		printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n",
660 				node.i.usercompr);
661 		printk(JFFS2_DBG_LVL "flags:\t%#04x\n",
662 				je16_to_cpu(node.i.flags));
663 		printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n",
664 				je32_to_cpu(node.i.data_crc));
665 		printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
666 				je32_to_cpu(node.i.node_crc));
667 		crc = crc32(0, &node.i, sizeof(node.i) - 8);
668 		if (crc != je32_to_cpu(node.i.node_crc)) {
669 			JFFS2_ERROR("wrong node header CRC.\n");
670 			return;
671 		}
672 		break;
673 
674 	case JFFS2_NODETYPE_DIRENT:
675 
676 		printk(JFFS2_DBG_LVL "the node is dirent node\n");
677 		printk(JFFS2_DBG_LVL "pino:\t%#08x\n",
678 				je32_to_cpu(node.d.pino));
679 		printk(JFFS2_DBG_LVL "version:\t%#08x\n",
680 				je32_to_cpu(node.d.version));
681 		printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
682 				je32_to_cpu(node.d.ino));
683 		printk(JFFS2_DBG_LVL "mctime:\t%#08x\n",
684 				je32_to_cpu(node.d.mctime));
685 		printk(JFFS2_DBG_LVL "nsize:\t%#02x\n",
686 				node.d.nsize);
687 		printk(JFFS2_DBG_LVL "type:\t%#02x\n",
688 				node.d.type);
689 		printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
690 				je32_to_cpu(node.d.node_crc));
691 		printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n",
692 				je32_to_cpu(node.d.name_crc));
693 
694 		node.d.name[node.d.nsize] = '\0';
695 		printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name);
696 
697 		crc = crc32(0, &node.d, sizeof(node.d) - 8);
698 		if (crc != je32_to_cpu(node.d.node_crc)) {
699 			JFFS2_ERROR("wrong node header CRC.\n");
700 			return;
701 		}
702 		break;
703 
704 	default:
705 		printk(JFFS2_DBG_LVL "node type is unknown\n");
706 		break;
707 	}
708 }
709 #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */
710