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