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