xref: /openbmc/linux/fs/jffs2/debug.c (revision 45ca1b50)
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  *
1045ca1b50SArtem B. Bityutskiy  * $Id: debug.c,v 1.9 2005/08/05 10:42:24 dedekind 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 
2145ca1b50SArtem B. Bityutskiy #ifdef JFFS2_DBG_SANITY_CHECKS
2245ca1b50SArtem B. Bityutskiy 
2345ca1b50SArtem B. Bityutskiy void
2445ca1b50SArtem B. Bityutskiy __jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c,
2545ca1b50SArtem B. Bityutskiy 				     struct jffs2_eraseblock *jeb)
2645ca1b50SArtem B. Bityutskiy {
2745ca1b50SArtem B. Bityutskiy 	if (unlikely(jeb && jeb->used_size + jeb->dirty_size +
2845ca1b50SArtem B. Bityutskiy 			jeb->free_size + jeb->wasted_size +
2945ca1b50SArtem B. Bityutskiy 			jeb->unchecked_size != c->sector_size)) {
3045ca1b50SArtem B. Bityutskiy 		JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset);
3145ca1b50SArtem B. Bityutskiy 		JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked "
3245ca1b50SArtem B. Bityutskiy 			"%#08x != total %#08x.\n", jeb->free_size, jeb->dirty_size, jeb->used_size,
3345ca1b50SArtem B. Bityutskiy 			jeb->wasted_size, jeb->unchecked_size, c->sector_size);
3445ca1b50SArtem B. Bityutskiy 		BUG();
3545ca1b50SArtem B. Bityutskiy 	}
3645ca1b50SArtem B. Bityutskiy 
3745ca1b50SArtem B. Bityutskiy 	if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size
3845ca1b50SArtem B. Bityutskiy 				+ c->wasted_size + c->unchecked_size != c->flash_size)) {
3945ca1b50SArtem B. Bityutskiy 		JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n");
4045ca1b50SArtem B. Bityutskiy 		JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + "
4145ca1b50SArtem B. Bityutskiy 			"wasted %#08x + unchecked %#08x != total %#08x.\n",
4245ca1b50SArtem B. Bityutskiy 			c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size,
4345ca1b50SArtem B. Bityutskiy 			c->wasted_size, c->unchecked_size, c->flash_size);
4445ca1b50SArtem B. Bityutskiy 		BUG();
4545ca1b50SArtem B. Bityutskiy 	}
4645ca1b50SArtem B. Bityutskiy }
4745ca1b50SArtem B. Bityutskiy 
4845ca1b50SArtem B. Bityutskiy void
4945ca1b50SArtem B. Bityutskiy __jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
5045ca1b50SArtem B. Bityutskiy 			      struct jffs2_eraseblock *jeb)
5145ca1b50SArtem B. Bityutskiy {
5245ca1b50SArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
5345ca1b50SArtem B. Bityutskiy 	jffs2_dbg_acct_sanity_check_nolock(c, jeb);
5445ca1b50SArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
5545ca1b50SArtem B. Bityutskiy }
5645ca1b50SArtem B. Bityutskiy 
5745ca1b50SArtem B. Bityutskiy #endif /* JFFS2_DBG_SANITY_CHECKS */
5845ca1b50SArtem B. Bityutskiy 
59730554d9SArtem B. Bityutskiy #ifdef JFFS2_DBG_PARANOIA_CHECKS
60e0c8e42fSArtem B. Bityutskiy /*
61e0c8e42fSArtem B. Bityutskiy  * Check the fragtree.
62e0c8e42fSArtem B. Bityutskiy  */
63e0c8e42fSArtem B. Bityutskiy void
64e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
65e0c8e42fSArtem B. Bityutskiy {
66e0c8e42fSArtem B. Bityutskiy 	down(&f->sem);
67e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_fragtree_paranoia_check_nolock(f);
68e0c8e42fSArtem B. Bityutskiy 	up(&f->sem);
69e0c8e42fSArtem B. Bityutskiy }
70730554d9SArtem B. Bityutskiy 
71730554d9SArtem B. Bityutskiy void
72e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
73730554d9SArtem B. Bityutskiy {
74730554d9SArtem B. Bityutskiy 	struct jffs2_node_frag *frag;
75730554d9SArtem B. Bityutskiy 	int bitched = 0;
76730554d9SArtem B. Bityutskiy 
77730554d9SArtem B. Bityutskiy 	for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
78730554d9SArtem B. Bityutskiy 		struct jffs2_full_dnode *fn = frag->node;
79730554d9SArtem B. Bityutskiy 
80730554d9SArtem B. Bityutskiy 		if (!fn || !fn->raw)
81730554d9SArtem B. Bityutskiy 			continue;
82730554d9SArtem B. Bityutskiy 
83730554d9SArtem B. Bityutskiy 		if (ref_flags(fn->raw) == REF_PRISTINE) {
84730554d9SArtem B. Bityutskiy 			if (fn->frags > 1) {
85e0c8e42fSArtem B. Bityutskiy 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
86730554d9SArtem B. Bityutskiy 						ref_offset(fn->raw), fn->frags);
87730554d9SArtem B. Bityutskiy 				bitched = 1;
88730554d9SArtem B. Bityutskiy 			}
89730554d9SArtem B. Bityutskiy 
90730554d9SArtem B. Bityutskiy 			/* A hole node which isn't multi-page should be garbage-collected
91730554d9SArtem B. Bityutskiy 			   and merged anyway, so we just check for the frag size here,
92730554d9SArtem B. Bityutskiy 			   rather than mucking around with actually reading the node
93730554d9SArtem B. Bityutskiy 			   and checking the compression type, which is the real way
94730554d9SArtem B. Bityutskiy 			   to tell a hole node. */
95730554d9SArtem B. Bityutskiy 			if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
96730554d9SArtem B. Bityutskiy 					&& frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
97e0c8e42fSArtem B. Bityutskiy 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag "
98e0c8e42fSArtem B. Bityutskiy 						"in the same page. Tell dwmw2.\n", ref_offset(fn->raw));
99730554d9SArtem B. Bityutskiy 				bitched = 1;
100730554d9SArtem B. Bityutskiy 			}
101730554d9SArtem B. Bityutskiy 
102730554d9SArtem B. Bityutskiy 			if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
103730554d9SArtem B. Bityutskiy 					&& frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
104e0c8e42fSArtem B. Bityutskiy 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
105e0c8e42fSArtem B. Bityutskiy 						"non-hole frag in the same page. Tell dwmw2.\n",
106730554d9SArtem B. Bityutskiy 					       ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
107730554d9SArtem B. Bityutskiy 				bitched = 1;
108730554d9SArtem B. Bityutskiy 			}
109730554d9SArtem B. Bityutskiy 		}
110730554d9SArtem B. Bityutskiy 	}
111730554d9SArtem B. Bityutskiy 
112730554d9SArtem B. Bityutskiy 	if (bitched) {
113e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("fragtree is corrupted.\n");
114e0c8e42fSArtem B. Bityutskiy 		__jffs2_dbg_dump_fragtree_nolock(f);
115730554d9SArtem B. Bityutskiy 		BUG();
116730554d9SArtem B. Bityutskiy 	}
117730554d9SArtem B. Bityutskiy }
118730554d9SArtem B. Bityutskiy 
119730554d9SArtem B. Bityutskiy /*
120730554d9SArtem B. Bityutskiy  * Check if the flash contains all 0xFF before we start writing.
121730554d9SArtem B. Bityutskiy  */
122730554d9SArtem B. Bityutskiy void
123e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
124e0c8e42fSArtem B. Bityutskiy 				    uint32_t ofs, int len)
125730554d9SArtem B. Bityutskiy {
126730554d9SArtem B. Bityutskiy 	size_t retlen;
127730554d9SArtem B. Bityutskiy 	int ret, i;
128730554d9SArtem B. Bityutskiy 	unsigned char *buf;
129730554d9SArtem B. Bityutskiy 
130730554d9SArtem B. Bityutskiy 	buf = kmalloc(len, GFP_KERNEL);
131730554d9SArtem B. Bityutskiy 	if (!buf)
132730554d9SArtem B. Bityutskiy 		return;
133730554d9SArtem B. Bityutskiy 
134730554d9SArtem B. Bityutskiy 	ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
135730554d9SArtem B. Bityutskiy 	if (ret || (retlen != len)) {
136e0c8e42fSArtem B. Bityutskiy 		JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
137e0c8e42fSArtem B. Bityutskiy 				len, ret, retlen);
138730554d9SArtem B. Bityutskiy 		kfree(buf);
139730554d9SArtem B. Bityutskiy 		return;
140730554d9SArtem B. Bityutskiy 	}
141730554d9SArtem B. Bityutskiy 
142730554d9SArtem B. Bityutskiy 	ret = 0;
143730554d9SArtem B. Bityutskiy 	for (i = 0; i < len; i++)
144730554d9SArtem B. Bityutskiy 		if (buf[i] != 0xff)
145730554d9SArtem B. Bityutskiy 			ret = 1;
146730554d9SArtem B. Bityutskiy 
147730554d9SArtem B. Bityutskiy 	if (ret) {
148e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data "
149e0c8e42fSArtem B. Bityutskiy 			"already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i);
150e0c8e42fSArtem B. Bityutskiy 		__jffs2_dbg_dump_buffer(buf, len, ofs);
151730554d9SArtem B. Bityutskiy 		kfree(buf);
152730554d9SArtem B. Bityutskiy 		BUG();
153730554d9SArtem B. Bityutskiy 	}
154730554d9SArtem B. Bityutskiy 
155730554d9SArtem B. Bityutskiy 	kfree(buf);
156730554d9SArtem B. Bityutskiy }
157730554d9SArtem B. Bityutskiy 
158730554d9SArtem B. Bityutskiy /*
159730554d9SArtem B. Bityutskiy  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
160730554d9SArtem B. Bityutskiy  */
161730554d9SArtem B. Bityutskiy void
162e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
163e0c8e42fSArtem B. Bityutskiy 				struct jffs2_eraseblock *jeb)
164e0c8e42fSArtem B. Bityutskiy {
165e0c8e42fSArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
166e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
167e0c8e42fSArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
168e0c8e42fSArtem B. Bityutskiy }
169e0c8e42fSArtem B. Bityutskiy 
170e0c8e42fSArtem B. Bityutskiy void
171e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
172e0c8e42fSArtem B. Bityutskiy 				       struct jffs2_eraseblock *jeb)
173730554d9SArtem B. Bityutskiy {
174730554d9SArtem B. Bityutskiy 	uint32_t my_used_size = 0;
175730554d9SArtem B. Bityutskiy 	uint32_t my_unchecked_size = 0;
176730554d9SArtem B. Bityutskiy 	uint32_t my_dirty_size = 0;
177730554d9SArtem B. Bityutskiy 	struct jffs2_raw_node_ref *ref2 = jeb->first_node;
178730554d9SArtem B. Bityutskiy 
179730554d9SArtem B. Bityutskiy 	while (ref2) {
180730554d9SArtem B. Bityutskiy 		uint32_t totlen = ref_totlen(c, jeb, ref2);
181730554d9SArtem B. Bityutskiy 
182730554d9SArtem B. Bityutskiy 		if (ref2->flash_offset < jeb->offset ||
183730554d9SArtem B. Bityutskiy 				ref2->flash_offset > jeb->offset + c->sector_size) {
184e0c8e42fSArtem B. Bityutskiy 			JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
185730554d9SArtem B. Bityutskiy 				ref_offset(ref2), jeb->offset);
186e0c8e42fSArtem B. Bityutskiy 			goto error;
187730554d9SArtem B. Bityutskiy 
188730554d9SArtem B. Bityutskiy 		}
189730554d9SArtem B. Bityutskiy 		if (ref_flags(ref2) == REF_UNCHECKED)
190730554d9SArtem B. Bityutskiy 			my_unchecked_size += totlen;
191730554d9SArtem B. Bityutskiy 		else if (!ref_obsolete(ref2))
192730554d9SArtem B. Bityutskiy 			my_used_size += totlen;
193730554d9SArtem B. Bityutskiy 		else
194730554d9SArtem B. Bityutskiy 			my_dirty_size += totlen;
195730554d9SArtem B. Bityutskiy 
196730554d9SArtem B. Bityutskiy 		if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
197e0c8e42fSArtem B. Bityutskiy 			JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
198e0c8e42fSArtem B. Bityutskiy 				"last_node is at %#08x (mem %p).\n",
199730554d9SArtem B. Bityutskiy 				ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
200730554d9SArtem B. Bityutskiy 				ref_offset(jeb->last_node), jeb->last_node);
201e0c8e42fSArtem B. Bityutskiy 			goto error;
202730554d9SArtem B. Bityutskiy 		}
203730554d9SArtem B. Bityutskiy 		ref2 = ref2->next_phys;
204730554d9SArtem B. Bityutskiy 	}
205730554d9SArtem B. Bityutskiy 
206730554d9SArtem B. Bityutskiy 	if (my_used_size != jeb->used_size) {
207e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
208730554d9SArtem B. Bityutskiy 			my_used_size, jeb->used_size);
209e0c8e42fSArtem B. Bityutskiy 		goto error;
210730554d9SArtem B. Bityutskiy 	}
211730554d9SArtem B. Bityutskiy 
212730554d9SArtem B. Bityutskiy 	if (my_unchecked_size != jeb->unchecked_size) {
213e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
214730554d9SArtem B. Bityutskiy 			my_unchecked_size, jeb->unchecked_size);
215e0c8e42fSArtem B. Bityutskiy 		goto error;
216730554d9SArtem B. Bityutskiy 	}
217730554d9SArtem B. Bityutskiy 
218e0c8e42fSArtem B. Bityutskiy #if 0
219e0c8e42fSArtem B. Bityutskiy 	/* This should work when we implement ref->__totlen elemination */
220730554d9SArtem B. Bityutskiy 	if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
221e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
222730554d9SArtem B. Bityutskiy 			my_dirty_size, jeb->dirty_size + jeb->wasted_size);
223e0c8e42fSArtem B. Bityutskiy 		goto error;
224730554d9SArtem B. Bityutskiy 	}
225730554d9SArtem B. Bityutskiy 
226730554d9SArtem B. Bityutskiy 	if (jeb->free_size == 0
227730554d9SArtem B. Bityutskiy 		&& my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
228e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
229730554d9SArtem B. Bityutskiy 			my_used_size + my_unchecked_size + my_dirty_size,
230730554d9SArtem B. Bityutskiy 			c->sector_size);
231e0c8e42fSArtem B. Bityutskiy 		goto error;
232730554d9SArtem B. Bityutskiy 	}
233e0c8e42fSArtem B. Bityutskiy #endif
234730554d9SArtem B. Bityutskiy 
235e0c8e42fSArtem B. Bityutskiy 	return;
236e0c8e42fSArtem B. Bityutskiy 
237e0c8e42fSArtem B. Bityutskiy error:
238e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
239e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_jeb_nolock(jeb);
240e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_block_lists_nolock(c);
241e0c8e42fSArtem B. Bityutskiy 	BUG();
242e0c8e42fSArtem B. Bityutskiy 
243e0c8e42fSArtem B. Bityutskiy }
244e0c8e42fSArtem B. Bityutskiy #endif /* JFFS2_DBG_PARANOIA_CHECKS */
245e0c8e42fSArtem B. Bityutskiy 
246e0c8e42fSArtem B. Bityutskiy #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
247730554d9SArtem B. Bityutskiy /*
248730554d9SArtem B. Bityutskiy  * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
249730554d9SArtem B. Bityutskiy  */
250730554d9SArtem B. Bityutskiy void
251e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
252e0c8e42fSArtem B. Bityutskiy 			   struct jffs2_eraseblock *jeb)
253e0c8e42fSArtem B. Bityutskiy {
254e0c8e42fSArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
255e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
256e0c8e42fSArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
257e0c8e42fSArtem B. Bityutskiy }
258e0c8e42fSArtem B. Bityutskiy 
259e0c8e42fSArtem B. Bityutskiy void
260e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
261e0c8e42fSArtem B. Bityutskiy 				  struct jffs2_eraseblock *jeb)
262730554d9SArtem B. Bityutskiy {
263730554d9SArtem B. Bityutskiy 	struct jffs2_raw_node_ref *ref;
264730554d9SArtem B. Bityutskiy 	int i = 0;
265730554d9SArtem B. Bityutskiy 
266e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset);
267730554d9SArtem B. Bityutskiy 	if (!jeb->first_node) {
268e0c8e42fSArtem B. Bityutskiy 		JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset);
269730554d9SArtem B. Bityutskiy 		return;
270730554d9SArtem B. Bityutskiy 	}
271730554d9SArtem B. Bityutskiy 
272e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL);
273730554d9SArtem B. Bityutskiy 	for (ref = jeb->first_node; ; ref = ref->next_phys) {
274730554d9SArtem B. Bityutskiy 		printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
275730554d9SArtem B. Bityutskiy 		if (ref->next_phys)
276730554d9SArtem B. Bityutskiy 			printk("->");
277730554d9SArtem B. Bityutskiy 		else
278730554d9SArtem B. Bityutskiy 			break;
279730554d9SArtem B. Bityutskiy 		if (++i == 4) {
280730554d9SArtem B. Bityutskiy 			i = 0;
281e0c8e42fSArtem B. Bityutskiy 			printk("\n" JFFS2_DBG_LVL);
282730554d9SArtem B. Bityutskiy 		}
283730554d9SArtem B. Bityutskiy 	}
284730554d9SArtem B. Bityutskiy 	printk("\n");
285730554d9SArtem B. Bityutskiy }
286730554d9SArtem B. Bityutskiy 
287e0c8e42fSArtem B. Bityutskiy /*
288e0c8e42fSArtem B. Bityutskiy  * Dump an eraseblock's space accounting.
289e0c8e42fSArtem B. Bityutskiy  */
290730554d9SArtem B. Bityutskiy void
291e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
292730554d9SArtem B. Bityutskiy {
293e0c8e42fSArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
294e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_jeb_nolock(jeb);
295e0c8e42fSArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
296e0c8e42fSArtem B. Bityutskiy }
297e0c8e42fSArtem B. Bityutskiy 
298e0c8e42fSArtem B. Bityutskiy void
299e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
300e0c8e42fSArtem B. Bityutskiy {
301e0c8e42fSArtem B. Bityutskiy 	if (!jeb)
302e0c8e42fSArtem B. Bityutskiy 		return;
303e0c8e42fSArtem B. Bityutskiy 
304e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n",
305e0c8e42fSArtem B. Bityutskiy 			jeb->offset);
306e0c8e42fSArtem B. Bityutskiy 
307e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "used_size: %#08x\n",	jeb->used_size);
308e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "dirty_size: %#08x\n",	jeb->dirty_size);
309e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "wasted_size: %#08x\n",	jeb->wasted_size);
310e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n",	jeb->unchecked_size);
311e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "free_size: %#08x\n",	jeb->free_size);
312e0c8e42fSArtem B. Bityutskiy }
313e0c8e42fSArtem B. Bityutskiy 
314e0c8e42fSArtem B. Bityutskiy void
315e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
316e0c8e42fSArtem B. Bityutskiy {
317e0c8e42fSArtem B. Bityutskiy 	spin_lock(&c->erase_completion_lock);
318e0c8e42fSArtem B. Bityutskiy 	__jffs2_dbg_dump_block_lists_nolock(c);
319e0c8e42fSArtem B. Bityutskiy 	spin_unlock(&c->erase_completion_lock);
320e0c8e42fSArtem B. Bityutskiy }
321e0c8e42fSArtem B. Bityutskiy 
322e0c8e42fSArtem B. Bityutskiy void
323e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
324e0c8e42fSArtem B. Bityutskiy {
325e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump JFFS2 blocks lists:\n");
326e0c8e42fSArtem B. Bityutskiy 
327e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "flash_size: %#08x\n",	c->flash_size);
328e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "used_size: %#08x\n",	c->used_size);
329e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "dirty_size: %#08x\n",	c->dirty_size);
330e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "wasted_size: %#08x\n",	c->wasted_size);
331e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n",	c->unchecked_size);
332e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "free_size: %#08x\n",	c->free_size);
333e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "erasing_size: %#08x\n",	c->erasing_size);
334e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "bad_size: %#08x\n",	c->bad_size);
335e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "sector_size: %#08x\n",	c->sector_size);
336e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n",
337730554d9SArtem B. Bityutskiy 				c->sector_size * c->resv_blocks_write);
338730554d9SArtem B. Bityutskiy 
339730554d9SArtem B. Bityutskiy 	if (c->nextblock)
340e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
341730554d9SArtem B. Bityutskiy 			"unchecked %#08x, free %#08x)\n",
342730554d9SArtem B. Bityutskiy 			c->nextblock->offset, c->nextblock->used_size,
343730554d9SArtem B. Bityutskiy 			c->nextblock->dirty_size, c->nextblock->wasted_size,
344730554d9SArtem B. Bityutskiy 			c->nextblock->unchecked_size, c->nextblock->free_size);
345730554d9SArtem B. Bityutskiy 	else
346e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "nextblock: NULL\n");
347730554d9SArtem B. Bityutskiy 
348730554d9SArtem B. Bityutskiy 	if (c->gcblock)
349e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
350730554d9SArtem B. Bityutskiy 			"unchecked %#08x, free %#08x)\n",
351730554d9SArtem B. Bityutskiy 			c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
352730554d9SArtem B. Bityutskiy 			c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
353730554d9SArtem B. Bityutskiy 	else
354e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "gcblock: NULL\n");
355730554d9SArtem B. Bityutskiy 
356730554d9SArtem B. Bityutskiy 	if (list_empty(&c->clean_list)) {
357e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "clean_list: empty\n");
358730554d9SArtem B. Bityutskiy 	} else {
359730554d9SArtem B. Bityutskiy 		struct list_head *this;
360730554d9SArtem B. Bityutskiy 		int numblocks = 0;
361730554d9SArtem B. Bityutskiy 		uint32_t dirty = 0;
362730554d9SArtem B. Bityutskiy 
363730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->clean_list) {
364730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
365730554d9SArtem B. Bityutskiy 			numblocks ++;
366730554d9SArtem B. Bityutskiy 			dirty += jeb->wasted_size;
367730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
368e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
369730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
370730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
371730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
372730554d9SArtem B. Bityutskiy 			}
373730554d9SArtem B. Bityutskiy 		}
374730554d9SArtem B. Bityutskiy 
375e0c8e42fSArtem B. Bityutskiy 		printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
376730554d9SArtem B. Bityutskiy 			numblocks, dirty, dirty / numblocks);
377730554d9SArtem B. Bityutskiy 	}
378730554d9SArtem B. Bityutskiy 
379730554d9SArtem B. Bityutskiy 	if (list_empty(&c->very_dirty_list)) {
380e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "very_dirty_list: empty\n");
381730554d9SArtem B. Bityutskiy 	} else {
382730554d9SArtem B. Bityutskiy 		struct list_head *this;
383730554d9SArtem B. Bityutskiy 		int numblocks = 0;
384730554d9SArtem B. Bityutskiy 		uint32_t dirty = 0;
385730554d9SArtem B. Bityutskiy 
386730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->very_dirty_list) {
387730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
388730554d9SArtem B. Bityutskiy 
389730554d9SArtem B. Bityutskiy 			numblocks ++;
390730554d9SArtem B. Bityutskiy 			dirty += jeb->dirty_size;
391730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
392e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
393730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
394730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
395730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
396730554d9SArtem B. Bityutskiy 			}
397730554d9SArtem B. Bityutskiy 		}
398730554d9SArtem B. Bityutskiy 
399e0c8e42fSArtem B. Bityutskiy 		printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
400730554d9SArtem B. Bityutskiy 			numblocks, dirty, dirty / numblocks);
401730554d9SArtem B. Bityutskiy 	}
402730554d9SArtem B. Bityutskiy 
403730554d9SArtem B. Bityutskiy 	if (list_empty(&c->dirty_list)) {
404e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "dirty_list: empty\n");
405730554d9SArtem B. Bityutskiy 	} else {
406730554d9SArtem B. Bityutskiy 		struct list_head *this;
407730554d9SArtem B. Bityutskiy 		int numblocks = 0;
408730554d9SArtem B. Bityutskiy 		uint32_t dirty = 0;
409730554d9SArtem B. Bityutskiy 
410730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->dirty_list) {
411730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
412730554d9SArtem B. Bityutskiy 
413730554d9SArtem B. Bityutskiy 			numblocks ++;
414730554d9SArtem B. Bityutskiy 			dirty += jeb->dirty_size;
415730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
416e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
417730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
418730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
419730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
420730554d9SArtem B. Bityutskiy 			}
421730554d9SArtem B. Bityutskiy 		}
422730554d9SArtem B. Bityutskiy 
423e0c8e42fSArtem B. Bityutskiy 		printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n",
424730554d9SArtem B. Bityutskiy 			numblocks, dirty, dirty / numblocks);
425730554d9SArtem B. Bityutskiy 	}
426730554d9SArtem B. Bityutskiy 
427730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erasable_list)) {
428e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "erasable_list: empty\n");
429730554d9SArtem B. Bityutskiy 	} else {
430730554d9SArtem B. Bityutskiy 		struct list_head *this;
431730554d9SArtem B. Bityutskiy 
432730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erasable_list) {
433730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
434730554d9SArtem B. Bityutskiy 
435730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
436e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
437730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
438730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
439730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
440730554d9SArtem B. Bityutskiy 			}
441730554d9SArtem B. Bityutskiy 		}
442730554d9SArtem B. Bityutskiy 	}
443730554d9SArtem B. Bityutskiy 
444730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erasing_list)) {
445e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "erasing_list: empty\n");
446730554d9SArtem B. Bityutskiy 	} else {
447730554d9SArtem B. Bityutskiy 		struct list_head *this;
448730554d9SArtem B. Bityutskiy 
449730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erasing_list) {
450730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
451730554d9SArtem B. Bityutskiy 
452730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
453e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
454730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
455730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
456730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
457730554d9SArtem B. Bityutskiy 			}
458730554d9SArtem B. Bityutskiy 		}
459730554d9SArtem B. Bityutskiy 	}
460730554d9SArtem B. Bityutskiy 
461730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erase_pending_list)) {
462e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "erase_pending_list: empty\n");
463730554d9SArtem B. Bityutskiy 	} else {
464730554d9SArtem B. Bityutskiy 		struct list_head *this;
465730554d9SArtem B. Bityutskiy 
466730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erase_pending_list) {
467730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
468730554d9SArtem B. Bityutskiy 
469730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
470e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
471730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
472730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
473730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
474730554d9SArtem B. Bityutskiy 			}
475730554d9SArtem B. Bityutskiy 		}
476730554d9SArtem B. Bityutskiy 	}
477730554d9SArtem B. Bityutskiy 
478730554d9SArtem B. Bityutskiy 	if (list_empty(&c->erasable_pending_wbuf_list)) {
479e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n");
480730554d9SArtem B. Bityutskiy 	} else {
481730554d9SArtem B. Bityutskiy 		struct list_head *this;
482730554d9SArtem B. Bityutskiy 
483730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->erasable_pending_wbuf_list) {
484730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
485730554d9SArtem B. Bityutskiy 
486730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
487e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
488730554d9SArtem B. Bityutskiy 					"wasted %#08x, unchecked %#08x, free %#08x)\n",
489730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
490730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
491730554d9SArtem B. Bityutskiy 			}
492730554d9SArtem B. Bityutskiy 		}
493730554d9SArtem B. Bityutskiy 	}
494730554d9SArtem B. Bityutskiy 
495730554d9SArtem B. Bityutskiy 	if (list_empty(&c->free_list)) {
496e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "free_list: empty\n");
497730554d9SArtem B. Bityutskiy 	} else {
498730554d9SArtem B. Bityutskiy 		struct list_head *this;
499730554d9SArtem B. Bityutskiy 
500730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->free_list) {
501730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
502730554d9SArtem B. Bityutskiy 
503730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
504e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
505730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
506730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
507730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
508730554d9SArtem B. Bityutskiy 			}
509730554d9SArtem B. Bityutskiy 		}
510730554d9SArtem B. Bityutskiy 	}
511730554d9SArtem B. Bityutskiy 
512730554d9SArtem B. Bityutskiy 	if (list_empty(&c->bad_list)) {
513e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "bad_list: empty\n");
514730554d9SArtem B. Bityutskiy 	} else {
515730554d9SArtem B. Bityutskiy 		struct list_head *this;
516730554d9SArtem B. Bityutskiy 
517730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->bad_list) {
518730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
519730554d9SArtem B. Bityutskiy 
520730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
521e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
522730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
523730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
524730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
525730554d9SArtem B. Bityutskiy 			}
526730554d9SArtem B. Bityutskiy 		}
527730554d9SArtem B. Bityutskiy 	}
528730554d9SArtem B. Bityutskiy 
529730554d9SArtem B. Bityutskiy 	if (list_empty(&c->bad_used_list)) {
530e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "bad_used_list: empty\n");
531730554d9SArtem B. Bityutskiy 	} else {
532730554d9SArtem B. Bityutskiy 		struct list_head *this;
533730554d9SArtem B. Bityutskiy 
534730554d9SArtem B. Bityutskiy 		list_for_each(this, &c->bad_used_list) {
535730554d9SArtem B. Bityutskiy 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
536730554d9SArtem B. Bityutskiy 
537730554d9SArtem B. Bityutskiy 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
538e0c8e42fSArtem B. Bityutskiy 				printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
539730554d9SArtem B. Bityutskiy 					"unchecked %#08x, free %#08x)\n",
540730554d9SArtem B. Bityutskiy 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
541730554d9SArtem B. Bityutskiy 					jeb->unchecked_size, jeb->free_size);
542730554d9SArtem B. Bityutskiy 			}
543730554d9SArtem B. Bityutskiy 		}
544730554d9SArtem B. Bityutskiy 	}
545730554d9SArtem B. Bityutskiy }
546730554d9SArtem B. Bityutskiy 
547730554d9SArtem B. Bityutskiy void
548e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
549e0c8e42fSArtem B. Bityutskiy {
550e0c8e42fSArtem B. Bityutskiy 	down(&f->sem);
551e0c8e42fSArtem B. Bityutskiy 	jffs2_dbg_dump_fragtree_nolock(f);
552e0c8e42fSArtem B. Bityutskiy 	up(&f->sem);
553e0c8e42fSArtem B. Bityutskiy }
554e0c8e42fSArtem B. Bityutskiy 
555e0c8e42fSArtem B. Bityutskiy void
556e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
557730554d9SArtem B. Bityutskiy {
558730554d9SArtem B. Bityutskiy 	struct jffs2_node_frag *this = frag_first(&f->fragtree);
559730554d9SArtem B. Bityutskiy 	uint32_t lastofs = 0;
560730554d9SArtem B. Bityutskiy 	int buggy = 0;
561730554d9SArtem B. Bityutskiy 
562e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino);
563730554d9SArtem B. Bityutskiy 	while(this) {
564730554d9SArtem B. Bityutskiy 		if (this->node)
565e0c8e42fSArtem B. Bityutskiy 			printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
566730554d9SArtem B. Bityutskiy 				"right (%p), parent (%p)\n",
567730554d9SArtem B. Bityutskiy 				this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
568730554d9SArtem B. Bityutskiy 				ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
569730554d9SArtem B. Bityutskiy 				frag_parent(this));
570730554d9SArtem B. Bityutskiy 		else
571e0c8e42fSArtem B. Bityutskiy 			printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
572730554d9SArtem B. Bityutskiy 				this->ofs, this->ofs+this->size, this, frag_left(this),
573730554d9SArtem B. Bityutskiy 				frag_right(this), frag_parent(this));
574730554d9SArtem B. Bityutskiy 		if (this->ofs != lastofs)
575730554d9SArtem B. Bityutskiy 			buggy = 1;
576730554d9SArtem B. Bityutskiy 		lastofs = this->ofs + this->size;
577730554d9SArtem B. Bityutskiy 		this = frag_next(this);
578730554d9SArtem B. Bityutskiy 	}
579730554d9SArtem B. Bityutskiy 
580730554d9SArtem B. Bityutskiy 	if (f->metadata)
581e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
582730554d9SArtem B. Bityutskiy 
583730554d9SArtem B. Bityutskiy 	if (buggy) {
584e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("frag tree got a hole in it.\n");
585730554d9SArtem B. Bityutskiy 		BUG();
586730554d9SArtem B. Bityutskiy 	}
587730554d9SArtem B. Bityutskiy }
588730554d9SArtem B. Bityutskiy 
589e0c8e42fSArtem B. Bityutskiy #define JFFS2_BUFDUMP_BYTES_PER_LINE	32
590730554d9SArtem B. Bityutskiy void
591e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
592730554d9SArtem B. Bityutskiy {
593e0c8e42fSArtem B. Bityutskiy 	int skip;
594e0c8e42fSArtem B. Bityutskiy 	int i;
595e0c8e42fSArtem B. Bityutskiy 
596e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n",
597e0c8e42fSArtem B. Bityutskiy 		offs, offs + len, len);
598e0c8e42fSArtem B. Bityutskiy 	i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
599e0c8e42fSArtem B. Bityutskiy 	offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
600e0c8e42fSArtem B. Bityutskiy 
601e0c8e42fSArtem B. Bityutskiy 	if (skip != 0)
602e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "%#08x: ", offs);
603e0c8e42fSArtem B. Bityutskiy 
604e0c8e42fSArtem B. Bityutskiy 	while (skip--)
605e0c8e42fSArtem B. Bityutskiy 		printk("   ");
606730554d9SArtem B. Bityutskiy 
607730554d9SArtem B. Bityutskiy 	while (i < len) {
608e0c8e42fSArtem B. Bityutskiy 		if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
609e0c8e42fSArtem B. Bityutskiy 			if (i != 0)
610e0c8e42fSArtem B. Bityutskiy 				printk("\n");
611e0c8e42fSArtem B. Bityutskiy 			offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
612e0c8e42fSArtem B. Bityutskiy 			printk(JFFS2_DBG_LVL "%0#8x: ", offs);
613730554d9SArtem B. Bityutskiy 		}
614730554d9SArtem B. Bityutskiy 
615e0c8e42fSArtem B. Bityutskiy 		printk("%02x ", buf[i]);
616e0c8e42fSArtem B. Bityutskiy 
617e0c8e42fSArtem B. Bityutskiy 		i += 1;
618730554d9SArtem B. Bityutskiy 	}
619730554d9SArtem B. Bityutskiy 
620e0c8e42fSArtem B. Bityutskiy 	printk("\n");
621e0c8e42fSArtem B. Bityutskiy }
622e0c8e42fSArtem B. Bityutskiy 
623e0c8e42fSArtem B. Bityutskiy /*
624e0c8e42fSArtem B. Bityutskiy  * Dump a JFFS2 node.
625e0c8e42fSArtem B. Bityutskiy  */
626e0c8e42fSArtem B. Bityutskiy void
627e0c8e42fSArtem B. Bityutskiy __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
628e0c8e42fSArtem B. Bityutskiy {
629e0c8e42fSArtem B. Bityutskiy 	union jffs2_node_union node;
630e0c8e42fSArtem B. Bityutskiy 	int len = sizeof(union jffs2_node_union);
631e0c8e42fSArtem B. Bityutskiy 	size_t retlen;
632e0c8e42fSArtem B. Bityutskiy 	uint32_t crc;
633e0c8e42fSArtem B. Bityutskiy 	int ret;
634e0c8e42fSArtem B. Bityutskiy 
635e0c8e42fSArtem B. Bityutskiy 	JFFS2_DEBUG("dump node at offset %#08x.\n", ofs);
636e0c8e42fSArtem B. Bityutskiy 
637e0c8e42fSArtem B. Bityutskiy 	ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
638e0c8e42fSArtem B. Bityutskiy 	if (ret || (retlen != len)) {
639e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
640e0c8e42fSArtem B. Bityutskiy 			len, ret, retlen);
641e0c8e42fSArtem B. Bityutskiy 		return;
642e0c8e42fSArtem B. Bityutskiy 	}
643e0c8e42fSArtem B. Bityutskiy 
644e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "magic:\t%#04x\n",
645e0c8e42fSArtem B. Bityutskiy 		je16_to_cpu(node.u.magic));
646e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n",
647e0c8e42fSArtem B. Bityutskiy 		je16_to_cpu(node.u.nodetype));
648e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "totlen:\t%#08x\n",
649e0c8e42fSArtem B. Bityutskiy 		je32_to_cpu(node.u.totlen));
650e0c8e42fSArtem B. Bityutskiy 	printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n",
651e0c8e42fSArtem B. Bityutskiy 		je32_to_cpu(node.u.hdr_crc));
652e0c8e42fSArtem B. Bityutskiy 
653e0c8e42fSArtem B. Bityutskiy 	crc = crc32(0, &node.u, sizeof(node.u) - 4);
654e0c8e42fSArtem B. Bityutskiy 	if (crc != je32_to_cpu(node.u.hdr_crc)) {
655e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("wrong common header CRC.\n");
656e0c8e42fSArtem B. Bityutskiy 		return;
657e0c8e42fSArtem B. Bityutskiy 	}
658e0c8e42fSArtem B. Bityutskiy 
659e0c8e42fSArtem B. Bityutskiy 	if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
660e0c8e42fSArtem B. Bityutskiy 		je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
661e0c8e42fSArtem B. Bityutskiy 	{
662e0c8e42fSArtem B. Bityutskiy 		JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
663e0c8e42fSArtem B. Bityutskiy 			je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
664e0c8e42fSArtem B. Bityutskiy 		return;
665e0c8e42fSArtem B. Bityutskiy 	}
666e0c8e42fSArtem B. Bityutskiy 
667e0c8e42fSArtem B. Bityutskiy 	switch(je16_to_cpu(node.u.nodetype)) {
668e0c8e42fSArtem B. Bityutskiy 
669e0c8e42fSArtem B. Bityutskiy 	case JFFS2_NODETYPE_INODE:
670e0c8e42fSArtem B. Bityutskiy 
671e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "the node is inode node\n");
672e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
673e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.ino));
674e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "version:\t%#08x\n",
675e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.version));
676e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "mode:\t%#08x\n",
677e0c8e42fSArtem B. Bityutskiy 				node.i.mode.m);
678e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "uid:\t%#04x\n",
679e0c8e42fSArtem B. Bityutskiy 				je16_to_cpu(node.i.uid));
680e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "gid:\t%#04x\n",
681e0c8e42fSArtem B. Bityutskiy 				je16_to_cpu(node.i.gid));
682e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "isize:\t%#08x\n",
683e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.isize));
684e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "atime:\t%#08x\n",
685e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.atime));
686e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "mtime:\t%#08x\n",
687e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.mtime));
688e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "ctime:\t%#08x\n",
689e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.ctime));
690e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "offset:\t%#08x\n",
691e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.offset));
692e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "csize:\t%#08x\n",
693e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.csize));
694e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "dsize:\t%#08x\n",
695e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.dsize));
696e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "compr:\t%#02x\n",
697e0c8e42fSArtem B. Bityutskiy 				node.i.compr);
698e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n",
699e0c8e42fSArtem B. Bityutskiy 				node.i.usercompr);
700e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "flags:\t%#04x\n",
701e0c8e42fSArtem B. Bityutskiy 				je16_to_cpu(node.i.flags));
702e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n",
703e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.data_crc));
704e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
705e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.i.node_crc));
706e0c8e42fSArtem B. Bityutskiy 		crc = crc32(0, &node.i, sizeof(node.i) - 8);
707e0c8e42fSArtem B. Bityutskiy 		if (crc != je32_to_cpu(node.i.node_crc)) {
708e0c8e42fSArtem B. Bityutskiy 			JFFS2_ERROR("wrong node header CRC.\n");
709e0c8e42fSArtem B. Bityutskiy 			return;
710e0c8e42fSArtem B. Bityutskiy 		}
711e0c8e42fSArtem B. Bityutskiy 		break;
712e0c8e42fSArtem B. Bityutskiy 
713e0c8e42fSArtem B. Bityutskiy 	case JFFS2_NODETYPE_DIRENT:
714e0c8e42fSArtem B. Bityutskiy 
715e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "the node is dirent node\n");
716e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "pino:\t%#08x\n",
717e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.pino));
718e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "version:\t%#08x\n",
719e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.version));
720e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
721e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.ino));
722e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "mctime:\t%#08x\n",
723e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.mctime));
724e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "nsize:\t%#02x\n",
725e0c8e42fSArtem B. Bityutskiy 				node.d.nsize);
726e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "type:\t%#02x\n",
727e0c8e42fSArtem B. Bityutskiy 				node.d.type);
728e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
729e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.node_crc));
730e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n",
731e0c8e42fSArtem B. Bityutskiy 				je32_to_cpu(node.d.name_crc));
732e0c8e42fSArtem B. Bityutskiy 
733e0c8e42fSArtem B. Bityutskiy 		node.d.name[node.d.nsize] = '\0';
734e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name);
735e0c8e42fSArtem B. Bityutskiy 
736e0c8e42fSArtem B. Bityutskiy 		crc = crc32(0, &node.d, sizeof(node.d) - 8);
737e0c8e42fSArtem B. Bityutskiy 		if (crc != je32_to_cpu(node.d.node_crc)) {
738e0c8e42fSArtem B. Bityutskiy 			JFFS2_ERROR("wrong node header CRC.\n");
739e0c8e42fSArtem B. Bityutskiy 			return;
740e0c8e42fSArtem B. Bityutskiy 		}
741e0c8e42fSArtem B. Bityutskiy 		break;
742e0c8e42fSArtem B. Bityutskiy 
743e0c8e42fSArtem B. Bityutskiy 	default:
744e0c8e42fSArtem B. Bityutskiy 		printk(JFFS2_DBG_LVL "node type is unknown\n");
745e0c8e42fSArtem B. Bityutskiy 		break;
746730554d9SArtem B. Bityutskiy 	}
747730554d9SArtem B. Bityutskiy }
748e0c8e42fSArtem B. Bityutskiy #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */
749