asus-laptop: Add support for P30/P35
[linux-2.6/mini2440.git] / fs / jffs2 / debug.c
blob5544d31c066be22fb25cc857df3691de8e420ea6
1 /*
2 * JFFS2 -- Journalling Flash File System, Version 2.
4 * Copyright © 2001-2007 Red Hat, Inc.
6 * Created by David Woodhouse <dwmw2@infradead.org>
8 * For licensing information, see the file 'LICENCE' in this directory.
12 #include <linux/kernel.h>
13 #include <linux/types.h>
14 #include <linux/pagemap.h>
15 #include <linux/crc32.h>
16 #include <linux/jffs2.h>
17 #include <linux/mtd/mtd.h>
18 #include "nodelist.h"
19 #include "debug.h"
21 #ifdef JFFS2_DBG_SANITY_CHECKS
23 void
24 __jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c,
25 struct jffs2_eraseblock *jeb)
27 if (unlikely(jeb && jeb->used_size + jeb->dirty_size +
28 jeb->free_size + jeb->wasted_size +
29 jeb->unchecked_size != c->sector_size)) {
30 JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset);
31 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
32 jeb->free_size, jeb->dirty_size, jeb->used_size,
33 jeb->wasted_size, jeb->unchecked_size, c->sector_size);
34 BUG();
37 if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size
38 + c->wasted_size + c->unchecked_size != c->flash_size)) {
39 JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n");
40 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
41 c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size,
42 c->wasted_size, c->unchecked_size, c->flash_size);
43 BUG();
47 void
48 __jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
49 struct jffs2_eraseblock *jeb)
51 spin_lock(&c->erase_completion_lock);
52 jffs2_dbg_acct_sanity_check_nolock(c, jeb);
53 spin_unlock(&c->erase_completion_lock);
56 #endif /* JFFS2_DBG_SANITY_CHECKS */
58 #ifdef JFFS2_DBG_PARANOIA_CHECKS
60 * Check the fragtree.
62 void
63 __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
65 mutex_lock(&f->sem);
66 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
67 mutex_unlock(&f->sem);
70 void
71 __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
73 struct jffs2_node_frag *frag;
74 int bitched = 0;
76 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
77 struct jffs2_full_dnode *fn = frag->node;
79 if (!fn || !fn->raw)
80 continue;
82 if (ref_flags(fn->raw) == REF_PRISTINE) {
83 if (fn->frags > 1) {
84 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
85 ref_offset(fn->raw), fn->frags);
86 bitched = 1;
89 /* A hole node which isn't multi-page should be garbage-collected
90 and merged anyway, so we just check for the frag size here,
91 rather than mucking around with actually reading the node
92 and checking the compression type, which is the real way
93 to tell a hole node. */
94 if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
95 && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
96 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2.\n",
97 ref_offset(fn->raw));
98 bitched = 1;
101 if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
102 && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
103 JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2.\n",
104 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
105 bitched = 1;
110 if (bitched) {
111 JFFS2_ERROR("fragtree is corrupted.\n");
112 __jffs2_dbg_dump_fragtree_nolock(f);
113 BUG();
118 * Check if the flash contains all 0xFF before we start writing.
120 void
121 __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
122 uint32_t ofs, int len)
124 size_t retlen;
125 int ret, i;
126 unsigned char *buf;
128 buf = kmalloc(len, GFP_KERNEL);
129 if (!buf)
130 return;
132 ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
133 if (ret || (retlen != len)) {
134 JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
135 len, ret, retlen);
136 kfree(buf);
137 return;
140 ret = 0;
141 for (i = 0; i < len; i++)
142 if (buf[i] != 0xff)
143 ret = 1;
145 if (ret) {
146 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",
147 ofs, ofs + i);
148 __jffs2_dbg_dump_buffer(buf, len, ofs);
149 kfree(buf);
150 BUG();
153 kfree(buf);
156 void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
158 struct jffs2_eraseblock *jeb;
159 uint32_t free = 0, dirty = 0, used = 0, wasted = 0,
160 erasing = 0, bad = 0, unchecked = 0;
161 int nr_counted = 0;
162 int dump = 0;
164 if (c->gcblock) {
165 nr_counted++;
166 free += c->gcblock->free_size;
167 dirty += c->gcblock->dirty_size;
168 used += c->gcblock->used_size;
169 wasted += c->gcblock->wasted_size;
170 unchecked += c->gcblock->unchecked_size;
172 if (c->nextblock) {
173 nr_counted++;
174 free += c->nextblock->free_size;
175 dirty += c->nextblock->dirty_size;
176 used += c->nextblock->used_size;
177 wasted += c->nextblock->wasted_size;
178 unchecked += c->nextblock->unchecked_size;
180 list_for_each_entry(jeb, &c->clean_list, list) {
181 nr_counted++;
182 free += jeb->free_size;
183 dirty += jeb->dirty_size;
184 used += jeb->used_size;
185 wasted += jeb->wasted_size;
186 unchecked += jeb->unchecked_size;
188 list_for_each_entry(jeb, &c->very_dirty_list, list) {
189 nr_counted++;
190 free += jeb->free_size;
191 dirty += jeb->dirty_size;
192 used += jeb->used_size;
193 wasted += jeb->wasted_size;
194 unchecked += jeb->unchecked_size;
196 list_for_each_entry(jeb, &c->dirty_list, list) {
197 nr_counted++;
198 free += jeb->free_size;
199 dirty += jeb->dirty_size;
200 used += jeb->used_size;
201 wasted += jeb->wasted_size;
202 unchecked += jeb->unchecked_size;
204 list_for_each_entry(jeb, &c->erasable_list, list) {
205 nr_counted++;
206 free += jeb->free_size;
207 dirty += jeb->dirty_size;
208 used += jeb->used_size;
209 wasted += jeb->wasted_size;
210 unchecked += jeb->unchecked_size;
212 list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) {
213 nr_counted++;
214 free += jeb->free_size;
215 dirty += jeb->dirty_size;
216 used += jeb->used_size;
217 wasted += jeb->wasted_size;
218 unchecked += jeb->unchecked_size;
220 list_for_each_entry(jeb, &c->erase_pending_list, list) {
221 nr_counted++;
222 free += jeb->free_size;
223 dirty += jeb->dirty_size;
224 used += jeb->used_size;
225 wasted += jeb->wasted_size;
226 unchecked += jeb->unchecked_size;
228 list_for_each_entry(jeb, &c->free_list, list) {
229 nr_counted++;
230 free += jeb->free_size;
231 dirty += jeb->dirty_size;
232 used += jeb->used_size;
233 wasted += jeb->wasted_size;
234 unchecked += jeb->unchecked_size;
236 list_for_each_entry(jeb, &c->bad_used_list, list) {
237 nr_counted++;
238 free += jeb->free_size;
239 dirty += jeb->dirty_size;
240 used += jeb->used_size;
241 wasted += jeb->wasted_size;
242 unchecked += jeb->unchecked_size;
245 list_for_each_entry(jeb, &c->erasing_list, list) {
246 nr_counted++;
247 erasing += c->sector_size;
249 list_for_each_entry(jeb, &c->erase_checking_list, list) {
250 nr_counted++;
251 erasing += c->sector_size;
253 list_for_each_entry(jeb, &c->erase_complete_list, list) {
254 nr_counted++;
255 erasing += c->sector_size;
257 list_for_each_entry(jeb, &c->bad_list, list) {
258 nr_counted++;
259 bad += c->sector_size;
262 #define check(sz) \
263 if (sz != c->sz##_size) { \
264 printk(KERN_WARNING #sz "_size mismatch counted 0x%x, c->" #sz "_size 0x%x\n", \
265 sz, c->sz##_size); \
266 dump = 1; \
268 check(free);
269 check(dirty);
270 check(used);
271 check(wasted);
272 check(unchecked);
273 check(bad);
274 check(erasing);
275 #undef check
277 if (nr_counted != c->nr_blocks) {
278 printk(KERN_WARNING "%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
279 __func__, nr_counted, c->nr_blocks);
280 dump = 1;
283 if (dump) {
284 __jffs2_dbg_dump_block_lists_nolock(c);
285 BUG();
290 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
292 void
293 __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
294 struct jffs2_eraseblock *jeb)
296 spin_lock(&c->erase_completion_lock);
297 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
298 spin_unlock(&c->erase_completion_lock);
301 void
302 __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
303 struct jffs2_eraseblock *jeb)
305 uint32_t my_used_size = 0;
306 uint32_t my_unchecked_size = 0;
307 uint32_t my_dirty_size = 0;
308 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
310 while (ref2) {
311 uint32_t totlen = ref_totlen(c, jeb, ref2);
313 if (ref_offset(ref2) < jeb->offset ||
314 ref_offset(ref2) > jeb->offset + c->sector_size) {
315 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
316 ref_offset(ref2), jeb->offset);
317 goto error;
320 if (ref_flags(ref2) == REF_UNCHECKED)
321 my_unchecked_size += totlen;
322 else if (!ref_obsolete(ref2))
323 my_used_size += totlen;
324 else
325 my_dirty_size += totlen;
327 if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
328 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
329 ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
330 ref_offset(jeb->last_node), jeb->last_node);
331 goto error;
333 ref2 = ref_next(ref2);
336 if (my_used_size != jeb->used_size) {
337 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
338 my_used_size, jeb->used_size);
339 goto error;
342 if (my_unchecked_size != jeb->unchecked_size) {
343 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
344 my_unchecked_size, jeb->unchecked_size);
345 goto error;
348 #if 0
349 /* This should work when we implement ref->__totlen elemination */
350 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
351 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
352 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
353 goto error;
356 if (jeb->free_size == 0
357 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
358 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
359 my_used_size + my_unchecked_size + my_dirty_size,
360 c->sector_size);
361 goto error;
363 #endif
365 if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
366 __jffs2_dbg_superblock_counts(c);
368 return;
370 error:
371 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
372 __jffs2_dbg_dump_jeb_nolock(jeb);
373 __jffs2_dbg_dump_block_lists_nolock(c);
374 BUG();
377 #endif /* JFFS2_DBG_PARANOIA_CHECKS */
379 #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
381 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
383 void
384 __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
385 struct jffs2_eraseblock *jeb)
387 spin_lock(&c->erase_completion_lock);
388 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
389 spin_unlock(&c->erase_completion_lock);
392 void
393 __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
394 struct jffs2_eraseblock *jeb)
396 struct jffs2_raw_node_ref *ref;
397 int i = 0;
399 printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
400 if (!jeb->first_node) {
401 printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
402 return;
405 printk(JFFS2_DBG);
406 for (ref = jeb->first_node; ; ref = ref_next(ref)) {
407 printk("%#08x", ref_offset(ref));
408 #ifdef TEST_TOTLEN
409 printk("(%x)", ref->__totlen);
410 #endif
411 if (ref_next(ref))
412 printk("->");
413 else
414 break;
415 if (++i == 4) {
416 i = 0;
417 printk("\n" JFFS2_DBG);
420 printk("\n");
424 * Dump an eraseblock's space accounting.
426 void
427 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
429 spin_lock(&c->erase_completion_lock);
430 __jffs2_dbg_dump_jeb_nolock(jeb);
431 spin_unlock(&c->erase_completion_lock);
434 void
435 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
437 if (!jeb)
438 return;
440 printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
441 jeb->offset);
443 printk(JFFS2_DBG "used_size: %#08x\n", jeb->used_size);
444 printk(JFFS2_DBG "dirty_size: %#08x\n", jeb->dirty_size);
445 printk(JFFS2_DBG "wasted_size: %#08x\n", jeb->wasted_size);
446 printk(JFFS2_DBG "unchecked_size: %#08x\n", jeb->unchecked_size);
447 printk(JFFS2_DBG "free_size: %#08x\n", jeb->free_size);
450 void
451 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
453 spin_lock(&c->erase_completion_lock);
454 __jffs2_dbg_dump_block_lists_nolock(c);
455 spin_unlock(&c->erase_completion_lock);
458 void
459 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
461 printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
463 printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size);
464 printk(JFFS2_DBG "used_size: %#08x\n", c->used_size);
465 printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size);
466 printk(JFFS2_DBG "wasted_size: %#08x\n", c->wasted_size);
467 printk(JFFS2_DBG "unchecked_size: %#08x\n", c->unchecked_size);
468 printk(JFFS2_DBG "free_size: %#08x\n", c->free_size);
469 printk(JFFS2_DBG "erasing_size: %#08x\n", c->erasing_size);
470 printk(JFFS2_DBG "bad_size: %#08x\n", c->bad_size);
471 printk(JFFS2_DBG "sector_size: %#08x\n", c->sector_size);
472 printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
473 c->sector_size * c->resv_blocks_write);
475 if (c->nextblock)
476 printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
477 c->nextblock->offset, c->nextblock->used_size,
478 c->nextblock->dirty_size, c->nextblock->wasted_size,
479 c->nextblock->unchecked_size, c->nextblock->free_size);
480 else
481 printk(JFFS2_DBG "nextblock: NULL\n");
483 if (c->gcblock)
484 printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
485 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
486 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
487 else
488 printk(JFFS2_DBG "gcblock: NULL\n");
490 if (list_empty(&c->clean_list)) {
491 printk(JFFS2_DBG "clean_list: empty\n");
492 } else {
493 struct list_head *this;
494 int numblocks = 0;
495 uint32_t dirty = 0;
497 list_for_each(this, &c->clean_list) {
498 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
499 numblocks ++;
500 dirty += jeb->wasted_size;
501 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
502 printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
503 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
504 jeb->unchecked_size, jeb->free_size);
508 printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
509 numblocks, dirty, dirty / numblocks);
512 if (list_empty(&c->very_dirty_list)) {
513 printk(JFFS2_DBG "very_dirty_list: empty\n");
514 } else {
515 struct list_head *this;
516 int numblocks = 0;
517 uint32_t dirty = 0;
519 list_for_each(this, &c->very_dirty_list) {
520 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
522 numblocks ++;
523 dirty += jeb->dirty_size;
524 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
525 printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
526 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
527 jeb->unchecked_size, jeb->free_size);
531 printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
532 numblocks, dirty, dirty / numblocks);
535 if (list_empty(&c->dirty_list)) {
536 printk(JFFS2_DBG "dirty_list: empty\n");
537 } else {
538 struct list_head *this;
539 int numblocks = 0;
540 uint32_t dirty = 0;
542 list_for_each(this, &c->dirty_list) {
543 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
545 numblocks ++;
546 dirty += jeb->dirty_size;
547 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
548 printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
549 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
550 jeb->unchecked_size, jeb->free_size);
554 printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
555 numblocks, dirty, dirty / numblocks);
558 if (list_empty(&c->erasable_list)) {
559 printk(JFFS2_DBG "erasable_list: empty\n");
560 } else {
561 struct list_head *this;
563 list_for_each(this, &c->erasable_list) {
564 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
566 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
567 printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
568 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
569 jeb->unchecked_size, jeb->free_size);
574 if (list_empty(&c->erasing_list)) {
575 printk(JFFS2_DBG "erasing_list: empty\n");
576 } else {
577 struct list_head *this;
579 list_for_each(this, &c->erasing_list) {
580 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
582 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
583 printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
584 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
585 jeb->unchecked_size, jeb->free_size);
589 if (list_empty(&c->erase_checking_list)) {
590 printk(JFFS2_DBG "erase_checking_list: empty\n");
591 } else {
592 struct list_head *this;
594 list_for_each(this, &c->erase_checking_list) {
595 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
597 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
598 printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
599 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
600 jeb->unchecked_size, jeb->free_size);
605 if (list_empty(&c->erase_pending_list)) {
606 printk(JFFS2_DBG "erase_pending_list: empty\n");
607 } else {
608 struct list_head *this;
610 list_for_each(this, &c->erase_pending_list) {
611 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
613 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
614 printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
615 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
616 jeb->unchecked_size, jeb->free_size);
621 if (list_empty(&c->erasable_pending_wbuf_list)) {
622 printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
623 } else {
624 struct list_head *this;
626 list_for_each(this, &c->erasable_pending_wbuf_list) {
627 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
629 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
630 printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
631 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
632 jeb->unchecked_size, jeb->free_size);
637 if (list_empty(&c->free_list)) {
638 printk(JFFS2_DBG "free_list: empty\n");
639 } else {
640 struct list_head *this;
642 list_for_each(this, &c->free_list) {
643 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
645 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
646 printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
647 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
648 jeb->unchecked_size, jeb->free_size);
653 if (list_empty(&c->bad_list)) {
654 printk(JFFS2_DBG "bad_list: empty\n");
655 } else {
656 struct list_head *this;
658 list_for_each(this, &c->bad_list) {
659 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
661 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
662 printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
663 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
664 jeb->unchecked_size, jeb->free_size);
669 if (list_empty(&c->bad_used_list)) {
670 printk(JFFS2_DBG "bad_used_list: empty\n");
671 } else {
672 struct list_head *this;
674 list_for_each(this, &c->bad_used_list) {
675 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
677 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
678 printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
679 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
680 jeb->unchecked_size, jeb->free_size);
686 void
687 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
689 mutex_lock(&f->sem);
690 jffs2_dbg_dump_fragtree_nolock(f);
691 mutex_unlock(&f->sem);
694 void
695 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
697 struct jffs2_node_frag *this = frag_first(&f->fragtree);
698 uint32_t lastofs = 0;
699 int buggy = 0;
701 printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
702 while(this) {
703 if (this->node)
704 printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
705 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
706 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
707 frag_parent(this));
708 else
709 printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
710 this->ofs, this->ofs+this->size, this, frag_left(this),
711 frag_right(this), frag_parent(this));
712 if (this->ofs != lastofs)
713 buggy = 1;
714 lastofs = this->ofs + this->size;
715 this = frag_next(this);
718 if (f->metadata)
719 printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
721 if (buggy) {
722 JFFS2_ERROR("frag tree got a hole in it.\n");
723 BUG();
727 #define JFFS2_BUFDUMP_BYTES_PER_LINE 32
728 void
729 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
731 int skip;
732 int i;
734 printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
735 offs, offs + len, len);
736 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
737 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
739 if (skip != 0)
740 printk(JFFS2_DBG "%#08x: ", offs);
742 while (skip--)
743 printk(" ");
745 while (i < len) {
746 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
747 if (i != 0)
748 printk("\n");
749 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
750 printk(JFFS2_DBG "%0#8x: ", offs);
753 printk("%02x ", buf[i]);
755 i += 1;
758 printk("\n");
762 * Dump a JFFS2 node.
764 void
765 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
767 union jffs2_node_union node;
768 int len = sizeof(union jffs2_node_union);
769 size_t retlen;
770 uint32_t crc;
771 int ret;
773 printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
775 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
776 if (ret || (retlen != len)) {
777 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
778 len, ret, retlen);
779 return;
782 printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
783 printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
784 printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
785 printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
787 crc = crc32(0, &node.u, sizeof(node.u) - 4);
788 if (crc != je32_to_cpu(node.u.hdr_crc)) {
789 JFFS2_ERROR("wrong common header CRC.\n");
790 return;
793 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
794 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
796 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
797 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
798 return;
801 switch(je16_to_cpu(node.u.nodetype)) {
803 case JFFS2_NODETYPE_INODE:
805 printk(JFFS2_DBG "the node is inode node\n");
806 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
807 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
808 printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
809 printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
810 printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
811 printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
812 printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
813 printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
814 printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
815 printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
816 printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
817 printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
818 printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
819 printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
820 printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
821 printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
822 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
824 crc = crc32(0, &node.i, sizeof(node.i) - 8);
825 if (crc != je32_to_cpu(node.i.node_crc)) {
826 JFFS2_ERROR("wrong node header CRC.\n");
827 return;
829 break;
831 case JFFS2_NODETYPE_DIRENT:
833 printk(JFFS2_DBG "the node is dirent node\n");
834 printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
835 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
836 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
837 printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
838 printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
839 printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
840 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
841 printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
843 node.d.name[node.d.nsize] = '\0';
844 printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
846 crc = crc32(0, &node.d, sizeof(node.d) - 8);
847 if (crc != je32_to_cpu(node.d.node_crc)) {
848 JFFS2_ERROR("wrong node header CRC.\n");
849 return;
851 break;
853 default:
854 printk(JFFS2_DBG "node type is unknown\n");
855 break;
858 #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */