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