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