• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/fs/jffs2/
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
351	if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
352		__jffs2_dbg_superblock_counts(c);
353
354	return;
355
356error:
357	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
358	__jffs2_dbg_dump_jeb_nolock(jeb);
359	__jffs2_dbg_dump_block_lists_nolock(c);
360	BUG();
361
362}
363#endif /* JFFS2_DBG_PARANOIA_CHECKS */
364
365#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
366/*
367 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
368 */
369void
370__jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
371			   struct jffs2_eraseblock *jeb)
372{
373	spin_lock(&c->erase_completion_lock);
374	__jffs2_dbg_dump_node_refs_nolock(c, jeb);
375	spin_unlock(&c->erase_completion_lock);
376}
377
378void
379__jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
380				  struct jffs2_eraseblock *jeb)
381{
382	struct jffs2_raw_node_ref *ref;
383	int i = 0;
384
385	printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
386	if (!jeb->first_node) {
387		printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
388		return;
389	}
390
391	printk(JFFS2_DBG);
392	for (ref = jeb->first_node; ; ref = ref_next(ref)) {
393		printk("%#08x", ref_offset(ref));
394#ifdef TEST_TOTLEN
395		printk("(%x)", ref->__totlen);
396#endif
397		if (ref_next(ref))
398			printk("->");
399		else
400			break;
401		if (++i == 4) {
402			i = 0;
403			printk("\n" JFFS2_DBG);
404		}
405	}
406	printk("\n");
407}
408
409/*
410 * Dump an eraseblock's space accounting.
411 */
412void
413__jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
414{
415	spin_lock(&c->erase_completion_lock);
416	__jffs2_dbg_dump_jeb_nolock(jeb);
417	spin_unlock(&c->erase_completion_lock);
418}
419
420void
421__jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
422{
423	if (!jeb)
424		return;
425
426	printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
427			jeb->offset);
428
429	printk(JFFS2_DBG "used_size: %#08x\n",		jeb->used_size);
430	printk(JFFS2_DBG "dirty_size: %#08x\n",		jeb->dirty_size);
431	printk(JFFS2_DBG "wasted_size: %#08x\n",	jeb->wasted_size);
432	printk(JFFS2_DBG "unchecked_size: %#08x\n",	jeb->unchecked_size);
433	printk(JFFS2_DBG "free_size: %#08x\n",		jeb->free_size);
434}
435
436void
437__jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
438{
439	spin_lock(&c->erase_completion_lock);
440	__jffs2_dbg_dump_block_lists_nolock(c);
441	spin_unlock(&c->erase_completion_lock);
442}
443
444void
445__jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
446{
447	printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
448
449	printk(JFFS2_DBG "flash_size: %#08x\n",		c->flash_size);
450	printk(JFFS2_DBG "used_size: %#08x\n",		c->used_size);
451	printk(JFFS2_DBG "dirty_size: %#08x\n",		c->dirty_size);
452	printk(JFFS2_DBG "wasted_size: %#08x\n",	c->wasted_size);
453	printk(JFFS2_DBG "unchecked_size: %#08x\n",	c->unchecked_size);
454	printk(JFFS2_DBG "free_size: %#08x\n",		c->free_size);
455	printk(JFFS2_DBG "erasing_size: %#08x\n",	c->erasing_size);
456	printk(JFFS2_DBG "bad_size: %#08x\n",		c->bad_size);
457	printk(JFFS2_DBG "sector_size: %#08x\n",	c->sector_size);
458	printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
459				c->sector_size * c->resv_blocks_write);
460
461	if (c->nextblock)
462		printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
463			c->nextblock->offset, c->nextblock->used_size,
464			c->nextblock->dirty_size, c->nextblock->wasted_size,
465			c->nextblock->unchecked_size, c->nextblock->free_size);
466	else
467		printk(JFFS2_DBG "nextblock: NULL\n");
468
469	if (c->gcblock)
470		printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
471			c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
472			c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
473	else
474		printk(JFFS2_DBG "gcblock: NULL\n");
475
476	if (list_empty(&c->clean_list)) {
477		printk(JFFS2_DBG "clean_list: empty\n");
478	} else {
479		struct list_head *this;
480		int numblocks = 0;
481		uint32_t dirty = 0;
482
483		list_for_each(this, &c->clean_list) {
484			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
485			numblocks ++;
486			dirty += jeb->wasted_size;
487			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
488				printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
489					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
490					jeb->unchecked_size, jeb->free_size);
491			}
492		}
493
494		printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
495			numblocks, dirty, dirty / numblocks);
496	}
497
498	if (list_empty(&c->very_dirty_list)) {
499		printk(JFFS2_DBG "very_dirty_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->very_dirty_list) {
506			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
507
508			numblocks ++;
509			dirty += jeb->dirty_size;
510			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
511				printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
512					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
513					jeb->unchecked_size, jeb->free_size);
514			}
515		}
516
517		printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
518			numblocks, dirty, dirty / numblocks);
519	}
520
521	if (list_empty(&c->dirty_list)) {
522		printk(JFFS2_DBG "dirty_list: empty\n");
523	} else {
524		struct list_head *this;
525		int numblocks = 0;
526		uint32_t dirty = 0;
527
528		list_for_each(this, &c->dirty_list) {
529			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
530
531			numblocks ++;
532			dirty += jeb->dirty_size;
533			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
534				printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
535					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
536					jeb->unchecked_size, jeb->free_size);
537			}
538		}
539
540		printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
541			numblocks, dirty, dirty / numblocks);
542	}
543
544	if (list_empty(&c->erasable_list)) {
545		printk(JFFS2_DBG "erasable_list: empty\n");
546	} else {
547		struct list_head *this;
548
549		list_for_each(this, &c->erasable_list) {
550			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
551
552			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
553				printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
554					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
555					jeb->unchecked_size, jeb->free_size);
556			}
557		}
558	}
559
560	if (list_empty(&c->erasing_list)) {
561		printk(JFFS2_DBG "erasing_list: empty\n");
562	} else {
563		struct list_head *this;
564
565		list_for_each(this, &c->erasing_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 "erasing_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	if (list_empty(&c->erase_checking_list)) {
576		printk(JFFS2_DBG "erase_checking_list: empty\n");
577	} else {
578		struct list_head *this;
579
580		list_for_each(this, &c->erase_checking_list) {
581			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
582
583			if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
584				printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
585					jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
586					jeb->unchecked_size, jeb->free_size);
587			}
588		}
589	}
590
591	if (list_empty(&c->erase_pending_list)) {
592		printk(JFFS2_DBG "erase_pending_list: empty\n");
593	} else {
594		struct list_head *this;
595
596		list_for_each(this, &c->erase_pending_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_pending_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->erasable_pending_wbuf_list)) {
608		printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
609	} else {
610		struct list_head *this;
611
612		list_for_each(this, &c->erasable_pending_wbuf_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 "erasable_pending_wbuf_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->free_list)) {
624		printk(JFFS2_DBG "free_list: empty\n");
625	} else {
626		struct list_head *this;
627
628		list_for_each(this, &c->free_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 "free_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->bad_list)) {
640		printk(JFFS2_DBG "bad_list: empty\n");
641	} else {
642		struct list_head *this;
643
644		list_for_each(this, &c->bad_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 "bad_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_used_list)) {
656		printk(JFFS2_DBG "bad_used_list: empty\n");
657	} else {
658		struct list_head *this;
659
660		list_for_each(this, &c->bad_used_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_used_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
672void
673__jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
674{
675	mutex_lock(&f->sem);
676	jffs2_dbg_dump_fragtree_nolock(f);
677	mutex_unlock(&f->sem);
678}
679
680void
681__jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
682{
683	struct jffs2_node_frag *this = frag_first(&f->fragtree);
684	uint32_t lastofs = 0;
685	int buggy = 0;
686
687	printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
688	while(this) {
689		if (this->node)
690			printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
691				this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
692				ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
693				frag_parent(this));
694		else
695			printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
696				this->ofs, this->ofs+this->size, this, frag_left(this),
697				frag_right(this), frag_parent(this));
698		if (this->ofs != lastofs)
699			buggy = 1;
700		lastofs = this->ofs + this->size;
701		this = frag_next(this);
702	}
703
704	if (f->metadata)
705		printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
706
707	if (buggy) {
708		JFFS2_ERROR("frag tree got a hole in it.\n");
709		BUG();
710	}
711}
712
713#define JFFS2_BUFDUMP_BYTES_PER_LINE	32
714void
715__jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
716{
717	int skip;
718	int i;
719
720	printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
721		offs, offs + len, len);
722	i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
723	offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
724
725	if (skip != 0)
726		printk(JFFS2_DBG "%#08x: ", offs);
727
728	while (skip--)
729		printk("   ");
730
731	while (i < len) {
732		if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
733			if (i != 0)
734				printk("\n");
735			offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
736			printk(JFFS2_DBG "%0#8x: ", offs);
737		}
738
739		printk("%02x ", buf[i]);
740
741		i += 1;
742	}
743
744	printk("\n");
745}
746
747/*
748 * Dump a JFFS2 node.
749 */
750void
751__jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
752{
753	union jffs2_node_union node;
754	int len = sizeof(union jffs2_node_union);
755	size_t retlen;
756	uint32_t crc;
757	int ret;
758
759	printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
760
761	ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
762	if (ret || (retlen != len)) {
763		JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
764			len, ret, retlen);
765		return;
766	}
767
768	printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
769	printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
770	printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
771	printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
772
773	crc = crc32(0, &node.u, sizeof(node.u) - 4);
774	if (crc != je32_to_cpu(node.u.hdr_crc)) {
775		JFFS2_ERROR("wrong common header CRC.\n");
776		return;
777	}
778
779	if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
780		je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
781	{
782		JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
783			je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
784		return;
785	}
786
787	switch(je16_to_cpu(node.u.nodetype)) {
788
789	case JFFS2_NODETYPE_INODE:
790
791		printk(JFFS2_DBG "the node is inode node\n");
792		printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
793		printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
794		printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
795		printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
796		printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
797		printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
798		printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
799		printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
800		printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
801		printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
802		printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
803		printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
804		printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
805		printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
806		printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
807		printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
808		printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
809
810		crc = crc32(0, &node.i, sizeof(node.i) - 8);
811		if (crc != je32_to_cpu(node.i.node_crc)) {
812			JFFS2_ERROR("wrong node header CRC.\n");
813			return;
814		}
815		break;
816
817	case JFFS2_NODETYPE_DIRENT:
818
819		printk(JFFS2_DBG "the node is dirent node\n");
820		printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
821		printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
822		printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
823		printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
824		printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
825		printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
826		printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
827		printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
828
829		node.d.name[node.d.nsize] = '\0';
830		printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
831
832		crc = crc32(0, &node.d, sizeof(node.d) - 8);
833		if (crc != je32_to_cpu(node.d.node_crc)) {
834			JFFS2_ERROR("wrong node header CRC.\n");
835			return;
836		}
837		break;
838
839	default:
840		printk(JFFS2_DBG "node type is unknown\n");
841		break;
842	}
843}
844#endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */
845