xref: /openbmc/linux/fs/jffs2/debug.c (revision 730554d9)
1730554d9SArtem B. Bityutskiy /*
2730554d9SArtem B. Bityutskiy  * JFFS2 -- Journalling Flash File System, Version 2.
3730554d9SArtem B. Bityutskiy  *
4730554d9SArtem B. Bityutskiy  * Copyright (C) 2001-2003 Red Hat, Inc.
5730554d9SArtem B. Bityutskiy  *
6730554d9SArtem B. Bityutskiy  * Created by David Woodhouse <dwmw2@infradead.org>
7730554d9SArtem B. Bityutskiy  *
8730554d9SArtem B. Bityutskiy  * For licensing information, see the file 'LICENCE' in this directory.
9730554d9SArtem B. Bityutskiy  *
10730554d9SArtem B. Bityutskiy  * $Id: debug.c,v 1.1 2005/07/17 06:56:20 dedekind Exp $
11730554d9SArtem B. Bityutskiy  *
12730554d9SArtem B. Bityutskiy  */
13730554d9SArtem B. Bityutskiy #include <linux/kernel.h>
14730554d9SArtem B. Bityutskiy #include <linux/pagemap.h>
15730554d9SArtem B. Bityutskiy #include "nodelist.h"
16730554d9SArtem B. Bityutskiy #include "debug.h"
17730554d9SArtem B. Bityutskiy 
18730554d9SArtem B. Bityutskiy #ifdef JFFS2_DBG_PARANOIA_CHECKS
19730554d9SArtem B. Bityutskiy 
20730554d9SArtem B. Bityutskiy void
21730554d9SArtem B. Bityutskiy jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
22730554d9SArtem B. Bityutskiy {
23730554d9SArtem B. Bityutskiy 	struct jffs2_node_frag *frag;
24730554d9SArtem B. Bityutskiy 	int bitched = 0;
25730554d9SArtem B. Bityutskiy 
26730554d9SArtem B. Bityutskiy 	for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
27730554d9SArtem B. Bityutskiy 		struct jffs2_full_dnode *fn = frag->node;
28730554d9SArtem B. Bityutskiy 
29730554d9SArtem B. Bityutskiy 		if (!fn || !fn->raw)
30730554d9SArtem B. Bityutskiy 			continue;
31730554d9SArtem B. Bityutskiy 
32730554d9SArtem B. Bityutskiy 		if (ref_flags(fn->raw) == REF_PRISTINE) {
33730554d9SArtem B. Bityutskiy 			if (fn->frags > 1) {
34730554d9SArtem B. Bityutskiy 				printk(KERN_ERR "REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2\n",
35730554d9SArtem B. Bityutskiy 						ref_offset(fn->raw), fn->frags);
36730554d9SArtem B. Bityutskiy 				bitched = 1;
37730554d9SArtem B. Bityutskiy 			}
38730554d9SArtem B. Bityutskiy 
39730554d9SArtem B. Bityutskiy 			/* A hole node which isn't multi-page should be garbage-collected
40730554d9SArtem B. Bityutskiy 			   and merged anyway, so we just check for the frag size here,
41730554d9SArtem B. Bityutskiy 			   rather than mucking around with actually reading the node
42730554d9SArtem B. Bityutskiy 			   and checking the compression type, which is the real way
43730554d9SArtem B. Bityutskiy 			   to tell a hole node. */
44730554d9SArtem B. Bityutskiy 			if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
45730554d9SArtem B. Bityutskiy 					&& frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
46730554d9SArtem B. Bityutskiy 				printk(KERN_ERR "REF_PRISTINE node at 0x%08x had a previous non-hole frag "
47730554d9SArtem B. Bityutskiy 						"in the same page. Tell dwmw2\n", ref_offset(fn->raw));
48730554d9SArtem B. Bityutskiy 				bitched = 1;
49730554d9SArtem B. Bityutskiy 			}
50730554d9SArtem B. Bityutskiy 
51730554d9SArtem B. Bityutskiy 			if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
52730554d9SArtem B. Bityutskiy 					&& frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
53730554d9SArtem B. Bityutskiy 				printk(KERN_ERR "REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
54730554d9SArtem B. Bityutskiy 						"non-hole frag in the same page. Tell dwmw2\n",
55730554d9SArtem B. Bityutskiy 					       ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
56730554d9SArtem B. Bityutskiy 				bitched = 1;
57730554d9SArtem B. Bityutskiy 			}
58730554d9SArtem B. Bityutskiy 		}
59730554d9SArtem B. Bityutskiy 	}
60730554d9SArtem B. Bityutskiy 
61730554d9SArtem B. Bityutskiy 	if (bitched) {
62730554d9SArtem B. Bityutskiy 		printk(KERN_ERR "Fragtree is corrupted. Fragtree dump:\n");
63730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_fragtree(f);
64730554d9SArtem B. Bityutskiy 		BUG();
65730554d9SArtem B. Bityutskiy 	}
66730554d9SArtem B. Bityutskiy }
67730554d9SArtem B. Bityutskiy 
68730554d9SArtem B. Bityutskiy /*
69730554d9SArtem B. Bityutskiy  * Check if the flash contains all 0xFF before we start writing.
70730554d9SArtem B. Bityutskiy  */
71730554d9SArtem B. Bityutskiy void
72730554d9SArtem B. Bityutskiy jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, uint32_t ofs, int len)
73730554d9SArtem B. Bityutskiy {
74730554d9SArtem B. Bityutskiy 	size_t retlen;
75730554d9SArtem B. Bityutskiy 	int ret, i;
76730554d9SArtem B. Bityutskiy 	unsigned char *buf;
77730554d9SArtem B. Bityutskiy 
78730554d9SArtem B. Bityutskiy 	buf = kmalloc(len, GFP_KERNEL);
79730554d9SArtem B. Bityutskiy 	if (!buf)
80730554d9SArtem B. Bityutskiy 		return;
81730554d9SArtem B. Bityutskiy 
82730554d9SArtem B. Bityutskiy 	ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
83730554d9SArtem B. Bityutskiy 	if (ret || (retlen != len)) {
84730554d9SArtem B. Bityutskiy 		printk(KERN_WARNING "read %d bytes failed or short in %s(). ret %d, retlen %zd\n",
85730554d9SArtem B. Bityutskiy 				len, __FUNCTION__, ret, retlen);
86730554d9SArtem B. Bityutskiy 		kfree(buf);
87730554d9SArtem B. Bityutskiy 		return;
88730554d9SArtem B. Bityutskiy 	}
89730554d9SArtem B. Bityutskiy 
90730554d9SArtem B. Bityutskiy 	ret = 0;
91730554d9SArtem B. Bityutskiy 	for (i = 0; i < len; i++)
92730554d9SArtem B. Bityutskiy 		if (buf[i] != 0xff)
93730554d9SArtem B. Bityutskiy 			ret = 1;
94730554d9SArtem B. Bityutskiy 
95730554d9SArtem B. Bityutskiy 	if (ret) {
96730554d9SArtem B. Bityutskiy 		printk(KERN_ERR "ARGH. About to write node to %#08x on flash, but there are data "
97730554d9SArtem B. Bityutskiy 				"already there. The first corrupted byte is at %#08x.\n", ofs, ofs + i);
98730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_buffer(buf, len, ofs);
99730554d9SArtem B. Bityutskiy 		kfree(buf);
100730554d9SArtem B. Bityutskiy 		BUG();
101730554d9SArtem B. Bityutskiy 	}
102730554d9SArtem B. Bityutskiy 
103730554d9SArtem B. Bityutskiy 	kfree(buf);
104730554d9SArtem B. Bityutskiy }
105730554d9SArtem B. Bityutskiy 
106730554d9SArtem B. Bityutskiy /*
107730554d9SArtem B. Bityutskiy  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
108730554d9SArtem B. Bityutskiy  */
109730554d9SArtem B. Bityutskiy void
110730554d9SArtem B. Bityutskiy jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
111730554d9SArtem B. Bityutskiy {
112730554d9SArtem B. Bityutskiy 	uint32_t my_used_size = 0;
113730554d9SArtem B. Bityutskiy 	uint32_t my_unchecked_size = 0;
114730554d9SArtem B. Bityutskiy 	uint32_t my_dirty_size = 0;
115730554d9SArtem B. Bityutskiy 	struct jffs2_raw_node_ref *ref2 = jeb->first_node;
116730554d9SArtem B. Bityutskiy 
117730554d9SArtem B. Bityutskiy 	while (ref2) {
118730554d9SArtem B. Bityutskiy 		uint32_t totlen = ref_totlen(c, jeb, ref2);
119730554d9SArtem B. Bityutskiy 
120730554d9SArtem B. Bityutskiy 		if (ref2->flash_offset < jeb->offset ||
121730554d9SArtem B. Bityutskiy 				ref2->flash_offset > jeb->offset + c->sector_size) {
122730554d9SArtem B. Bityutskiy 			printk(KERN_ERR "node_ref %#08x shouldn't be in block at %#08x!\n",
123730554d9SArtem B. Bityutskiy 				ref_offset(ref2), jeb->offset);
124730554d9SArtem B. Bityutskiy 			jffs2_dbg_dump_node_refs(c, jeb);
125730554d9SArtem B. Bityutskiy 			jffs2_dbg_dump_block_lists(c);
126730554d9SArtem B. Bityutskiy 			BUG();
127730554d9SArtem B. Bityutskiy 
128730554d9SArtem B. Bityutskiy 		}
129730554d9SArtem B. Bityutskiy 		if (ref_flags(ref2) == REF_UNCHECKED)
130730554d9SArtem B. Bityutskiy 			my_unchecked_size += totlen;
131730554d9SArtem B. Bityutskiy 		else if (!ref_obsolete(ref2))
132730554d9SArtem B. Bityutskiy 			my_used_size += totlen;
133730554d9SArtem B. Bityutskiy 		else
134730554d9SArtem B. Bityutskiy 			my_dirty_size += totlen;
135730554d9SArtem B. Bityutskiy 
136730554d9SArtem B. Bityutskiy 		if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
137730554d9SArtem B. Bityutskiy 			printk(KERN_ERR "node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
138730554d9SArtem B. Bityutskiy 					"last_node is at %#08x (mem %p)\n",
139730554d9SArtem B. Bityutskiy 					ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
140730554d9SArtem B. Bityutskiy 					ref_offset(jeb->last_node), jeb->last_node);
141730554d9SArtem B. Bityutskiy 			jffs2_dbg_dump_node_refs(c, jeb);
142730554d9SArtem B. Bityutskiy 			jffs2_dbg_dump_block_lists(c);
143730554d9SArtem B. Bityutskiy 			BUG();
144730554d9SArtem B. Bityutskiy 		}
145730554d9SArtem B. Bityutskiy 		ref2 = ref2->next_phys;
146730554d9SArtem B. Bityutskiy 	}
147730554d9SArtem B. Bityutskiy 
148730554d9SArtem B. Bityutskiy 	if (my_used_size != jeb->used_size) {
149730554d9SArtem B. Bityutskiy 		printk(KERN_ERR "Calculated used size %#08x != stored used size %#08x\n",
150730554d9SArtem B. Bityutskiy 				my_used_size, jeb->used_size);
151730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_node_refs(c, jeb);
152730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_block_lists(c);
153730554d9SArtem B. Bityutskiy 		BUG();
154730554d9SArtem B. Bityutskiy 	}
155730554d9SArtem B. Bityutskiy 
156730554d9SArtem B. Bityutskiy 	if (my_unchecked_size != jeb->unchecked_size) {
157730554d9SArtem B. Bityutskiy 		printk(KERN_ERR "Calculated unchecked size %#08x != stored unchecked size %#08x\n",
158730554d9SArtem B. Bityutskiy 				my_unchecked_size, jeb->unchecked_size);
159730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_node_refs(c, jeb);
160730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_block_lists(c);
161730554d9SArtem B. Bityutskiy 		BUG();
162730554d9SArtem B. Bityutskiy 	}
163730554d9SArtem B. Bityutskiy 
164730554d9SArtem B. Bityutskiy 	if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
165730554d9SArtem B. Bityutskiy 		printk(KERN_ERR "Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
166730554d9SArtem B. Bityutskiy 			my_dirty_size, jeb->dirty_size + jeb->wasted_size);
167730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_node_refs(c, jeb);
168730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_block_lists(c);
169730554d9SArtem B. Bityutskiy 		BUG();
170730554d9SArtem B. Bityutskiy 	}
171730554d9SArtem B. Bityutskiy 
172730554d9SArtem B. Bityutskiy 	if (jeb->free_size == 0
173730554d9SArtem B. Bityutskiy 		&& my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
174730554d9SArtem B. Bityutskiy 		printk(KERN_ERR "The sum of all nodes in block (%#x) != size of block (%#x)\n",
175730554d9SArtem B. Bityutskiy 			my_used_size + my_unchecked_size + my_dirty_size,
176730554d9SArtem B. Bityutskiy 			c->sector_size);
177730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_node_refs(c, jeb);
178730554d9SArtem B. Bityutskiy 		jffs2_dbg_dump_block_lists(c);
179730554d9SArtem B. Bityutskiy 		BUG();
180730554d9SArtem B. Bityutskiy 	}
181730554d9SArtem B. Bityutskiy }
182730554d9SArtem B. Bityutskiy #endif /* JFFS2_PARANOIA_CHECKS */
183730554d9SArtem B. Bityutskiy 
184730554d9SArtem B. Bityutskiy #if defined(JFFS2_PARANOIA_CHECKS) || (CONFIG_JFFS2_FS_DEBUG > 0)
185730554d9SArtem B. Bityutskiy /*
186730554d9SArtem B. Bityutskiy  * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
187730554d9SArtem B. Bityutskiy  */
188730554d9SArtem B. Bityutskiy void
189730554d9SArtem B. Bityutskiy jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
190730554d9SArtem B. Bityutskiy {
191730554d9SArtem B. Bityutskiy 	struct jffs2_raw_node_ref *ref;
192730554d9SArtem B. Bityutskiy 	int i = 0;
193730554d9SArtem B. Bityutskiy 
194730554d9SArtem B. Bityutskiy 	if (!jeb->first_node) {
195730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "no nodes in block %#08x\n", jeb->offset);
196730554d9SArtem B. Bityutskiy 		return;
197730554d9SArtem B. Bityutskiy 	}
198730554d9SArtem B. Bityutskiy 
199730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG);
200730554d9SArtem B. Bityutskiy 	for (ref = jeb->first_node; ; ref = ref->next_phys) {
201730554d9SArtem B. Bityutskiy 		printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
202730554d9SArtem B. Bityutskiy 		if (ref->next_phys)
203730554d9SArtem B. Bityutskiy 			printk("->");
204730554d9SArtem B. Bityutskiy 		else
205730554d9SArtem B. Bityutskiy 			break;
206730554d9SArtem B. Bityutskiy 		if (++i == 4) {
207730554d9SArtem B. Bityutskiy 			i = 0;
208730554d9SArtem B. Bityutskiy 			printk("\n" KERN_DEBUG);
209730554d9SArtem B. Bityutskiy 		}
210730554d9SArtem B. Bityutskiy 	}
211730554d9SArtem B. Bityutskiy 	printk("\n");
212730554d9SArtem B. Bityutskiy }
213730554d9SArtem B. Bityutskiy 
214730554d9SArtem B. Bityutskiy void
215730554d9SArtem B. Bityutskiy jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
216730554d9SArtem B. Bityutskiy {
217730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "flash_size: %#08x\n",	c->flash_size);
218730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "used_size: %#08x\n",		c->used_size);
219730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "dirty_size: %#08x\n",	c->dirty_size);
220730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "wasted_size: %#08x\n",	c->wasted_size);
221730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "unchecked_size: %#08x\n",	c->unchecked_size);
222730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "free_size: %#08x\n",		c->free_size);
223730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "erasing_size: %#08x\n",	c->erasing_size);
224730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "bad_size: %#08x\n",		c->bad_size);
225730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "sector_size: %#08x\n",	c->sector_size);
226730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "jffs2_reserved_blocks size: %#08x\n",
227730554d9SArtem B. Bityutskiy 				c->sector_size * c->resv_blocks_write);
228730554d9SArtem B. Bityutskiy 
229730554d9SArtem B. Bityutskiy 	if (c->nextblock)
230730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
231730554d9SArtem B. Bityutskiy 				"unchecked %#08x, free %#08x)\n",
232730554d9SArtem B. Bityutskiy 				c->nextblock->offset, c->nextblock->used_size,
233730554d9SArtem B. Bityutskiy 				c->nextblock->dirty_size, c->nextblock->wasted_size,
234730554d9SArtem B. Bityutskiy 				c->nextblock->unchecked_size, c->nextblock->free_size);
235730554d9SArtem B. Bityutskiy 	else
236730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "nextblock: NULL\n");
237730554d9SArtem B. Bityutskiy 
238730554d9SArtem B. Bityutskiy 	if (c->gcblock)
239730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
240730554d9SArtem B. Bityutskiy 				"unchecked %#08x, free %#08x)\n",
241730554d9SArtem B. Bityutskiy 				c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
242730554d9SArtem B. Bityutskiy 				c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
243730554d9SArtem B. Bityutskiy 	else
244730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "gcblock: NULL\n");
245730554d9SArtem B. Bityutskiy 
246730554d9SArtem B. Bityutskiy 	if (list_empty(&c->clean_list)) {
247730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "clean_list: empty\n");
248730554d9SArtem B. Bityutskiy 	} else {
249730554d9SArtem B. Bityutskiy 		struct list_head *this;
250730554d9SArtem B. Bityutskiy 		int numblocks = 0;
251730554d9SArtem B. Bityutskiy 		uint32_t dirty = 0;
252730554d9SArtem B. Bityutskiy 
253730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->clean_list) {
254730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
255730554d9SArtem B. Bityutskiy 			numblocks ++;
256730554d9SArtem B. Bityutskiy 			dirty += jeb->wasted_size;
257730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
258730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
259730554d9SArtem B. Bityutskiy 						"unchecked %#08x, free %#08x)\n",
260730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
261730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
262730554d9SArtem B. Bityutskiy 			}
263730554d9SArtem B. Bityutskiy 		}
264730554d9SArtem B. Bityutskiy 
265730554d9SArtem B. Bityutskiy 		printk (KERN_DEBUG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
266730554d9SArtem B. Bityutskiy 				numblocks, dirty, dirty / numblocks);
267730554d9SArtem B. Bityutskiy 	}
268730554d9SArtem B. Bityutskiy 
269730554d9SArtem B. Bityutskiy 	if (list_empty(&c->very_dirty_list)) {
270730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "very_dirty_list: empty\n");
271730554d9SArtem B. Bityutskiy 	} else {
272730554d9SArtem B. Bityutskiy 		struct list_head *this;
273730554d9SArtem B. Bityutskiy 		int numblocks = 0;
274730554d9SArtem B. Bityutskiy 		uint32_t dirty = 0;
275730554d9SArtem B. Bityutskiy 
276730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->very_dirty_list) {
277730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
278730554d9SArtem B. Bityutskiy 
279730554d9SArtem B. Bityutskiy 			numblocks ++;
280730554d9SArtem B. Bityutskiy 			dirty += jeb->dirty_size;
281730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
282730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
283730554d9SArtem B. Bityutskiy 						"unchecked %#08x, free %#08x)\n",
284730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
285730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
286730554d9SArtem B. Bityutskiy 			}
287730554d9SArtem B. Bityutskiy 		}
288730554d9SArtem B. Bityutskiy 
289730554d9SArtem B. Bityutskiy 		printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
290730554d9SArtem B. Bityutskiy 				numblocks, dirty, dirty / numblocks);
291730554d9SArtem B. Bityutskiy 	}
292730554d9SArtem B. Bityutskiy 
293730554d9SArtem B. Bityutskiy 	if (list_empty(&c->dirty_list)) {
294730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "dirty_list: empty\n");
295730554d9SArtem B. Bityutskiy 	} else {
296730554d9SArtem B. Bityutskiy 		struct list_head *this;
297730554d9SArtem B. Bityutskiy 		int numblocks = 0;
298730554d9SArtem B. Bityutskiy 		uint32_t dirty = 0;
299730554d9SArtem B. Bityutskiy 
300730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->dirty_list) {
301730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
302730554d9SArtem B. Bityutskiy 
303730554d9SArtem B. Bityutskiy 			numblocks ++;
304730554d9SArtem B. Bityutskiy 			dirty += jeb->dirty_size;
305730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
306730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
307730554d9SArtem B. Bityutskiy 						"unchecked %#08x, free %#08x)\n",
308730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
309730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
310730554d9SArtem B. Bityutskiy 			}
311730554d9SArtem B. Bityutskiy 		}
312730554d9SArtem B. Bityutskiy 
313730554d9SArtem B. Bityutskiy 		printk (KERN_DEBUG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
314730554d9SArtem B. Bityutskiy 			numblocks, dirty, dirty / numblocks);
315730554d9SArtem B. Bityutskiy 	}
316730554d9SArtem B. Bityutskiy 
317730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erasable_list)) {
318730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "erasable_list: empty\n");
319730554d9SArtem B. Bityutskiy 	} else {
320730554d9SArtem B. Bityutskiy 		struct list_head *this;
321730554d9SArtem B. Bityutskiy 
322730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erasable_list) {
323730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
324730554d9SArtem B. Bityutskiy 
325730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
326730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
327730554d9SArtem B. Bityutskiy 						"unchecked %#08x, free %#08x)\n",
328730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
329730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
330730554d9SArtem B. Bityutskiy 			}
331730554d9SArtem B. Bityutskiy 		}
332730554d9SArtem B. Bityutskiy 	}
333730554d9SArtem B. Bityutskiy 
334730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erasing_list)) {
335730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "erasing_list: empty\n");
336730554d9SArtem B. Bityutskiy 	} else {
337730554d9SArtem B. Bityutskiy 		struct list_head *this;
338730554d9SArtem B. Bityutskiy 
339730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erasing_list) {
340730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
341730554d9SArtem B. Bityutskiy 
342730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
343730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
344730554d9SArtem B. Bityutskiy 						"unchecked %#08x, free %#08x)\n",
345730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
346730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
347730554d9SArtem B. Bityutskiy 			}
348730554d9SArtem B. Bityutskiy 		}
349730554d9SArtem B. Bityutskiy 	}
350730554d9SArtem B. Bityutskiy 
351730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erase_pending_list)) {
352730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "erase_pending_list: empty\n");
353730554d9SArtem B. Bityutskiy 	} else {
354730554d9SArtem B. Bityutskiy 		struct list_head *this;
355730554d9SArtem B. Bityutskiy 
356730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erase_pending_list) {
357730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
358730554d9SArtem B. Bityutskiy 
359730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
360730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
361730554d9SArtem B. Bityutskiy 						"unchecked %#08x, free %#08x)\n",
362730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
363730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
364730554d9SArtem B. Bityutskiy 			}
365730554d9SArtem B. Bityutskiy 		}
366730554d9SArtem B. Bityutskiy 	}
367730554d9SArtem B. Bityutskiy 
368730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erasable_pending_wbuf_list)) {
369730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n");
370730554d9SArtem B. Bityutskiy 	} else {
371730554d9SArtem B. Bityutskiy 		struct list_head *this;
372730554d9SArtem B. Bityutskiy 
373730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erasable_pending_wbuf_list) {
374730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
375730554d9SArtem B. Bityutskiy 
376730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
377730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
378730554d9SArtem B. Bityutskiy 						"wasted %#08x, unchecked %#08x, free %#08x)\n",
379730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
380730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
381730554d9SArtem B. Bityutskiy 			}
382730554d9SArtem B. Bityutskiy 		}
383730554d9SArtem B. Bityutskiy 	}
384730554d9SArtem B. Bityutskiy 
385730554d9SArtem B. Bityutskiy 	if (list_empty(&c->free_list)) {
386730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "free_list: empty\n");
387730554d9SArtem B. Bityutskiy 	} else {
388730554d9SArtem B. Bityutskiy 		struct list_head *this;
389730554d9SArtem B. Bityutskiy 
390730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->free_list) {
391730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
392730554d9SArtem B. Bityutskiy 
393730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
394730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
395730554d9SArtem B. Bityutskiy 						"unchecked %#08x, free %#08x)\n",
396730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
397730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
398730554d9SArtem B. Bityutskiy 			}
399730554d9SArtem B. Bityutskiy 		}
400730554d9SArtem B. Bityutskiy 	}
401730554d9SArtem B. Bityutskiy 
402730554d9SArtem B. Bityutskiy 	if (list_empty(&c->bad_list)) {
403730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "bad_list: empty\n");
404730554d9SArtem B. Bityutskiy 	} else {
405730554d9SArtem B. Bityutskiy 		struct list_head *this;
406730554d9SArtem B. Bityutskiy 
407730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->bad_list) {
408730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
409730554d9SArtem B. Bityutskiy 
410730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
411730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
412730554d9SArtem B. Bityutskiy 						"unchecked %#08x, free %#08x)\n",
413730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
414730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
415730554d9SArtem B. Bityutskiy 			}
416730554d9SArtem B. Bityutskiy 		}
417730554d9SArtem B. Bityutskiy 	}
418730554d9SArtem B. Bityutskiy 
419730554d9SArtem B. Bityutskiy 	if (list_empty(&c->bad_used_list)) {
420730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "bad_used_list: empty\n");
421730554d9SArtem B. Bityutskiy 	} else {
422730554d9SArtem B. Bityutskiy 		struct list_head *this;
423730554d9SArtem B. Bityutskiy 
424730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->bad_used_list) {
425730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
426730554d9SArtem B. Bityutskiy 
427730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
428730554d9SArtem B. Bityutskiy 				printk(KERN_DEBUG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
429730554d9SArtem B. Bityutskiy 						"unchecked %#08x, free %#08x)\n",
430730554d9SArtem B. Bityutskiy 						jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
431730554d9SArtem B. Bityutskiy 						jeb->unchecked_size, jeb->free_size);
432730554d9SArtem B. Bityutskiy 			}
433730554d9SArtem B. Bityutskiy 		}
434730554d9SArtem B. Bityutskiy 	}
435730554d9SArtem B. Bityutskiy }
436730554d9SArtem B. Bityutskiy 
437730554d9SArtem B. Bityutskiy void
438730554d9SArtem B. Bityutskiy jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
439730554d9SArtem B. Bityutskiy {
440730554d9SArtem B. Bityutskiy 	struct jffs2_node_frag *this = frag_first(&f->fragtree);
441730554d9SArtem B. Bityutskiy 	uint32_t lastofs = 0;
442730554d9SArtem B. Bityutskiy 	int buggy = 0;
443730554d9SArtem B. Bityutskiy 
444730554d9SArtem B. Bityutskiy 	printk(KERN_DEBUG "inode is ino #%u\n", f->inocache->ino);
445730554d9SArtem B. Bityutskiy 	while(this) {
446730554d9SArtem B. Bityutskiy 		if (this->node)
447730554d9SArtem B. Bityutskiy 			printk(KERN_DEBUG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
448730554d9SArtem B. Bityutskiy 					"right (%p), parent (%p)\n",
449730554d9SArtem B. Bityutskiy 					this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
450730554d9SArtem B. Bityutskiy 					ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
451730554d9SArtem B. Bityutskiy 					frag_parent(this));
452730554d9SArtem B. Bityutskiy 		else
453730554d9SArtem B. Bityutskiy 			printk(KERN_DEBUG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
454730554d9SArtem B. Bityutskiy 					this->ofs, this->ofs+this->size, this, frag_left(this),
455730554d9SArtem B. Bityutskiy 					frag_right(this), frag_parent(this));
456730554d9SArtem B. Bityutskiy 		if (this->ofs != lastofs)
457730554d9SArtem B. Bityutskiy 			buggy = 1;
458730554d9SArtem B. Bityutskiy 		lastofs = this->ofs + this->size;
459730554d9SArtem B. Bityutskiy 		this = frag_next(this);
460730554d9SArtem B. Bityutskiy 	}
461730554d9SArtem B. Bityutskiy 
462730554d9SArtem B. Bityutskiy 	if (f->metadata)
463730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
464730554d9SArtem B. Bityutskiy 
465730554d9SArtem B. Bityutskiy 	if (buggy) {
466730554d9SArtem B. Bityutskiy 		printk(KERN_ERR "Error! %s(): Frag tree got a hole in it\n", __FUNCTION__);
467730554d9SArtem B. Bityutskiy 		BUG();
468730554d9SArtem B. Bityutskiy 	}
469730554d9SArtem B. Bityutskiy }
470730554d9SArtem B. Bityutskiy 
471730554d9SArtem B. Bityutskiy #define JFFS3_BUFDUMP_BYTES_PER_LINE	8
472730554d9SArtem B. Bityutskiy void
473730554d9SArtem B. Bityutskiy jffs2_dbg_dump_buffer(char *buf, int len, uint32_t offs)
474730554d9SArtem B. Bityutskiy {
475730554d9SArtem B. Bityutskiy 	int i = 0;
476730554d9SArtem B. Bityutskiy 	int skip = offs & ~(JFFS3_BUFDUMP_BYTES_PER_LINE - 1);
477730554d9SArtem B. Bityutskiy 
478730554d9SArtem B. Bityutskiy 	while (i < len) {
479730554d9SArtem B. Bityutskiy 		int j = 0;
480730554d9SArtem B. Bityutskiy 
481730554d9SArtem B. Bityutskiy 		printk(KERN_DEBUG "0x#x: \n");
482730554d9SArtem B. Bityutskiy 		while (skip) {
483730554d9SArtem B. Bityutskiy 			printk("   ");
484730554d9SArtem B. Bityutskiy 			skip -= 1;
485730554d9SArtem B. Bityutskiy 		}
486730554d9SArtem B. Bityutskiy 
487730554d9SArtem B. Bityutskiy 		while (j < JFFS3_BUFDUMP_BYTES_PER_LINE) {
488730554d9SArtem B. Bityutskiy 			if (i + j < len)
489730554d9SArtem B. Bityutskiy 				printk(" %#02x", buf[i + j++]);
490730554d9SArtem B. Bityutskiy 		}
491730554d9SArtem B. Bityutskiy 
492730554d9SArtem B. Bityutskiy 		i += JFFS3_BUFDUMP_BYTES_PER_LINE;
493730554d9SArtem B. Bityutskiy 	}
494730554d9SArtem B. Bityutskiy }
495730554d9SArtem B. Bityutskiy #endif /* JFFS2_PARANOIA_CHECKS || CONFIG_JFFS2_FS_DEBUG > 0 */
496