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