xref: /openbmc/linux/fs/jffs2/debug.c (revision 737b7661)
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  *
10737b7661SAndrew Lunn  * $Id: debug.c,v 1.8 2005/07/30 15:27:05 lunn Exp $
11730554d9SArtem B. Bityutskiy  *
12730554d9SArtem B. Bityutskiy  */
13730554d9SArtem B. Bityutskiy #include <linux/kernel.h>
14737b7661SAndrew Lunn #include <linux/types.h>
15730554d9SArtem B. Bityutskiy #include <linux/pagemap.h>
16e0c8e42fSArtem B. Bityutskiy #include <linux/crc32.h>
17e0c8e42fSArtem B. Bityutskiy #include <linux/jffs2.h>
18730554d9SArtem B. Bityutskiy #include "nodelist.h"
19730554d9SArtem B. Bityutskiy #include "debug.h"
20730554d9SArtem B. Bityutskiy 
21730554d9SArtem B. Bityutskiy #ifdef JFFS2_DBG_PARANOIA_CHECKS
22e0c8e42fSArtem B. Bityutskiy /*
23e0c8e42fSArtem B. Bityutskiy  * Check the fragtree.
24e0c8e42fSArtem B. Bityutskiy  */
25e0c8e42fSArtem B. Bityutskiy void
26e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
27e0c8e42fSArtem B. Bityutskiy {
28e0c8e42fSArtem B. Bityutskiy 	down(&f->sem);
29e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_fragtree_paranoia_check_nolock(f);
30e0c8e42fSArtem B. Bityutskiy 	up(&f->sem);
31e0c8e42fSArtem B. Bityutskiy }
32730554d9SArtem B. Bityutskiy 
33730554d9SArtem B. Bityutskiy void
34e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
35730554d9SArtem B. Bityutskiy {
36730554d9SArtem B. Bityutskiy 	struct jffs2_node_frag *frag;
37730554d9SArtem B. Bityutskiy 	int bitched = 0;
38730554d9SArtem B. Bityutskiy 
39730554d9SArtem B. Bityutskiy 	for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
40730554d9SArtem B. Bityutskiy 		struct jffs2_full_dnode *fn = frag->node;
41730554d9SArtem B. Bityutskiy 
42730554d9SArtem B. Bityutskiy 		if (!fn || !fn->raw)
43730554d9SArtem B. Bityutskiy 			continue;
44730554d9SArtem B. Bityutskiy 
45730554d9SArtem B. Bityutskiy 		if (ref_flags(fn->raw) == REF_PRISTINE) {
46730554d9SArtem B. Bityutskiy 			if (fn->frags > 1) {
47e0c8e42fSArtem B. Bityutskiy 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
48730554d9SArtem B. Bityutskiy 						ref_offset(fn->raw), fn->frags);
49730554d9SArtem B. Bityutskiy 				bitched = 1;
50730554d9SArtem B. Bityutskiy 			}
51730554d9SArtem B. Bityutskiy 
52730554d9SArtem B. Bityutskiy 			/* A hole node which isn't multi-page should be garbage-collected
53730554d9SArtem B. Bityutskiy 			   and merged anyway, so we just check for the frag size here,
54730554d9SArtem B. Bityutskiy 			   rather than mucking around with actually reading the node
55730554d9SArtem B. Bityutskiy 			   and checking the compression type, which is the real way
56730554d9SArtem B. Bityutskiy 			   to tell a hole node. */
57730554d9SArtem B. Bityutskiy 			if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
58730554d9SArtem B. Bityutskiy 					&& frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
59e0c8e42fSArtem B. Bityutskiy 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag "
60e0c8e42fSArtem B. Bityutskiy 						"in the same page. Tell dwmw2.\n", ref_offset(fn->raw));
61730554d9SArtem B. Bityutskiy 				bitched = 1;
62730554d9SArtem B. Bityutskiy 			}
63730554d9SArtem B. Bityutskiy 
64730554d9SArtem B. Bityutskiy 			if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
65730554d9SArtem B. Bityutskiy 					&& frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
66e0c8e42fSArtem B. Bityutskiy 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
67e0c8e42fSArtem B. Bityutskiy 						"non-hole frag in the same page. Tell dwmw2.\n",
68730554d9SArtem B. Bityutskiy 					       ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
69730554d9SArtem B. Bityutskiy 				bitched = 1;
70730554d9SArtem B. Bityutskiy 			}
71730554d9SArtem B. Bityutskiy 		}
72730554d9SArtem B. Bityutskiy 	}
73730554d9SArtem B. Bityutskiy 
74730554d9SArtem B. Bityutskiy 	if (bitched) {
75e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("fragtree is corrupted.\n");
76e0c8e42fSArtem B. Bityutskiy 		__jffs2_dbg_dump_fragtree_nolock(f);
77730554d9SArtem B. Bityutskiy 		BUG();
78730554d9SArtem B. Bityutskiy 	}
79730554d9SArtem B. Bityutskiy }
80730554d9SArtem B. Bityutskiy 
81730554d9SArtem B. Bityutskiy /*
82730554d9SArtem B. Bityutskiy  * Check if the flash contains all 0xFF before we start writing.
83730554d9SArtem B. Bityutskiy  */
84730554d9SArtem B. Bityutskiy void
85e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
86e0c8e42fSArtem B. Bityutskiy 				    uint32_t ofs, int len)
87730554d9SArtem B. Bityutskiy {
88730554d9SArtem B. Bityutskiy 	size_t retlen;
89730554d9SArtem B. Bityutskiy 	int ret, i;
90730554d9SArtem B. Bityutskiy 	unsigned char *buf;
91730554d9SArtem B. Bityutskiy 
92730554d9SArtem B. Bityutskiy 	buf = kmalloc(len, GFP_KERNEL);
93730554d9SArtem B. Bityutskiy 	if (!buf)
94730554d9SArtem B. Bityutskiy 		return;
95730554d9SArtem B. Bityutskiy 
96730554d9SArtem B. Bityutskiy 	ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
97730554d9SArtem B. Bityutskiy 	if (ret || (retlen != len)) {
98e0c8e42fSArtem B. Bityutskiy 		JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
99e0c8e42fSArtem B. Bityutskiy 				len, ret, retlen);
100730554d9SArtem B. Bityutskiy 		kfree(buf);
101730554d9SArtem B. Bityutskiy 		return;
102730554d9SArtem B. Bityutskiy 	}
103730554d9SArtem B. Bityutskiy 
104730554d9SArtem B. Bityutskiy 	ret = 0;
105730554d9SArtem B. Bityutskiy 	for (i = 0; i < len; i++)
106730554d9SArtem B. Bityutskiy 		if (buf[i] != 0xff)
107730554d9SArtem B. Bityutskiy 			ret = 1;
108730554d9SArtem B. Bityutskiy 
109730554d9SArtem B. Bityutskiy 	if (ret) {
110e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data "
111e0c8e42fSArtem B. Bityutskiy 			"already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i);
112e0c8e42fSArtem B. Bityutskiy 		__jffs2_dbg_dump_buffer(buf, len, ofs);
113730554d9SArtem B. Bityutskiy 		kfree(buf);
114730554d9SArtem B. Bityutskiy 		BUG();
115730554d9SArtem B. Bityutskiy 	}
116730554d9SArtem B. Bityutskiy 
117730554d9SArtem B. Bityutskiy 	kfree(buf);
118730554d9SArtem B. Bityutskiy }
119730554d9SArtem B. Bityutskiy 
120730554d9SArtem B. Bityutskiy /*
121730554d9SArtem B. Bityutskiy  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
122730554d9SArtem B. Bityutskiy  */
123730554d9SArtem B. Bityutskiy void
124e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
125e0c8e42fSArtem B. Bityutskiy 				struct jffs2_eraseblock *jeb)
126e0c8e42fSArtem B. Bityutskiy {
127e0c8e42fSArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
128e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
129e0c8e42fSArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
130e0c8e42fSArtem B. Bityutskiy }
131e0c8e42fSArtem B. Bityutskiy 
132e0c8e42fSArtem B. Bityutskiy void
133e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
134e0c8e42fSArtem B. Bityutskiy 				       struct jffs2_eraseblock *jeb)
135730554d9SArtem B. Bityutskiy {
136730554d9SArtem B. Bityutskiy 	uint32_t my_used_size = 0;
137730554d9SArtem B. Bityutskiy 	uint32_t my_unchecked_size = 0;
138730554d9SArtem B. Bityutskiy 	uint32_t my_dirty_size = 0;
139730554d9SArtem B. Bityutskiy 	struct jffs2_raw_node_ref *ref2 = jeb->first_node;
140730554d9SArtem B. Bityutskiy 
141730554d9SArtem B. Bityutskiy 	while (ref2) {
142730554d9SArtem B. Bityutskiy 		uint32_t totlen = ref_totlen(c, jeb, ref2);
143730554d9SArtem B. Bityutskiy 
144730554d9SArtem B. Bityutskiy 		if (ref2->flash_offset < jeb->offset ||
145730554d9SArtem B. Bityutskiy 				ref2->flash_offset > jeb->offset + c->sector_size) {
146e0c8e42fSArtem B. Bityutskiy 			JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
147730554d9SArtem B. Bityutskiy 				ref_offset(ref2), jeb->offset);
148e0c8e42fSArtem B. Bityutskiy 			goto error;
149730554d9SArtem B. Bityutskiy 
150730554d9SArtem B. Bityutskiy 		}
151730554d9SArtem B. Bityutskiy 		if (ref_flags(ref2) == REF_UNCHECKED)
152730554d9SArtem B. Bityutskiy 			my_unchecked_size += totlen;
153730554d9SArtem B. Bityutskiy 		else if (!ref_obsolete(ref2))
154730554d9SArtem B. Bityutskiy 			my_used_size += totlen;
155730554d9SArtem B. Bityutskiy 		else
156730554d9SArtem B. Bityutskiy 			my_dirty_size += totlen;
157730554d9SArtem B. Bityutskiy 
158730554d9SArtem B. Bityutskiy 		if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
159e0c8e42fSArtem B. Bityutskiy 			JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
160e0c8e42fSArtem B. Bityutskiy 				"last_node is at %#08x (mem %p).\n",
161730554d9SArtem B. Bityutskiy 				ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
162730554d9SArtem B. Bityutskiy 				ref_offset(jeb->last_node), jeb->last_node);
163e0c8e42fSArtem B. Bityutskiy 			goto error;
164730554d9SArtem B. Bityutskiy 		}
165730554d9SArtem B. Bityutskiy 		ref2 = ref2->next_phys;
166730554d9SArtem B. Bityutskiy 	}
167730554d9SArtem B. Bityutskiy 
168730554d9SArtem B. Bityutskiy 	if (my_used_size != jeb->used_size) {
169e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
170730554d9SArtem B. Bityutskiy 			my_used_size, jeb->used_size);
171e0c8e42fSArtem B. Bityutskiy 		goto error;
172730554d9SArtem B. Bityutskiy 	}
173730554d9SArtem B. Bityutskiy 
174730554d9SArtem B. Bityutskiy 	if (my_unchecked_size != jeb->unchecked_size) {
175e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
176730554d9SArtem B. Bityutskiy 			my_unchecked_size, jeb->unchecked_size);
177e0c8e42fSArtem B. Bityutskiy 		goto error;
178730554d9SArtem B. Bityutskiy 	}
179730554d9SArtem B. Bityutskiy 
180e0c8e42fSArtem B. Bityutskiy #if 0
181e0c8e42fSArtem B. Bityutskiy 	/* This should work when we implement ref->__totlen elemination */
182730554d9SArtem B. Bityutskiy 	if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
183e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
184730554d9SArtem B. Bityutskiy 			my_dirty_size, jeb->dirty_size + jeb->wasted_size);
185e0c8e42fSArtem B. Bityutskiy 		goto error;
186730554d9SArtem B. Bityutskiy 	}
187730554d9SArtem B. Bityutskiy 
188730554d9SArtem B. Bityutskiy 	if (jeb->free_size == 0
189730554d9SArtem B. Bityutskiy 		&& my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
190e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
191730554d9SArtem B. Bityutskiy 			my_used_size + my_unchecked_size + my_dirty_size,
192730554d9SArtem B. Bityutskiy 			c->sector_size);
193e0c8e42fSArtem B. Bityutskiy 		goto error;
194730554d9SArtem B. Bityutskiy 	}
195e0c8e42fSArtem B. Bityutskiy #endif
196730554d9SArtem B. Bityutskiy 
197e0c8e42fSArtem B. Bityutskiy 	return;
198e0c8e42fSArtem B. Bityutskiy 
199e0c8e42fSArtem B. Bityutskiy error:
200e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
201e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_jeb_nolock(jeb);
202e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_block_lists_nolock(c);
203e0c8e42fSArtem B. Bityutskiy 	BUG();
204e0c8e42fSArtem B. Bityutskiy 
205e0c8e42fSArtem B. Bityutskiy }
206e0c8e42fSArtem B. Bityutskiy #endif /* JFFS2_DBG_PARANOIA_CHECKS */
207e0c8e42fSArtem B. Bityutskiy 
208e0c8e42fSArtem B. Bityutskiy #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
209730554d9SArtem B. Bityutskiy /*
210730554d9SArtem B. Bityutskiy  * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
211730554d9SArtem B. Bityutskiy  */
212730554d9SArtem B. Bityutskiy void
213e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
214e0c8e42fSArtem B. Bityutskiy 			   struct jffs2_eraseblock *jeb)
215e0c8e42fSArtem B. Bityutskiy {
216e0c8e42fSArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
217e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
218e0c8e42fSArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
219e0c8e42fSArtem B. Bityutskiy }
220e0c8e42fSArtem B. Bityutskiy 
221e0c8e42fSArtem B. Bityutskiy void
222e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
223e0c8e42fSArtem B. Bityutskiy 				  struct jffs2_eraseblock *jeb)
224730554d9SArtem B. Bityutskiy {
225730554d9SArtem B. Bityutskiy 	struct jffs2_raw_node_ref *ref;
226730554d9SArtem B. Bityutskiy 	int i = 0;
227730554d9SArtem B. Bityutskiy 
228e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset);
229730554d9SArtem B. Bityutskiy 	if (!jeb->first_node) {
230e0c8e42fSArtem B. Bityutskiy 		JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset);
231730554d9SArtem B. Bityutskiy 		return;
232730554d9SArtem B. Bityutskiy 	}
233730554d9SArtem B. Bityutskiy 
234e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL);
235730554d9SArtem B. Bityutskiy 	for (ref = jeb->first_node; ; ref = ref->next_phys) {
236730554d9SArtem B. Bityutskiy 		printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
237730554d9SArtem B. Bityutskiy 		if (ref->next_phys)
238730554d9SArtem B. Bityutskiy 			printk("->");
239730554d9SArtem B. Bityutskiy 		else
240730554d9SArtem B. Bityutskiy 			break;
241730554d9SArtem B. Bityutskiy 		if (++i == 4) {
242730554d9SArtem B. Bityutskiy 			i = 0;
243e0c8e42fSArtem B. Bityutskiy 			printk("\n" JFFS2_DBG_LVL);
244730554d9SArtem B. Bityutskiy 		}
245730554d9SArtem B. Bityutskiy 	}
246730554d9SArtem B. Bityutskiy 	printk("\n");
247730554d9SArtem B. Bityutskiy }
248730554d9SArtem B. Bityutskiy 
249e0c8e42fSArtem B. Bityutskiy /*
250e0c8e42fSArtem B. Bityutskiy  * Dump an eraseblock's space accounting.
251e0c8e42fSArtem B. Bityutskiy  */
252730554d9SArtem B. Bityutskiy void
253e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
254730554d9SArtem B. Bityutskiy {
255e0c8e42fSArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
256e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_jeb_nolock(jeb);
257e0c8e42fSArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
258e0c8e42fSArtem B. Bityutskiy }
259e0c8e42fSArtem B. Bityutskiy 
260e0c8e42fSArtem B. Bityutskiy void
261e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
262e0c8e42fSArtem B. Bityutskiy {
263e0c8e42fSArtem B. Bityutskiy 	if (!jeb)
264e0c8e42fSArtem B. Bityutskiy 		return;
265e0c8e42fSArtem B. Bityutskiy 
266e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n",
267e0c8e42fSArtem B. Bityutskiy 			jeb->offset);
268e0c8e42fSArtem B. Bityutskiy 
269e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "used_size: %#08x\n",	jeb->used_size);
270e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "dirty_size: %#08x\n",	jeb->dirty_size);
271e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "wasted_size: %#08x\n",	jeb->wasted_size);
272e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n",	jeb->unchecked_size);
273e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "free_size: %#08x\n",	jeb->free_size);
274e0c8e42fSArtem B. Bityutskiy }
275e0c8e42fSArtem B. Bityutskiy 
276e0c8e42fSArtem B. Bityutskiy void
277e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
278e0c8e42fSArtem B. Bityutskiy {
279e0c8e42fSArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
280e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_block_lists_nolock(c);
281e0c8e42fSArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
282e0c8e42fSArtem B. Bityutskiy }
283e0c8e42fSArtem B. Bityutskiy 
284e0c8e42fSArtem B. Bityutskiy void
285e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
286e0c8e42fSArtem B. Bityutskiy {
287e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump JFFS2 blocks lists:\n");
288e0c8e42fSArtem B. Bityutskiy 
289e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "flash_size: %#08x\n",	c->flash_size);
290e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "used_size: %#08x\n",	c->used_size);
291e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "dirty_size: %#08x\n",	c->dirty_size);
292e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "wasted_size: %#08x\n",	c->wasted_size);
293e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n",	c->unchecked_size);
294e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "free_size: %#08x\n",	c->free_size);
295e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "erasing_size: %#08x\n",	c->erasing_size);
296e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "bad_size: %#08x\n",	c->bad_size);
297e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "sector_size: %#08x\n",	c->sector_size);
298e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n",
299730554d9SArtem B. Bityutskiy 				c->sector_size * c->resv_blocks_write);
300730554d9SArtem B. Bityutskiy 
301730554d9SArtem B. Bityutskiy 	if (c->nextblock)
302e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
303730554d9SArtem B. Bityutskiy 			"unchecked %#08x, free %#08x)\n",
304730554d9SArtem B. Bityutskiy 			c->nextblock->offset, c->nextblock->used_size,
305730554d9SArtem B. Bityutskiy 			c->nextblock->dirty_size, c->nextblock->wasted_size,
306730554d9SArtem B. Bityutskiy 			c->nextblock->unchecked_size, c->nextblock->free_size);
307730554d9SArtem B. Bityutskiy 	else
308e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "nextblock: NULL\n");
309730554d9SArtem B. Bityutskiy 
310730554d9SArtem B. Bityutskiy 	if (c->gcblock)
311e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
312730554d9SArtem B. Bityutskiy 			"unchecked %#08x, free %#08x)\n",
313730554d9SArtem B. Bityutskiy 			c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
314730554d9SArtem B. Bityutskiy 			c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
315730554d9SArtem B. Bityutskiy 	else
316e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "gcblock: NULL\n");
317730554d9SArtem B. Bityutskiy 
318730554d9SArtem B. Bityutskiy 	if (list_empty(&c->clean_list)) {
319e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "clean_list: empty\n");
320730554d9SArtem B. Bityutskiy 	} else {
321730554d9SArtem B. Bityutskiy 		struct list_head *this;
322730554d9SArtem B. Bityutskiy 		int numblocks = 0;
323730554d9SArtem B. Bityutskiy 		uint32_t dirty = 0;
324730554d9SArtem B. Bityutskiy 
325730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->clean_list) {
326730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
327730554d9SArtem B. Bityutskiy 			numblocks ++;
328730554d9SArtem B. Bityutskiy 			dirty += jeb->wasted_size;
329730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
330e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
331730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
332730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
333730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
334730554d9SArtem B. Bityutskiy 			}
335730554d9SArtem B. Bityutskiy 		}
336730554d9SArtem B. Bityutskiy 
337e0c8e42fSArtem B. Bityutskiy 		printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
338730554d9SArtem B. Bityutskiy 			numblocks, dirty, dirty / numblocks);
339730554d9SArtem B. Bityutskiy 	}
340730554d9SArtem B. Bityutskiy 
341730554d9SArtem B. Bityutskiy 	if (list_empty(&c->very_dirty_list)) {
342e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "very_dirty_list: empty\n");
343730554d9SArtem B. Bityutskiy 	} else {
344730554d9SArtem B. Bityutskiy 		struct list_head *this;
345730554d9SArtem B. Bityutskiy 		int numblocks = 0;
346730554d9SArtem B. Bityutskiy 		uint32_t dirty = 0;
347730554d9SArtem B. Bityutskiy 
348730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->very_dirty_list) {
349730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
350730554d9SArtem B. Bityutskiy 
351730554d9SArtem B. Bityutskiy 			numblocks ++;
352730554d9SArtem B. Bityutskiy 			dirty += jeb->dirty_size;
353730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
354e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
355730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
356730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
357730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
358730554d9SArtem B. Bityutskiy 			}
359730554d9SArtem B. Bityutskiy 		}
360730554d9SArtem B. Bityutskiy 
361e0c8e42fSArtem B. Bityutskiy 		printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
362730554d9SArtem B. Bityutskiy 			numblocks, dirty, dirty / numblocks);
363730554d9SArtem B. Bityutskiy 	}
364730554d9SArtem B. Bityutskiy 
365730554d9SArtem B. Bityutskiy 	if (list_empty(&c->dirty_list)) {
366e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "dirty_list: empty\n");
367730554d9SArtem B. Bityutskiy 	} else {
368730554d9SArtem B. Bityutskiy 		struct list_head *this;
369730554d9SArtem B. Bityutskiy 		int numblocks = 0;
370730554d9SArtem B. Bityutskiy 		uint32_t dirty = 0;
371730554d9SArtem B. Bityutskiy 
372730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->dirty_list) {
373730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
374730554d9SArtem B. Bityutskiy 
375730554d9SArtem B. Bityutskiy 			numblocks ++;
376730554d9SArtem B. Bityutskiy 			dirty += jeb->dirty_size;
377730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
378e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
379730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
380730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
381730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
382730554d9SArtem B. Bityutskiy 			}
383730554d9SArtem B. Bityutskiy 		}
384730554d9SArtem B. Bityutskiy 
385e0c8e42fSArtem B. Bityutskiy 		printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n",
386730554d9SArtem B. Bityutskiy 			numblocks, dirty, dirty / numblocks);
387730554d9SArtem B. Bityutskiy 	}
388730554d9SArtem B. Bityutskiy 
389730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erasable_list)) {
390e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "erasable_list: empty\n");
391730554d9SArtem B. Bityutskiy 	} else {
392730554d9SArtem B. Bityutskiy 		struct list_head *this;
393730554d9SArtem B. Bityutskiy 
394730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erasable_list) {
395730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
396730554d9SArtem B. Bityutskiy 
397730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
398e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
399730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
400730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
401730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
402730554d9SArtem B. Bityutskiy 			}
403730554d9SArtem B. Bityutskiy 		}
404730554d9SArtem B. Bityutskiy 	}
405730554d9SArtem B. Bityutskiy 
406730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erasing_list)) {
407e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "erasing_list: empty\n");
408730554d9SArtem B. Bityutskiy 	} else {
409730554d9SArtem B. Bityutskiy 		struct list_head *this;
410730554d9SArtem B. Bityutskiy 
411730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erasing_list) {
412730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
413730554d9SArtem B. Bityutskiy 
414730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
415e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
416730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
417730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
418730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
419730554d9SArtem B. Bityutskiy 			}
420730554d9SArtem B. Bityutskiy 		}
421730554d9SArtem B. Bityutskiy 	}
422730554d9SArtem B. Bityutskiy 
423730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erase_pending_list)) {
424e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "erase_pending_list: empty\n");
425730554d9SArtem B. Bityutskiy 	} else {
426730554d9SArtem B. Bityutskiy 		struct list_head *this;
427730554d9SArtem B. Bityutskiy 
428730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erase_pending_list) {
429730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
430730554d9SArtem B. Bityutskiy 
431730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
432e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
433730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
434730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
435730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
436730554d9SArtem B. Bityutskiy 			}
437730554d9SArtem B. Bityutskiy 		}
438730554d9SArtem B. Bityutskiy 	}
439730554d9SArtem B. Bityutskiy 
440730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erasable_pending_wbuf_list)) {
441e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n");
442730554d9SArtem B. Bityutskiy 	} else {
443730554d9SArtem B. Bityutskiy 		struct list_head *this;
444730554d9SArtem B. Bityutskiy 
445730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erasable_pending_wbuf_list) {
446730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
447730554d9SArtem B. Bityutskiy 
448730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
449e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
450730554d9SArtem B. Bityutskiy 					"wasted %#08x, unchecked %#08x, free %#08x)\n",
451730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
452730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
453730554d9SArtem B. Bityutskiy 			}
454730554d9SArtem B. Bityutskiy 		}
455730554d9SArtem B. Bityutskiy 	}
456730554d9SArtem B. Bityutskiy 
457730554d9SArtem B. Bityutskiy 	if (list_empty(&c->free_list)) {
458e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "free_list: empty\n");
459730554d9SArtem B. Bityutskiy 	} else {
460730554d9SArtem B. Bityutskiy 		struct list_head *this;
461730554d9SArtem B. Bityutskiy 
462730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->free_list) {
463730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
464730554d9SArtem B. Bityutskiy 
465730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
466e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
467730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
468730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
469730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
470730554d9SArtem B. Bityutskiy 			}
471730554d9SArtem B. Bityutskiy 		}
472730554d9SArtem B. Bityutskiy 	}
473730554d9SArtem B. Bityutskiy 
474730554d9SArtem B. Bityutskiy 	if (list_empty(&c->bad_list)) {
475e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "bad_list: empty\n");
476730554d9SArtem B. Bityutskiy 	} else {
477730554d9SArtem B. Bityutskiy 		struct list_head *this;
478730554d9SArtem B. Bityutskiy 
479730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->bad_list) {
480730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
481730554d9SArtem B. Bityutskiy 
482730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
483e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
484730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
485730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
486730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
487730554d9SArtem B. Bityutskiy 			}
488730554d9SArtem B. Bityutskiy 		}
489730554d9SArtem B. Bityutskiy 	}
490730554d9SArtem B. Bityutskiy 
491730554d9SArtem B. Bityutskiy 	if (list_empty(&c->bad_used_list)) {
492e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "bad_used_list: empty\n");
493730554d9SArtem B. Bityutskiy 	} else {
494730554d9SArtem B. Bityutskiy 		struct list_head *this;
495730554d9SArtem B. Bityutskiy 
496730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->bad_used_list) {
497730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
498730554d9SArtem B. Bityutskiy 
499730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
500e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
501730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
502730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
503730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
504730554d9SArtem B. Bityutskiy 			}
505730554d9SArtem B. Bityutskiy 		}
506730554d9SArtem B. Bityutskiy 	}
507730554d9SArtem B. Bityutskiy }
508730554d9SArtem B. Bityutskiy 
509730554d9SArtem B. Bityutskiy void
510e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
511e0c8e42fSArtem B. Bityutskiy {
512e0c8e42fSArtem B. Bityutskiy 	down(&f->sem);
513e0c8e42fSArtem B. Bityutskiy 	jffs2_dbg_dump_fragtree_nolock(f);
514e0c8e42fSArtem B. Bityutskiy 	up(&f->sem);
515e0c8e42fSArtem B. Bityutskiy }
516e0c8e42fSArtem B. Bityutskiy 
517e0c8e42fSArtem B. Bityutskiy void
518e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
519730554d9SArtem B. Bityutskiy {
520730554d9SArtem B. Bityutskiy 	struct jffs2_node_frag *this = frag_first(&f->fragtree);
521730554d9SArtem B. Bityutskiy 	uint32_t lastofs = 0;
522730554d9SArtem B. Bityutskiy 	int buggy = 0;
523730554d9SArtem B. Bityutskiy 
524e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino);
525730554d9SArtem B. Bityutskiy 	while(this) {
526730554d9SArtem B. Bityutskiy 		if (this->node)
527e0c8e42fSArtem B. Bityutskiy 			printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
528730554d9SArtem B. Bityutskiy 				"right (%p), parent (%p)\n",
529730554d9SArtem B. Bityutskiy 				this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
530730554d9SArtem B. Bityutskiy 				ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
531730554d9SArtem B. Bityutskiy 				frag_parent(this));
532730554d9SArtem B. Bityutskiy 		else
533e0c8e42fSArtem B. Bityutskiy 			printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
534730554d9SArtem B. Bityutskiy 				this->ofs, this->ofs+this->size, this, frag_left(this),
535730554d9SArtem B. Bityutskiy 				frag_right(this), frag_parent(this));
536730554d9SArtem B. Bityutskiy 		if (this->ofs != lastofs)
537730554d9SArtem B. Bityutskiy 			buggy = 1;
538730554d9SArtem B. Bityutskiy 		lastofs = this->ofs + this->size;
539730554d9SArtem B. Bityutskiy 		this = frag_next(this);
540730554d9SArtem B. Bityutskiy 	}
541730554d9SArtem B. Bityutskiy 
542730554d9SArtem B. Bityutskiy 	if (f->metadata)
543e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
544730554d9SArtem B. Bityutskiy 
545730554d9SArtem B. Bityutskiy 	if (buggy) {
546e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("frag tree got a hole in it.\n");
547730554d9SArtem B. Bityutskiy 		BUG();
548730554d9SArtem B. Bityutskiy 	}
549730554d9SArtem B. Bityutskiy }
550730554d9SArtem B. Bityutskiy 
551e0c8e42fSArtem B. Bityutskiy #define JFFS2_BUFDUMP_BYTES_PER_LINE	32
552730554d9SArtem B. Bityutskiy void
553e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
554730554d9SArtem B. Bityutskiy {
555e0c8e42fSArtem B. Bityutskiy 	int skip;
556e0c8e42fSArtem B. Bityutskiy 	int i;
557e0c8e42fSArtem B. Bityutskiy 
558e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n",
559e0c8e42fSArtem B. Bityutskiy 		offs, offs + len, len);
560e0c8e42fSArtem B. Bityutskiy 	i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
561e0c8e42fSArtem B. Bityutskiy 	offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
562e0c8e42fSArtem B. Bityutskiy 
563e0c8e42fSArtem B. Bityutskiy 	if (skip != 0)
564e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "%#08x: ", offs);
565e0c8e42fSArtem B. Bityutskiy 
566e0c8e42fSArtem B. Bityutskiy 	while (skip--)
567e0c8e42fSArtem B. Bityutskiy 		printk("   ");
568730554d9SArtem B. Bityutskiy 
569730554d9SArtem B. Bityutskiy 	while (i < len) {
570e0c8e42fSArtem B. Bityutskiy 		if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
571e0c8e42fSArtem B. Bityutskiy 			if (i != 0)
572e0c8e42fSArtem B. Bityutskiy 				printk("\n");
573e0c8e42fSArtem B. Bityutskiy 			offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
574e0c8e42fSArtem B. Bityutskiy 			printk(JFFS2_DBG_LVL "%0#8x: ", offs);
575730554d9SArtem B. Bityutskiy 		}
576730554d9SArtem B. Bityutskiy 
577e0c8e42fSArtem B. Bityutskiy 		printk("%02x ", buf[i]);
578e0c8e42fSArtem B. Bityutskiy 
579e0c8e42fSArtem B. Bityutskiy 		i += 1;
580730554d9SArtem B. Bityutskiy 	}
581730554d9SArtem B. Bityutskiy 
582e0c8e42fSArtem B. Bityutskiy 	printk("\n");
583e0c8e42fSArtem B. Bityutskiy }
584e0c8e42fSArtem B. Bityutskiy 
585e0c8e42fSArtem B. Bityutskiy /*
586e0c8e42fSArtem B. Bityutskiy  * Dump a JFFS2 node.
587e0c8e42fSArtem B. Bityutskiy  */
588e0c8e42fSArtem B. Bityutskiy void
589e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
590e0c8e42fSArtem B. Bityutskiy {
591e0c8e42fSArtem B. Bityutskiy 	union jffs2_node_union node;
592e0c8e42fSArtem B. Bityutskiy 	int len = sizeof(union jffs2_node_union);
593e0c8e42fSArtem B. Bityutskiy 	size_t retlen;
594e0c8e42fSArtem B. Bityutskiy 	uint32_t crc;
595e0c8e42fSArtem B. Bityutskiy 	int ret;
596e0c8e42fSArtem B. Bityutskiy 
597e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump node at offset %#08x.\n", ofs);
598e0c8e42fSArtem B. Bityutskiy 
599e0c8e42fSArtem B. Bityutskiy 	ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
600e0c8e42fSArtem B. Bityutskiy 	if (ret || (retlen != len)) {
601e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
602e0c8e42fSArtem B. Bityutskiy 			len, ret, retlen);
603e0c8e42fSArtem B. Bityutskiy 		return;
604e0c8e42fSArtem B. Bityutskiy 	}
605e0c8e42fSArtem B. Bityutskiy 
606e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "magic:\t%#04x\n",
607e0c8e42fSArtem B. Bityutskiy 		je16_to_cpu(node.u.magic));
608e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n",
609e0c8e42fSArtem B. Bityutskiy 		je16_to_cpu(node.u.nodetype));
610e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "totlen:\t%#08x\n",
611e0c8e42fSArtem B. Bityutskiy 		je32_to_cpu(node.u.totlen));
612e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n",
613e0c8e42fSArtem B. Bityutskiy 		je32_to_cpu(node.u.hdr_crc));
614e0c8e42fSArtem B. Bityutskiy 
615e0c8e42fSArtem B. Bityutskiy 	crc = crc32(0, &node.u, sizeof(node.u) - 4);
616e0c8e42fSArtem B. Bityutskiy 	if (crc != je32_to_cpu(node.u.hdr_crc)) {
617e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("wrong common header CRC.\n");
618e0c8e42fSArtem B. Bityutskiy 		return;
619e0c8e42fSArtem B. Bityutskiy 	}
620e0c8e42fSArtem B. Bityutskiy 
621e0c8e42fSArtem B. Bityutskiy 	if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
622e0c8e42fSArtem B. Bityutskiy 		je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
623e0c8e42fSArtem B. Bityutskiy 	{
624e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
625e0c8e42fSArtem B. Bityutskiy 			je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
626e0c8e42fSArtem B. Bityutskiy 		return;
627e0c8e42fSArtem B. Bityutskiy 	}
628e0c8e42fSArtem B. Bityutskiy 
629e0c8e42fSArtem B. Bityutskiy 	switch(je16_to_cpu(node.u.nodetype)) {
630e0c8e42fSArtem B. Bityutskiy 
631e0c8e42fSArtem B. Bityutskiy 	case JFFS2_NODETYPE_INODE:
632e0c8e42fSArtem B. Bityutskiy 
633e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "the node is inode node\n");
634e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
635e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.ino));
636e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "version:\t%#08x\n",
637e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.version));
638e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "mode:\t%#08x\n",
639e0c8e42fSArtem B. Bityutskiy 				node.i.mode.m);
640e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "uid:\t%#04x\n",
641e0c8e42fSArtem B. Bityutskiy 				je16_to_cpu(node.i.uid));
642e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "gid:\t%#04x\n",
643e0c8e42fSArtem B. Bityutskiy 				je16_to_cpu(node.i.gid));
644e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "isize:\t%#08x\n",
645e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.isize));
646e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "atime:\t%#08x\n",
647e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.atime));
648e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "mtime:\t%#08x\n",
649e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.mtime));
650e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "ctime:\t%#08x\n",
651e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.ctime));
652e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "offset:\t%#08x\n",
653e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.offset));
654e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "csize:\t%#08x\n",
655e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.csize));
656e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "dsize:\t%#08x\n",
657e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.dsize));
658e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "compr:\t%#02x\n",
659e0c8e42fSArtem B. Bityutskiy 				node.i.compr);
660e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n",
661e0c8e42fSArtem B. Bityutskiy 				node.i.usercompr);
662e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "flags:\t%#04x\n",
663e0c8e42fSArtem B. Bityutskiy 				je16_to_cpu(node.i.flags));
664e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n",
665e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.data_crc));
666e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
667e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.node_crc));
668e0c8e42fSArtem B. Bityutskiy 		crc = crc32(0, &node.i, sizeof(node.i) - 8);
669e0c8e42fSArtem B. Bityutskiy 		if (crc != je32_to_cpu(node.i.node_crc)) {
670e0c8e42fSArtem B. Bityutskiy 			JFFS2_ERROR("wrong node header CRC.\n");
671e0c8e42fSArtem B. Bityutskiy 			return;
672e0c8e42fSArtem B. Bityutskiy 		}
673e0c8e42fSArtem B. Bityutskiy 		break;
674e0c8e42fSArtem B. Bityutskiy 
675e0c8e42fSArtem B. Bityutskiy 	case JFFS2_NODETYPE_DIRENT:
676e0c8e42fSArtem B. Bityutskiy 
677e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "the node is dirent node\n");
678e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "pino:\t%#08x\n",
679e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.pino));
680e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "version:\t%#08x\n",
681e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.version));
682e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
683e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.ino));
684e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "mctime:\t%#08x\n",
685e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.mctime));
686e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "nsize:\t%#02x\n",
687e0c8e42fSArtem B. Bityutskiy 				node.d.nsize);
688e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "type:\t%#02x\n",
689e0c8e42fSArtem B. Bityutskiy 				node.d.type);
690e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
691e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.node_crc));
692e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n",
693e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.name_crc));
694e0c8e42fSArtem B. Bityutskiy 
695e0c8e42fSArtem B. Bityutskiy 		node.d.name[node.d.nsize] = '\0';
696e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name);
697e0c8e42fSArtem B. Bityutskiy 
698e0c8e42fSArtem B. Bityutskiy 		crc = crc32(0, &node.d, sizeof(node.d) - 8);
699e0c8e42fSArtem B. Bityutskiy 		if (crc != je32_to_cpu(node.d.node_crc)) {
700e0c8e42fSArtem B. Bityutskiy 			JFFS2_ERROR("wrong node header CRC.\n");
701e0c8e42fSArtem B. Bityutskiy 			return;
702e0c8e42fSArtem B. Bityutskiy 		}
703e0c8e42fSArtem B. Bityutskiy 		break;
704e0c8e42fSArtem B. Bityutskiy 
705e0c8e42fSArtem B. Bityutskiy 	default:
706e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "node type is unknown\n");
707e0c8e42fSArtem B. Bityutskiy 		break;
708730554d9SArtem B. Bityutskiy 	}
709730554d9SArtem B. Bityutskiy }
710e0c8e42fSArtem B. Bityutskiy #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */
711