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