xref: /openbmc/linux/fs/jffs2/debug.c (revision 27e6b8e3)
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", ref_offset(ref));
404 #ifdef TEST_TOTLEN
405 		printk("(%x)", ref->__totlen);
406 #endif
407 		if (ref_next(ref))
408 			printk("->");
409 		else
410 			break;
411 		if (++i == 4) {
412 			i = 0;
413 			printk("\n" JFFS2_DBG);
414 		}
415 	}
416 	printk("\n");
417 }
418 
419 /*
420  * Dump an eraseblock's space accounting.
421  */
422 void
423 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
424 {
425 	spin_lock(&c->erase_completion_lock);
426 	__jffs2_dbg_dump_jeb_nolock(jeb);
427 	spin_unlock(&c->erase_completion_lock);
428 }
429 
430 void
431 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
432 {
433 	if (!jeb)
434 		return;
435 
436 	printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
437 			jeb->offset);
438 
439 	printk(JFFS2_DBG "used_size: %#08x\n",		jeb->used_size);
440 	printk(JFFS2_DBG "dirty_size: %#08x\n",		jeb->dirty_size);
441 	printk(JFFS2_DBG "wasted_size: %#08x\n",	jeb->wasted_size);
442 	printk(JFFS2_DBG "unchecked_size: %#08x\n",	jeb->unchecked_size);
443 	printk(JFFS2_DBG "free_size: %#08x\n",		jeb->free_size);
444 }
445 
446 void
447 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
448 {
449 	spin_lock(&c->erase_completion_lock);
450 	__jffs2_dbg_dump_block_lists_nolock(c);
451 	spin_unlock(&c->erase_completion_lock);
452 }
453 
454 void
455 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
456 {
457 	printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
458 
459 	printk(JFFS2_DBG "flash_size: %#08x\n",		c->flash_size);
460 	printk(JFFS2_DBG "used_size: %#08x\n",		c->used_size);
461 	printk(JFFS2_DBG "dirty_size: %#08x\n",		c->dirty_size);
462 	printk(JFFS2_DBG "wasted_size: %#08x\n",	c->wasted_size);
463 	printk(JFFS2_DBG "unchecked_size: %#08x\n",	c->unchecked_size);
464 	printk(JFFS2_DBG "free_size: %#08x\n",		c->free_size);
465 	printk(JFFS2_DBG "erasing_size: %#08x\n",	c->erasing_size);
466 	printk(JFFS2_DBG "bad_size: %#08x\n",		c->bad_size);
467 	printk(JFFS2_DBG "sector_size: %#08x\n",	c->sector_size);
468 	printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
469 				c->sector_size * c->resv_blocks_write);
470 
471 	if (c->nextblock)
472 		printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
473 			c->nextblock->offset, c->nextblock->used_size,
474 			c->nextblock->dirty_size, c->nextblock->wasted_size,
475 			c->nextblock->unchecked_size, c->nextblock->free_size);
476 	else
477 		printk(JFFS2_DBG "nextblock: NULL\n");
478 
479 	if (c->gcblock)
480 		printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
481 			c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
482 			c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
483 	else
484 		printk(JFFS2_DBG "gcblock: NULL\n");
485 
486 	if (list_empty(&c->clean_list)) {
487 		printk(JFFS2_DBG "clean_list: empty\n");
488 	} else {
489 		struct list_head *this;
490 		int numblocks = 0;
491 		uint32_t dirty = 0;
492 
493 		list_for_each(this, &c->clean_list) {
494 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
495 			numblocks ++;
496 			dirty += jeb->wasted_size;
497 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
498 				printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
499 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
500 					jeb->unchecked_size, jeb->free_size);
501 			}
502 		}
503 
504 		printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
505 			numblocks, dirty, dirty / numblocks);
506 	}
507 
508 	if (list_empty(&c->very_dirty_list)) {
509 		printk(JFFS2_DBG "very_dirty_list: empty\n");
510 	} else {
511 		struct list_head *this;
512 		int numblocks = 0;
513 		uint32_t dirty = 0;
514 
515 		list_for_each(this, &c->very_dirty_list) {
516 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
517 
518 			numblocks ++;
519 			dirty += jeb->dirty_size;
520 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
521 				printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
522 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
523 					jeb->unchecked_size, jeb->free_size);
524 			}
525 		}
526 
527 		printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
528 			numblocks, dirty, dirty / numblocks);
529 	}
530 
531 	if (list_empty(&c->dirty_list)) {
532 		printk(JFFS2_DBG "dirty_list: empty\n");
533 	} else {
534 		struct list_head *this;
535 		int numblocks = 0;
536 		uint32_t dirty = 0;
537 
538 		list_for_each(this, &c->dirty_list) {
539 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
540 
541 			numblocks ++;
542 			dirty += jeb->dirty_size;
543 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
544 				printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
545 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
546 					jeb->unchecked_size, jeb->free_size);
547 			}
548 		}
549 
550 		printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
551 			numblocks, dirty, dirty / numblocks);
552 	}
553 
554 	if (list_empty(&c->erasable_list)) {
555 		printk(JFFS2_DBG "erasable_list: empty\n");
556 	} else {
557 		struct list_head *this;
558 
559 		list_for_each(this, &c->erasable_list) {
560 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
561 
562 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
563 				printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
564 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
565 					jeb->unchecked_size, jeb->free_size);
566 			}
567 		}
568 	}
569 
570 	if (list_empty(&c->erasing_list)) {
571 		printk(JFFS2_DBG "erasing_list: empty\n");
572 	} else {
573 		struct list_head *this;
574 
575 		list_for_each(this, &c->erasing_list) {
576 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
577 
578 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
579 				printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
580 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
581 					jeb->unchecked_size, jeb->free_size);
582 			}
583 		}
584 	}
585 
586 	if (list_empty(&c->erase_pending_list)) {
587 		printk(JFFS2_DBG "erase_pending_list: empty\n");
588 	} else {
589 		struct list_head *this;
590 
591 		list_for_each(this, &c->erase_pending_list) {
592 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
593 
594 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
595 				printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
596 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
597 					jeb->unchecked_size, jeb->free_size);
598 			}
599 		}
600 	}
601 
602 	if (list_empty(&c->erasable_pending_wbuf_list)) {
603 		printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
604 	} else {
605 		struct list_head *this;
606 
607 		list_for_each(this, &c->erasable_pending_wbuf_list) {
608 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
609 
610 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
611 				printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
612 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
613 					jeb->unchecked_size, jeb->free_size);
614 			}
615 		}
616 	}
617 
618 	if (list_empty(&c->free_list)) {
619 		printk(JFFS2_DBG "free_list: empty\n");
620 	} else {
621 		struct list_head *this;
622 
623 		list_for_each(this, &c->free_list) {
624 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
625 
626 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
627 				printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
628 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
629 					jeb->unchecked_size, jeb->free_size);
630 			}
631 		}
632 	}
633 
634 	if (list_empty(&c->bad_list)) {
635 		printk(JFFS2_DBG "bad_list: empty\n");
636 	} else {
637 		struct list_head *this;
638 
639 		list_for_each(this, &c->bad_list) {
640 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
641 
642 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
643 				printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
644 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
645 					jeb->unchecked_size, jeb->free_size);
646 			}
647 		}
648 	}
649 
650 	if (list_empty(&c->bad_used_list)) {
651 		printk(JFFS2_DBG "bad_used_list: empty\n");
652 	} else {
653 		struct list_head *this;
654 
655 		list_for_each(this, &c->bad_used_list) {
656 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
657 
658 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
659 				printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
660 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
661 					jeb->unchecked_size, jeb->free_size);
662 			}
663 		}
664 	}
665 }
666 
667 void
668 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
669 {
670 	mutex_lock(&f->sem);
671 	jffs2_dbg_dump_fragtree_nolock(f);
672 	mutex_unlock(&f->sem);
673 }
674 
675 void
676 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
677 {
678 	struct jffs2_node_frag *this = frag_first(&f->fragtree);
679 	uint32_t lastofs = 0;
680 	int buggy = 0;
681 
682 	printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
683 	while(this) {
684 		if (this->node)
685 			printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
686 				this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
687 				ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
688 				frag_parent(this));
689 		else
690 			printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
691 				this->ofs, this->ofs+this->size, this, frag_left(this),
692 				frag_right(this), frag_parent(this));
693 		if (this->ofs != lastofs)
694 			buggy = 1;
695 		lastofs = this->ofs + this->size;
696 		this = frag_next(this);
697 	}
698 
699 	if (f->metadata)
700 		printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
701 
702 	if (buggy) {
703 		JFFS2_ERROR("frag tree got a hole in it.\n");
704 		BUG();
705 	}
706 }
707 
708 #define JFFS2_BUFDUMP_BYTES_PER_LINE	32
709 void
710 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
711 {
712 	int skip;
713 	int i;
714 
715 	printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
716 		offs, offs + len, len);
717 	i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
718 	offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
719 
720 	if (skip != 0)
721 		printk(JFFS2_DBG "%#08x: ", offs);
722 
723 	while (skip--)
724 		printk("   ");
725 
726 	while (i < len) {
727 		if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
728 			if (i != 0)
729 				printk("\n");
730 			offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
731 			printk(JFFS2_DBG "%0#8x: ", offs);
732 		}
733 
734 		printk("%02x ", buf[i]);
735 
736 		i += 1;
737 	}
738 
739 	printk("\n");
740 }
741 
742 /*
743  * Dump a JFFS2 node.
744  */
745 void
746 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
747 {
748 	union jffs2_node_union node;
749 	int len = sizeof(union jffs2_node_union);
750 	size_t retlen;
751 	uint32_t crc;
752 	int ret;
753 
754 	printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
755 
756 	ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
757 	if (ret || (retlen != len)) {
758 		JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
759 			len, ret, retlen);
760 		return;
761 	}
762 
763 	printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
764 	printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
765 	printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
766 	printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
767 
768 	crc = crc32(0, &node.u, sizeof(node.u) - 4);
769 	if (crc != je32_to_cpu(node.u.hdr_crc)) {
770 		JFFS2_ERROR("wrong common header CRC.\n");
771 		return;
772 	}
773 
774 	if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
775 		je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
776 	{
777 		JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
778 			je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
779 		return;
780 	}
781 
782 	switch(je16_to_cpu(node.u.nodetype)) {
783 
784 	case JFFS2_NODETYPE_INODE:
785 
786 		printk(JFFS2_DBG "the node is inode node\n");
787 		printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
788 		printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
789 		printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
790 		printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
791 		printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
792 		printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
793 		printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
794 		printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
795 		printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
796 		printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
797 		printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
798 		printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
799 		printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
800 		printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
801 		printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
802 		printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
803 		printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
804 
805 		crc = crc32(0, &node.i, sizeof(node.i) - 8);
806 		if (crc != je32_to_cpu(node.i.node_crc)) {
807 			JFFS2_ERROR("wrong node header CRC.\n");
808 			return;
809 		}
810 		break;
811 
812 	case JFFS2_NODETYPE_DIRENT:
813 
814 		printk(JFFS2_DBG "the node is dirent node\n");
815 		printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
816 		printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
817 		printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
818 		printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
819 		printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
820 		printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
821 		printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
822 		printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
823 
824 		node.d.name[node.d.nsize] = '\0';
825 		printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
826 
827 		crc = crc32(0, &node.d, sizeof(node.d) - 8);
828 		if (crc != je32_to_cpu(node.d.node_crc)) {
829 			JFFS2_ERROR("wrong node header CRC.\n");
830 			return;
831 		}
832 		break;
833 
834 	default:
835 		printk(JFFS2_DBG "node type is unknown\n");
836 		break;
837 	}
838 }
839 #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */
840