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
27void
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
51void
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 */
66void
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
74void
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 */
124void
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
160static 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)							\
267do {									\
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 */
300void
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
309void
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
378error:
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 */
391void
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
400void
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 */
434void
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
442void
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
458void
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
466void
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
694void
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
702void
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
736void
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 */
772void
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