xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/jffs2/src/debug.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * JFFS2 -- Journalling Flash File System, Version 2.
3  *
4  * Copyright (C) 2001-2003 Red Hat, Inc.
5  *
6  * Created by David Woodhouse <[email protected]>
7  *
8  * For licensing information, see the file 'LICENCE' in this directory.
9  *
10  * $Id: debug.c,v 1.1 2005/07/30 15:30:42 asl Exp $
11  *
12  */
13 #include <linux/kernel.h>
14 #include <linux/types.h>
15 #include <linux/pagemap.h>
16 #include <linux/crc32.h>
17 #include <linux/jffs2.h>
18 #include <linux/slab.h>
19 #include "nodelist.h"
20 #include "debug.h"
21 
22 #ifdef JFFS2_DBG_PARANOIA_CHECKS
23 /*
24  * Check the fragtree.
25  */
26 void
__jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info * f)27 __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
28 {
29 	down(&f->sem);
30 	__jffs2_dbg_fragtree_paranoia_check_nolock(f);
31 	up(&f->sem);
32 }
33 
34 void
__jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info * f)35 __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
36 {
37 	struct jffs2_node_frag *frag;
38 	int bitched = 0;
39 
40 	for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
41 		struct jffs2_full_dnode *fn = frag->node;
42 
43 		if (!fn || !fn->raw)
44 			continue;
45 
46 		if (ref_flags(fn->raw) == REF_PRISTINE) {
47 			if (fn->frags > 1) {
48 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
49 						ref_offset(fn->raw), fn->frags);
50 				bitched = 1;
51 			}
52 
53 			/* A hole node which isn't multi-page should be garbage-collected
54 			   and merged anyway, so we just check for the frag size here,
55 			   rather than mucking around with actually reading the node
56 			   and checking the compression type, which is the real way
57 			   to tell a hole node. */
58 			if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
59 					&& frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
60 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag "
61 						"in the same page. Tell dwmw2.\n", ref_offset(fn->raw));
62 				bitched = 1;
63 			}
64 
65 			if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
66 					&& frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
67 				JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following "
68 						"non-hole frag in the same page. Tell dwmw2.\n",
69 					       ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
70 				bitched = 1;
71 			}
72 		}
73 	}
74 
75 	if (bitched) {
76 		JFFS2_ERROR("fragtree is corrupted.\n");
77 		__jffs2_dbg_dump_fragtree_nolock(f);
78 		BUG();
79 	}
80 }
81 
82 /*
83  * Check if the flash contains all 0xFF before we start writing.
84  */
85 void
__jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info * c,uint32_t ofs,int len)86 __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
87 				    uint32_t ofs, int len)
88 {
89 	size_t retlen;
90 	int ret, i;
91 	unsigned char *buf;
92 
93 	buf = kmalloc(len, GFP_KERNEL);
94 	if (!buf)
95 		return;
96 
97 	ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
98 	if (ret || (retlen != len)) {
99 		JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
100 				len, ret, retlen);
101 		kfree(buf);
102 		return;
103 	}
104 
105 	ret = 0;
106 	for (i = 0; i < len; i++)
107 		if (buf[i] != 0xff)
108 			ret = 1;
109 
110 	if (ret) {
111 		JFFS2_ERROR("argh, about to write node to %#08x on flash, but there are data "
112 			"already there. The first corrupted byte is at %#08x offset.\n", ofs, ofs + i);
113 		__jffs2_dbg_dump_buffer(buf, len, ofs);
114 		kfree(buf);
115 		BUG();
116 	}
117 
118 	kfree(buf);
119 }
120 
121 /*
122  * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
123  */
124 void
__jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)125 __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
126 				struct jffs2_eraseblock *jeb)
127 {
128 	spin_lock(&c->erase_completion_lock);
129 	__jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
130 	spin_unlock(&c->erase_completion_lock);
131 }
132 
133 void
__jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)134 __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
135 				       struct jffs2_eraseblock *jeb)
136 {
137 	uint32_t my_used_size = 0;
138 	uint32_t my_unchecked_size = 0;
139 	uint32_t my_dirty_size = 0;
140 	struct jffs2_raw_node_ref *ref2 = jeb->first_node;
141 
142 	while (ref2) {
143 		uint32_t totlen = ref_totlen(c, jeb, ref2);
144 
145 		if (ref2->flash_offset < jeb->offset ||
146 				ref2->flash_offset > jeb->offset + c->sector_size) {
147 			JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
148 				ref_offset(ref2), jeb->offset);
149 			goto error;
150 
151 		}
152 		if (ref_flags(ref2) == REF_UNCHECKED)
153 			my_unchecked_size += totlen;
154 		else if (!ref_obsolete(ref2))
155 			my_used_size += totlen;
156 		else
157 			my_dirty_size += totlen;
158 
159 		if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
160 			JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), "
161 				"last_node is at %#08x (mem %p).\n",
162 				ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
163 				ref_offset(jeb->last_node), jeb->last_node);
164 			goto error;
165 		}
166 		ref2 = ref2->next_phys;
167 	}
168 
169 	if (my_used_size != jeb->used_size) {
170 		JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
171 			my_used_size, jeb->used_size);
172 		goto error;
173 	}
174 
175 	if (my_unchecked_size != jeb->unchecked_size) {
176 		JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
177 			my_unchecked_size, jeb->unchecked_size);
178 		goto error;
179 	}
180 
181 #if 0
182 	/* This should work when we implement ref->__totlen elemination */
183 	if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
184 		JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
185 			my_dirty_size, jeb->dirty_size + jeb->wasted_size);
186 		goto error;
187 	}
188 
189 	if (jeb->free_size == 0
190 		&& my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
191 		JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
192 			my_used_size + my_unchecked_size + my_dirty_size,
193 			c->sector_size);
194 		goto error;
195 	}
196 #endif
197 
198 	return;
199 
200 error:
201 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
202 	__jffs2_dbg_dump_jeb_nolock(jeb);
203 	__jffs2_dbg_dump_block_lists_nolock(c);
204 	BUG();
205 
206 }
207 #endif /* JFFS2_DBG_PARANOIA_CHECKS */
208 
209 #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
210 /*
211  * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
212  */
213 void
__jffs2_dbg_dump_node_refs(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)214 __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
215 			   struct jffs2_eraseblock *jeb)
216 {
217 	spin_lock(&c->erase_completion_lock);
218 	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
219 	spin_unlock(&c->erase_completion_lock);
220 }
221 
222 void
__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)223 __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
224 				  struct jffs2_eraseblock *jeb)
225 {
226 	struct jffs2_raw_node_ref *ref;
227 	int i = 0;
228 
229 	JFFS2_DEBUG("Dump node_refs of the eraseblock %#08x\n", jeb->offset);
230 	if (!jeb->first_node) {
231 		JFFS2_DEBUG("no nodes in the eraseblock %#08x\n", jeb->offset);
232 		return;
233 	}
234 
235 	printk(JFFS2_DBG_LVL);
236 	for (ref = jeb->first_node; ; ref = ref->next_phys) {
237 		printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
238 		if (ref->next_phys)
239 			printk("->");
240 		else
241 			break;
242 		if (++i == 4) {
243 			i = 0;
244 			printk("\n" JFFS2_DBG_LVL);
245 		}
246 	}
247 	printk("\n");
248 }
249 
250 /*
251  * Dump an eraseblock's space accounting.
252  */
253 void
__jffs2_dbg_dump_jeb(struct jffs2_sb_info * c,struct jffs2_eraseblock * jeb)254 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
255 {
256 	spin_lock(&c->erase_completion_lock);
257 	__jffs2_dbg_dump_jeb_nolock(jeb);
258 	spin_unlock(&c->erase_completion_lock);
259 }
260 
261 void
__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock * jeb)262 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
263 {
264 	if (!jeb)
265 		return;
266 
267 	JFFS2_DEBUG("dump space accounting for the eraseblock at %#08x:\n",
268 			jeb->offset);
269 
270 	printk(JFFS2_DBG_LVL "used_size: %#08x\n",	jeb->used_size);
271 	printk(JFFS2_DBG_LVL "dirty_size: %#08x\n",	jeb->dirty_size);
272 	printk(JFFS2_DBG_LVL "wasted_size: %#08x\n",	jeb->wasted_size);
273 	printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n",	jeb->unchecked_size);
274 	printk(JFFS2_DBG_LVL "free_size: %#08x\n",	jeb->free_size);
275 }
276 
277 void
__jffs2_dbg_dump_block_lists(struct jffs2_sb_info * c)278 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
279 {
280 	spin_lock(&c->erase_completion_lock);
281 	__jffs2_dbg_dump_block_lists_nolock(c);
282 	spin_unlock(&c->erase_completion_lock);
283 }
284 
285 void
__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info * c)286 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
287 {
288 	JFFS2_DEBUG("dump JFFS2 blocks lists:\n");
289 
290 	printk(JFFS2_DBG_LVL "flash_size: %#08x\n",	c->flash_size);
291 	printk(JFFS2_DBG_LVL "used_size: %#08x\n",	c->used_size);
292 	printk(JFFS2_DBG_LVL "dirty_size: %#08x\n",	c->dirty_size);
293 	printk(JFFS2_DBG_LVL "wasted_size: %#08x\n",	c->wasted_size);
294 	printk(JFFS2_DBG_LVL "unchecked_size: %#08x\n",	c->unchecked_size);
295 	printk(JFFS2_DBG_LVL "free_size: %#08x\n",	c->free_size);
296 	printk(JFFS2_DBG_LVL "erasing_size: %#08x\n",	c->erasing_size);
297 	printk(JFFS2_DBG_LVL "bad_size: %#08x\n",	c->bad_size);
298 	printk(JFFS2_DBG_LVL "sector_size: %#08x\n",	c->sector_size);
299 	printk(JFFS2_DBG_LVL "jffs2_reserved_blocks size: %#08x\n",
300 				c->sector_size * c->resv_blocks_write);
301 
302 	if (c->nextblock)
303 		printk(JFFS2_DBG_LVL "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
304 			"unchecked %#08x, free %#08x)\n",
305 			c->nextblock->offset, c->nextblock->used_size,
306 			c->nextblock->dirty_size, c->nextblock->wasted_size,
307 			c->nextblock->unchecked_size, c->nextblock->free_size);
308 	else
309 		printk(JFFS2_DBG_LVL "nextblock: NULL\n");
310 
311 	if (c->gcblock)
312 		printk(JFFS2_DBG_LVL "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
313 			"unchecked %#08x, free %#08x)\n",
314 			c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
315 			c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
316 	else
317 		printk(JFFS2_DBG_LVL "gcblock: NULL\n");
318 
319 	if (list_empty(&c->clean_list)) {
320 		printk(JFFS2_DBG_LVL "clean_list: empty\n");
321 	} else {
322 		struct list_head *this;
323 		int numblocks = 0;
324 		uint32_t dirty = 0;
325 
326 		list_for_each(this, &c->clean_list) {
327 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
328 			numblocks ++;
329 			dirty += jeb->wasted_size;
330 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
331 				printk(JFFS2_DBG_LVL "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
332 					"unchecked %#08x, free %#08x)\n",
333 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
334 					jeb->unchecked_size, jeb->free_size);
335 			}
336 		}
337 
338 		printk (JFFS2_DBG_LVL "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
339 			numblocks, dirty, dirty / numblocks);
340 	}
341 
342 	if (list_empty(&c->very_dirty_list)) {
343 		printk(JFFS2_DBG_LVL "very_dirty_list: empty\n");
344 	} else {
345 		struct list_head *this;
346 		int numblocks = 0;
347 		uint32_t dirty = 0;
348 
349 		list_for_each(this, &c->very_dirty_list) {
350 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
351 
352 			numblocks ++;
353 			dirty += jeb->dirty_size;
354 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
355 				printk(JFFS2_DBG_LVL "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
356 					"unchecked %#08x, free %#08x)\n",
357 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
358 					jeb->unchecked_size, jeb->free_size);
359 			}
360 		}
361 
362 		printk (JFFS2_DBG_LVL "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
363 			numblocks, dirty, dirty / numblocks);
364 	}
365 
366 	if (list_empty(&c->dirty_list)) {
367 		printk(JFFS2_DBG_LVL "dirty_list: empty\n");
368 	} else {
369 		struct list_head *this;
370 		int numblocks = 0;
371 		uint32_t dirty = 0;
372 
373 		list_for_each(this, &c->dirty_list) {
374 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
375 
376 			numblocks ++;
377 			dirty += jeb->dirty_size;
378 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
379 				printk(JFFS2_DBG_LVL "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
380 					"unchecked %#08x, free %#08x)\n",
381 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
382 					jeb->unchecked_size, jeb->free_size);
383 			}
384 		}
385 
386 		printk (JFFS2_DBG_LVL "contains %d blocks with total dirty size %u, average dirty size: %u\n",
387 			numblocks, dirty, dirty / numblocks);
388 	}
389 
390 	if (list_empty(&c->erasable_list)) {
391 		printk(JFFS2_DBG_LVL "erasable_list: empty\n");
392 	} else {
393 		struct list_head *this;
394 
395 		list_for_each(this, &c->erasable_list) {
396 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
397 
398 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
399 				printk(JFFS2_DBG_LVL "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
400 					"unchecked %#08x, free %#08x)\n",
401 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
402 					jeb->unchecked_size, jeb->free_size);
403 			}
404 		}
405 	}
406 
407 	if (list_empty(&c->erasing_list)) {
408 		printk(JFFS2_DBG_LVL "erasing_list: empty\n");
409 	} else {
410 		struct list_head *this;
411 
412 		list_for_each(this, &c->erasing_list) {
413 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
414 
415 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
416 				printk(JFFS2_DBG_LVL "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
417 					"unchecked %#08x, free %#08x)\n",
418 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
419 					jeb->unchecked_size, jeb->free_size);
420 			}
421 		}
422 	}
423 
424 	if (list_empty(&c->erase_pending_list)) {
425 		printk(JFFS2_DBG_LVL "erase_pending_list: empty\n");
426 	} else {
427 		struct list_head *this;
428 
429 		list_for_each(this, &c->erase_pending_list) {
430 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
431 
432 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
433 				printk(JFFS2_DBG_LVL "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
434 					"unchecked %#08x, free %#08x)\n",
435 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
436 					jeb->unchecked_size, jeb->free_size);
437 			}
438 		}
439 	}
440 
441 	if (list_empty(&c->erasable_pending_wbuf_list)) {
442 		printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: empty\n");
443 	} else {
444 		struct list_head *this;
445 
446 		list_for_each(this, &c->erasable_pending_wbuf_list) {
447 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
448 
449 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
450 				printk(JFFS2_DBG_LVL "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, "
451 					"wasted %#08x, unchecked %#08x, free %#08x)\n",
452 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
453 					jeb->unchecked_size, jeb->free_size);
454 			}
455 		}
456 	}
457 
458 	if (list_empty(&c->free_list)) {
459 		printk(JFFS2_DBG_LVL "free_list: empty\n");
460 	} else {
461 		struct list_head *this;
462 
463 		list_for_each(this, &c->free_list) {
464 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
465 
466 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
467 				printk(JFFS2_DBG_LVL "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
468 					"unchecked %#08x, free %#08x)\n",
469 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
470 					jeb->unchecked_size, jeb->free_size);
471 			}
472 		}
473 	}
474 
475 	if (list_empty(&c->bad_list)) {
476 		printk(JFFS2_DBG_LVL "bad_list: empty\n");
477 	} else {
478 		struct list_head *this;
479 
480 		list_for_each(this, &c->bad_list) {
481 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
482 
483 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
484 				printk(JFFS2_DBG_LVL "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
485 					"unchecked %#08x, free %#08x)\n",
486 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
487 					jeb->unchecked_size, jeb->free_size);
488 			}
489 		}
490 	}
491 
492 	if (list_empty(&c->bad_used_list)) {
493 		printk(JFFS2_DBG_LVL "bad_used_list: empty\n");
494 	} else {
495 		struct list_head *this;
496 
497 		list_for_each(this, &c->bad_used_list) {
498 			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
499 
500 			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
501 				printk(JFFS2_DBG_LVL "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, "
502 					"unchecked %#08x, free %#08x)\n",
503 					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
504 					jeb->unchecked_size, jeb->free_size);
505 			}
506 		}
507 	}
508 }
509 
510 void
__jffs2_dbg_dump_fragtree(struct jffs2_inode_info * f)511 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
512 {
513 	down(&f->sem);
514 	jffs2_dbg_dump_fragtree_nolock(f);
515 	up(&f->sem);
516 }
517 
518 void
__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info * f)519 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
520 {
521 	struct jffs2_node_frag *this = frag_first(&f->fragtree);
522 	uint32_t lastofs = 0;
523 	int buggy = 0;
524 
525 	JFFS2_DEBUG("dump fragtree of ino #%u\n", f->inocache->ino);
526 	while(this) {
527 		if (this->node)
528 			printk(JFFS2_DBG_LVL "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), "
529 				"right (%p), parent (%p)\n",
530 				this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
531 				ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
532 				frag_parent(this));
533 		else
534 			printk(JFFS2_DBG_LVL "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
535 				this->ofs, this->ofs+this->size, this, frag_left(this),
536 				frag_right(this), frag_parent(this));
537 		if (this->ofs != lastofs)
538 			buggy = 1;
539 		lastofs = this->ofs + this->size;
540 		this = frag_next(this);
541 	}
542 
543 	if (f->metadata)
544 		printk(JFFS2_DBG_LVL "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
545 
546 	if (buggy) {
547 		JFFS2_ERROR("frag tree got a hole in it.\n");
548 		BUG();
549 	}
550 }
551 
552 #define JFFS2_BUFDUMP_BYTES_PER_LINE	32
553 void
__jffs2_dbg_dump_buffer(unsigned char * buf,int len,uint32_t offs)554 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
555 {
556 	int skip;
557 	int i;
558 
559 	JFFS2_DEBUG("dump from offset %#08x to offset %#08x (%x bytes).\n",
560 		offs, offs + len, len);
561 	i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
562 	offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
563 
564 	if (skip != 0)
565 		printk(JFFS2_DBG_LVL "%#08x: ", offs);
566 
567 	while (skip--)
568 		printk("   ");
569 
570 	while (i < len) {
571 		if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
572 			if (i != 0)
573 				printk("\n");
574 			offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
575 			printk(JFFS2_DBG_LVL "%0#8x: ", offs);
576 		}
577 
578 		printk("%02x ", buf[i]);
579 
580 		i += 1;
581 	}
582 
583 	printk("\n");
584 }
585 
586 /*
587  * Dump a JFFS2 node.
588  */
589 void
__jffs2_dbg_dump_node(struct jffs2_sb_info * c,uint32_t ofs)590 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
591 {
592 	union jffs2_node_union node;
593 	int len = sizeof(union jffs2_node_union);
594 	size_t retlen;
595 	uint32_t crc;
596 	int ret;
597 
598 	JFFS2_DEBUG("dump node at offset %#08x.\n", ofs);
599 
600 	ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
601 	if (ret || (retlen != len)) {
602 		JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
603 			len, ret, retlen);
604 		return;
605 	}
606 
607 	printk(JFFS2_DBG_LVL "magic:\t%#04x\n",
608 		je16_to_cpu(node.u.magic));
609 	printk(JFFS2_DBG_LVL "nodetype:\t%#04x\n",
610 		je16_to_cpu(node.u.nodetype));
611 	printk(JFFS2_DBG_LVL "totlen:\t%#08x\n",
612 		je32_to_cpu(node.u.totlen));
613 	printk(JFFS2_DBG_LVL "hdr_crc:\t%#08x\n",
614 		je32_to_cpu(node.u.hdr_crc));
615 
616 	crc = crc32(0, &node.u, sizeof(node.u) - 4);
617 	if (crc != je32_to_cpu(node.u.hdr_crc)) {
618 		JFFS2_ERROR("wrong common header CRC.\n");
619 		return;
620 	}
621 
622 	if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
623 		je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
624 	{
625 		JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
626 			je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
627 		return;
628 	}
629 
630 	switch(je16_to_cpu(node.u.nodetype)) {
631 
632 	case JFFS2_NODETYPE_INODE:
633 
634 		printk(JFFS2_DBG_LVL "the node is inode node\n");
635 		printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
636 				je32_to_cpu(node.i.ino));
637 		printk(JFFS2_DBG_LVL "version:\t%#08x\n",
638 				je32_to_cpu(node.i.version));
639 		printk(JFFS2_DBG_LVL "mode:\t%#08x\n",
640 				node.i.mode.m);
641 		printk(JFFS2_DBG_LVL "uid:\t%#04x\n",
642 				je16_to_cpu(node.i.uid));
643 		printk(JFFS2_DBG_LVL "gid:\t%#04x\n",
644 				je16_to_cpu(node.i.gid));
645 		printk(JFFS2_DBG_LVL "isize:\t%#08x\n",
646 				je32_to_cpu(node.i.isize));
647 		printk(JFFS2_DBG_LVL "atime:\t%#08x\n",
648 				je32_to_cpu(node.i.atime));
649 		printk(JFFS2_DBG_LVL "mtime:\t%#08x\n",
650 				je32_to_cpu(node.i.mtime));
651 		printk(JFFS2_DBG_LVL "ctime:\t%#08x\n",
652 				je32_to_cpu(node.i.ctime));
653 		printk(JFFS2_DBG_LVL "offset:\t%#08x\n",
654 				je32_to_cpu(node.i.offset));
655 		printk(JFFS2_DBG_LVL "csize:\t%#08x\n",
656 				je32_to_cpu(node.i.csize));
657 		printk(JFFS2_DBG_LVL "dsize:\t%#08x\n",
658 				je32_to_cpu(node.i.dsize));
659 		printk(JFFS2_DBG_LVL "compr:\t%#02x\n",
660 				node.i.compr);
661 		printk(JFFS2_DBG_LVL "usercompr:\t%#02x\n",
662 				node.i.usercompr);
663 		printk(JFFS2_DBG_LVL "flags:\t%#04x\n",
664 				je16_to_cpu(node.i.flags));
665 		printk(JFFS2_DBG_LVL "data_crc:\t%#08x\n",
666 				je32_to_cpu(node.i.data_crc));
667 		printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
668 				je32_to_cpu(node.i.node_crc));
669 		crc = crc32(0, &node.i, sizeof(node.i) - 8);
670 		if (crc != je32_to_cpu(node.i.node_crc)) {
671 			JFFS2_ERROR("wrong node header CRC.\n");
672 			return;
673 		}
674 		break;
675 
676 	case JFFS2_NODETYPE_DIRENT:
677 
678 		printk(JFFS2_DBG_LVL "the node is dirent node\n");
679 		printk(JFFS2_DBG_LVL "pino:\t%#08x\n",
680 				je32_to_cpu(node.d.pino));
681 		printk(JFFS2_DBG_LVL "version:\t%#08x\n",
682 				je32_to_cpu(node.d.version));
683 		printk(JFFS2_DBG_LVL "ino:\t%#08x\n",
684 				je32_to_cpu(node.d.ino));
685 		printk(JFFS2_DBG_LVL "mctime:\t%#08x\n",
686 				je32_to_cpu(node.d.mctime));
687 		printk(JFFS2_DBG_LVL "nsize:\t%#02x\n",
688 				node.d.nsize);
689 		printk(JFFS2_DBG_LVL "type:\t%#02x\n",
690 				node.d.type);
691 		printk(JFFS2_DBG_LVL "node_crc:\t%#08x\n",
692 				je32_to_cpu(node.d.node_crc));
693 		printk(JFFS2_DBG_LVL "name_crc:\t%#08x\n",
694 				je32_to_cpu(node.d.name_crc));
695 
696 		node.d.name[node.d.nsize] = '\0';
697 		printk(JFFS2_DBG_LVL "name:\t\"%s\"\n", node.d.name);
698 
699 		crc = crc32(0, &node.d, sizeof(node.d) - 8);
700 		if (crc != je32_to_cpu(node.d.node_crc)) {
701 			JFFS2_ERROR("wrong node header CRC.\n");
702 			return;
703 		}
704 		break;
705 
706 	default:
707 		printk(JFFS2_DBG_LVL "node type is unknown\n");
708 		break;
709 	}
710 }
711 #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */
712