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
__jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)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
__jffs2_dbg_acct_sanity_check(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)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
__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info * f)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
__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info * f)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
__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info * c,uint32_t ofs,int len)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 
__jffs2_dbg_superblock_counts(struct jffs2_sb_info * c)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 	if (sz != c->sz##_size) {			\
266 		printk(KERN_WARNING #sz "_size mismatch counted 0x%x, c->" #sz "_size 0x%x\n", \
267 		       sz, c->sz##_size);		\
268 		dump = 1;				\
269 	}
270 	check(free);
271 	check(dirty);
272 	check(used);
273 	check(wasted);
274 	check(unchecked);
275 	check(bad);
276 	check(erasing);
277 #undef check
278 
279 	if (nr_counted != c->nr_blocks) {
280 		printk(KERN_WARNING "%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
281 		       __func__, nr_counted, c->nr_blocks);
282 		dump = 1;
283 	}
284 
285 	if (dump) {
286 		__jffs2_dbg_dump_block_lists_nolock(c);
287 		BUG();
288 	}
289 }
290 
291 /*
292  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
293  */
294 void
__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)295 __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
296 				struct jffs2_eraseblock *jeb)
297 {
298 	spin_lock(&c->erase_completion_lock);
299 	__jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
300 	spin_unlock(&c->erase_completion_lock);
301 }
302 
303 void
__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)304 __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
305 				       struct jffs2_eraseblock *jeb)
306 {
307 	uint32_t my_used_size = 0;
308 	uint32_t my_unchecked_size = 0;
309 	uint32_t my_dirty_size = 0;
310 	struct jffs2_raw_node_ref *ref2 = jeb->first_node;
311 
312 	while (ref2) {
313 		uint32_t totlen = ref_totlen(c, jeb, ref2);
314 
315 		if (ref_offset(ref2) < jeb->offset ||
316 				ref_offset(ref2) > jeb->offset + c->sector_size) {
317 			JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
318 				ref_offset(ref2), jeb->offset);
319 			goto error;
320 
321 		}
322 		if (ref_flags(ref2) == REF_UNCHECKED)
323 			my_unchecked_size += totlen;
324 		else if (!ref_obsolete(ref2))
325 			my_used_size += totlen;
326 		else
327 			my_dirty_size += totlen;
328 
329 		if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
330 			JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
331 				    ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
332 				    ref_offset(jeb->last_node), jeb->last_node);
333 			goto error;
334 		}
335 		ref2 = ref_next(ref2);
336 	}
337 
338 	if (my_used_size != jeb->used_size) {
339 		JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
340 			my_used_size, jeb->used_size);
341 		goto error;
342 	}
343 
344 	if (my_unchecked_size != jeb->unchecked_size) {
345 		JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
346 			my_unchecked_size, jeb->unchecked_size);
347 		goto error;
348 	}
349 
350 #if 0
351 	/* This should work when we implement ref->__totlen elemination */
352 	if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
353 		JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
354 			my_dirty_size, jeb->dirty_size + jeb->wasted_size);
355 		goto error;
356 	}
357 
358 	if (jeb->free_size == 0
359 		&& my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
360 		JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
361 			my_used_size + my_unchecked_size + my_dirty_size,
362 			c->sector_size);
363 		goto error;
364 	}
365 #endif
366 
367 	if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
368 		__jffs2_dbg_superblock_counts(c);
369 
370 	return;
371 
372 error:
373 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
374 	__jffs2_dbg_dump_jeb_nolock(jeb);
375 	__jffs2_dbg_dump_block_lists_nolock(c);
376 	BUG();
377 
378 }
379 #endif /* JFFS2_DBG_PARANOIA_CHECKS */
380 
381 #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
382 /*
383  * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
384  */
385 void
__jffs2_dbg_dump_node_refs(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)386 __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
387 			   struct jffs2_eraseblock *jeb)
388 {
389 	spin_lock(&c->erase_completion_lock);
390 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
391 	spin_unlock(&c->erase_completion_lock);
392 }
393 
394 void
__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)395 __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
396 				  struct jffs2_eraseblock *jeb)
397 {
398 	struct jffs2_raw_node_ref *ref;
399 	int i = 0;
400 
401 	printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
402 	if (!jeb->first_node) {
403 		printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
404 		return;
405 	}
406 
407 	printk(JFFS2_DBG);
408 	for (ref = jeb->first_node; ; ref = ref_next(ref)) {
409 		printk("%#08x", ref_offset(ref));
410 #ifdef TEST_TOTLEN
411 		printk("(%x)", ref->__totlen);
412 #endif
413 		if (ref_next(ref))
414 			printk("->");
415 		else
416 			break;
417 		if (++i == 4) {
418 			i = 0;
419 			printk("\n" JFFS2_DBG);
420 		}
421 	}
422 	printk("\n");
423 }
424 
425 /*
426  * Dump an eraseblock's space accounting.
427  */
428 void
__jffs2_dbg_dump_jeb(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)429 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
430 {
431 	spin_lock(&c->erase_completion_lock);
432 	__jffs2_dbg_dump_jeb_nolock(jeb);
433 	spin_unlock(&c->erase_completion_lock);
434 }
435 
436 void
__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock * jeb)437 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
438 {
439 	if (!jeb)
440 		return;
441 
442 	printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
443 			jeb->offset);
444 
445 	printk(JFFS2_DBG "used_size: %#08x\n",		jeb->used_size);
446 	printk(JFFS2_DBG "dirty_size: %#08x\n",		jeb->dirty_size);
447 	printk(JFFS2_DBG "wasted_size: %#08x\n",	jeb->wasted_size);
448 	printk(JFFS2_DBG "unchecked_size: %#08x\n",	jeb->unchecked_size);
449 	printk(JFFS2_DBG "free_size: %#08x\n",		jeb->free_size);
450 }
451 
452 void
__jffs2_dbg_dump_block_lists(struct jffs2_sb_info * c)453 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
454 {
455 	spin_lock(&c->erase_completion_lock);
456 	__jffs2_dbg_dump_block_lists_nolock(c);
457 	spin_unlock(&c->erase_completion_lock);
458 }
459 
460 void
__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info * c)461 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
462 {
463 	printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
464 
465 	printk(JFFS2_DBG "flash_size: %#08x\n",		c->flash_size);
466 	printk(JFFS2_DBG "used_size: %#08x\n",		c->used_size);
467 	printk(JFFS2_DBG "dirty_size: %#08x\n",		c->dirty_size);
468 	printk(JFFS2_DBG "wasted_size: %#08x\n",	c->wasted_size);
469 	printk(JFFS2_DBG "unchecked_size: %#08x\n",	c->unchecked_size);
470 	printk(JFFS2_DBG "free_size: %#08x\n",		c->free_size);
471 	printk(JFFS2_DBG "erasing_size: %#08x\n",	c->erasing_size);
472 	printk(JFFS2_DBG "bad_size: %#08x\n",		c->bad_size);
473 	printk(JFFS2_DBG "sector_size: %#08x\n",	c->sector_size);
474 	printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
475 				c->sector_size * c->resv_blocks_write);
476 
477 	if (c->nextblock)
478 		printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
479 			c->nextblock->offset, c->nextblock->used_size,
480 			c->nextblock->dirty_size, c->nextblock->wasted_size,
481 			c->nextblock->unchecked_size, c->nextblock->free_size);
482 	else
483 		printk(JFFS2_DBG "nextblock: NULL\n");
484 
485 	if (c->gcblock)
486 		printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
487 			c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
488 			c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
489 	else
490 		printk(JFFS2_DBG "gcblock: NULL\n");
491 
492 	if (list_empty(&c->clean_list)) {
493 		printk(JFFS2_DBG "clean_list: empty\n");
494 	} else {
495 		struct list_head *this;
496 		int numblocks = 0;
497 		uint32_t dirty = 0;
498 
499 		list_for_each(this, &c->clean_list) {
500 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
501 			numblocks ++;
502 			dirty += jeb->wasted_size;
503 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
504 				printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
505 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
506 					jeb->unchecked_size, jeb->free_size);
507 			}
508 		}
509 
510 		printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
511 			numblocks, dirty, dirty / numblocks);
512 	}
513 
514 	if (list_empty(&c->very_dirty_list)) {
515 		printk(JFFS2_DBG "very_dirty_list: empty\n");
516 	} else {
517 		struct list_head *this;
518 		int numblocks = 0;
519 		uint32_t dirty = 0;
520 
521 		list_for_each(this, &c->very_dirty_list) {
522 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
523 
524 			numblocks ++;
525 			dirty += jeb->dirty_size;
526 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
527 				printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
528 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
529 					jeb->unchecked_size, jeb->free_size);
530 			}
531 		}
532 
533 		printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
534 			numblocks, dirty, dirty / numblocks);
535 	}
536 
537 	if (list_empty(&c->dirty_list)) {
538 		printk(JFFS2_DBG "dirty_list: empty\n");
539 	} else {
540 		struct list_head *this;
541 		int numblocks = 0;
542 		uint32_t dirty = 0;
543 
544 		list_for_each(this, &c->dirty_list) {
545 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
546 
547 			numblocks ++;
548 			dirty += jeb->dirty_size;
549 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
550 				printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
551 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
552 					jeb->unchecked_size, jeb->free_size);
553 			}
554 		}
555 
556 		printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
557 			numblocks, dirty, dirty / numblocks);
558 	}
559 
560 	if (list_empty(&c->erasable_list)) {
561 		printk(JFFS2_DBG "erasable_list: empty\n");
562 	} else {
563 		struct list_head *this;
564 
565 		list_for_each(this, &c->erasable_list) {
566 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
567 
568 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
569 				printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
570 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
571 					jeb->unchecked_size, jeb->free_size);
572 			}
573 		}
574 	}
575 
576 	if (list_empty(&c->erasing_list)) {
577 		printk(JFFS2_DBG "erasing_list: empty\n");
578 	} else {
579 		struct list_head *this;
580 
581 		list_for_each(this, &c->erasing_list) {
582 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
583 
584 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
585 				printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
586 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
587 					jeb->unchecked_size, jeb->free_size);
588 			}
589 		}
590 	}
591 	if (list_empty(&c->erase_checking_list)) {
592 		printk(JFFS2_DBG "erase_checking_list: empty\n");
593 	} else {
594 		struct list_head *this;
595 
596 		list_for_each(this, &c->erase_checking_list) {
597 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
598 
599 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
600 				printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
601 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
602 					jeb->unchecked_size, jeb->free_size);
603 			}
604 		}
605 	}
606 
607 	if (list_empty(&c->erase_pending_list)) {
608 		printk(JFFS2_DBG "erase_pending_list: empty\n");
609 	} else {
610 		struct list_head *this;
611 
612 		list_for_each(this, &c->erase_pending_list) {
613 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
614 
615 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
616 				printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
617 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
618 					jeb->unchecked_size, jeb->free_size);
619 			}
620 		}
621 	}
622 
623 	if (list_empty(&c->erasable_pending_wbuf_list)) {
624 		printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
625 	} else {
626 		struct list_head *this;
627 
628 		list_for_each(this, &c->erasable_pending_wbuf_list) {
629 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
630 
631 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
632 				printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
633 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
634 					jeb->unchecked_size, jeb->free_size);
635 			}
636 		}
637 	}
638 
639 	if (list_empty(&c->free_list)) {
640 		printk(JFFS2_DBG "free_list: empty\n");
641 	} else {
642 		struct list_head *this;
643 
644 		list_for_each(this, &c->free_list) {
645 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
646 
647 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
648 				printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
649 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
650 					jeb->unchecked_size, jeb->free_size);
651 			}
652 		}
653 	}
654 
655 	if (list_empty(&c->bad_list)) {
656 		printk(JFFS2_DBG "bad_list: empty\n");
657 	} else {
658 		struct list_head *this;
659 
660 		list_for_each(this, &c->bad_list) {
661 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
662 
663 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
664 				printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
665 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
666 					jeb->unchecked_size, jeb->free_size);
667 			}
668 		}
669 	}
670 
671 	if (list_empty(&c->bad_used_list)) {
672 		printk(JFFS2_DBG "bad_used_list: empty\n");
673 	} else {
674 		struct list_head *this;
675 
676 		list_for_each(this, &c->bad_used_list) {
677 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
678 
679 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
680 				printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
681 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
682 					jeb->unchecked_size, jeb->free_size);
683 			}
684 		}
685 	}
686 }
687 
688 void
__jffs2_dbg_dump_fragtree(struct jffs2_inode_info * f)689 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
690 {
691 	mutex_lock(&f->sem);
692 	jffs2_dbg_dump_fragtree_nolock(f);
693 	mutex_unlock(&f->sem);
694 }
695 
696 void
__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info * f)697 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
698 {
699 	struct jffs2_node_frag *this = frag_first(&f->fragtree);
700 	uint32_t lastofs = 0;
701 	int buggy = 0;
702 
703 	printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
704 	while(this) {
705 		if (this->node)
706 			printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
707 				this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
708 				ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
709 				frag_parent(this));
710 		else
711 			printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
712 				this->ofs, this->ofs+this->size, this, frag_left(this),
713 				frag_right(this), frag_parent(this));
714 		if (this->ofs != lastofs)
715 			buggy = 1;
716 		lastofs = this->ofs + this->size;
717 		this = frag_next(this);
718 	}
719 
720 	if (f->metadata)
721 		printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
722 
723 	if (buggy) {
724 		JFFS2_ERROR("frag tree got a hole in it.\n");
725 		BUG();
726 	}
727 }
728 
729 #define JFFS2_BUFDUMP_BYTES_PER_LINE	32
730 void
__jffs2_dbg_dump_buffer(unsigned char * buf,int len,uint32_t offs)731 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
732 {
733 	int skip;
734 	int i;
735 
736 	printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
737 		offs, offs + len, len);
738 	i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
739 	offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
740 
741 	if (skip != 0)
742 		printk(JFFS2_DBG "%#08x: ", offs);
743 
744 	while (skip--)
745 		printk("   ");
746 
747 	while (i < len) {
748 		if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
749 			if (i != 0)
750 				printk("\n");
751 			offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
752 			printk(JFFS2_DBG "%0#8x: ", offs);
753 		}
754 
755 		printk("%02x ", buf[i]);
756 
757 		i += 1;
758 	}
759 
760 	printk("\n");
761 }
762 
763 /*
764  * Dump a JFFS2 node.
765  */
766 void
__jffs2_dbg_dump_node(struct jffs2_sb_info * c,uint32_t ofs)767 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
768 {
769 	union jffs2_node_union node;
770 	int len = sizeof(union jffs2_node_union);
771 	size_t retlen;
772 	uint32_t crc;
773 	int ret;
774 
775 	printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
776 
777 	ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
778 	if (ret || (retlen != len)) {
779 		JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
780 			len, ret, retlen);
781 		return;
782 	}
783 
784 	printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
785 	printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
786 	printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
787 	printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
788 
789 	crc = crc32(0, &node.u, sizeof(node.u) - 4);
790 	if (crc != je32_to_cpu(node.u.hdr_crc)) {
791 		JFFS2_ERROR("wrong common header CRC.\n");
792 		return;
793 	}
794 
795 	if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
796 		je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
797 	{
798 		JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
799 			je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
800 		return;
801 	}
802 
803 	switch(je16_to_cpu(node.u.nodetype)) {
804 
805 	case JFFS2_NODETYPE_INODE:
806 
807 		printk(JFFS2_DBG "the node is inode node\n");
808 		printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
809 		printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
810 		printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
811 		printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
812 		printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
813 		printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
814 		printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
815 		printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
816 		printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
817 		printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
818 		printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
819 		printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
820 		printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
821 		printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
822 		printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
823 		printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
824 		printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
825 
826 		crc = crc32(0, &node.i, sizeof(node.i) - 8);
827 		if (crc != je32_to_cpu(node.i.node_crc)) {
828 			JFFS2_ERROR("wrong node header CRC.\n");
829 			return;
830 		}
831 		break;
832 
833 	case JFFS2_NODETYPE_DIRENT:
834 
835 		printk(JFFS2_DBG "the node is dirent node\n");
836 		printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
837 		printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
838 		printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
839 		printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
840 		printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
841 		printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
842 		printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
843 		printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
844 
845 		node.d.name[node.d.nsize] = '\0';
846 		printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
847 
848 		crc = crc32(0, &node.d, sizeof(node.d) - 8);
849 		if (crc != je32_to_cpu(node.d.node_crc)) {
850 			JFFS2_ERROR("wrong node header CRC.\n");
851 			return;
852 		}
853 		break;
854 
855 	default:
856 		printk(JFFS2_DBG "node type is unknown\n");
857 		break;
858 	}
859 }
860 #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */
861