Linux Audio

Check our new training course

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