Merge master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / jffs2 / debug.c
blobec3538413926f677feb3d763df9a7ebaa5d7a07d
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 <linux/slab.h>
19 #include "nodelist.h"
20 #include "debug.h"
22 #ifdef JFFS2_DBG_SANITY_CHECKS
24 void
25 __jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c,
26 struct jffs2_eraseblock *jeb)
28 if (unlikely(jeb && jeb->used_size + jeb->dirty_size +
29 jeb->free_size + jeb->wasted_size +
30 jeb->unchecked_size != c->sector_size)) {
31 JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset);
32 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
33 jeb->free_size, jeb->dirty_size, jeb->used_size,
34 jeb->wasted_size, jeb->unchecked_size, c->sector_size);
35 BUG();
38 if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size
39 + c->wasted_size + c->unchecked_size != c->flash_size)) {
40 JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n");
41 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
42 c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size,
43 c->wasted_size, c->unchecked_size, c->flash_size);
44 BUG();
48 void
49 __jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
50 struct jffs2_eraseblock *jeb)
52 spin_lock(&c->erase_completion_lock);
53 jffs2_dbg_acct_sanity_check_nolock(c, jeb);
54 spin_unlock(&c->erase_completion_lock);
57 #endif /* JFFS2_DBG_SANITY_CHECKS */
59 #ifdef JFFS2_DBG_PARANOIA_CHECKS
61 * Check the fragtree.
63 void
64 __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
66 mutex_lock(&f->sem);
67 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
68 mutex_unlock(&f->sem);
71 void
72 __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
74 struct jffs2_node_frag *frag;
75 int bitched = 0;
77 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
78 struct jffs2_full_dnode *fn = frag->node;
80 if (!fn || !fn->raw)
81 continue;
83 if (ref_flags(fn->raw) == REF_PRISTINE) {
84 if (fn->frags > 1) {
85 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
86 ref_offset(fn->raw), fn->frags);
87 bitched = 1;
90 /* A hole node which isn't multi-page should be garbage-collected
91 and merged anyway, so we just check for the frag size here,
92 rather than mucking around with actually reading the node
93 and checking the compression type, which is the real way
94 to tell a hole node. */
95 if (frag->ofs & (PAGE_CACHE_SIZE-1) && frag_prev(frag)
96 && frag_prev(frag)->size < PAGE_CACHE_SIZE && frag_prev(frag)->node) {
97 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2.\n",
98 ref_offset(fn->raw));
99 bitched = 1;
102 if ((frag->ofs+frag->size) & (PAGE_CACHE_SIZE-1) && frag_next(frag)
103 && frag_next(frag)->size < PAGE_CACHE_SIZE && frag_next(frag)->node) {
104 JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2.\n",
105 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
106 bitched = 1;
111 if (bitched) {
112 JFFS2_ERROR("fragtree is corrupted.\n");
113 __jffs2_dbg_dump_fragtree_nolock(f);
114 BUG();
119 * Check if the flash contains all 0xFF before we start writing.
121 void
122 __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
123 uint32_t ofs, int len)
125 size_t retlen;
126 int ret, i;
127 unsigned char *buf;
129 buf = kmalloc(len, GFP_KERNEL);
130 if (!buf)
131 return;
133 ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
134 if (ret || (retlen != len)) {
135 JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
136 len, ret, retlen);
137 kfree(buf);
138 return;
141 ret = 0;
142 for (i = 0; i < len; i++)
143 if (buf[i] != 0xff)
144 ret = 1;
146 if (ret) {
147 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",
148 ofs, ofs + i);
149 __jffs2_dbg_dump_buffer(buf, len, ofs);
150 kfree(buf);
151 BUG();
154 kfree(buf);
157 void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
159 struct jffs2_eraseblock *jeb;
160 uint32_t free = 0, dirty = 0, used = 0, wasted = 0,
161 erasing = 0, bad = 0, unchecked = 0;
162 int nr_counted = 0;
163 int dump = 0;
165 if (c->gcblock) {
166 nr_counted++;
167 free += c->gcblock->free_size;
168 dirty += c->gcblock->dirty_size;
169 used += c->gcblock->used_size;
170 wasted += c->gcblock->wasted_size;
171 unchecked += c->gcblock->unchecked_size;
173 if (c->nextblock) {
174 nr_counted++;
175 free += c->nextblock->free_size;
176 dirty += c->nextblock->dirty_size;
177 used += c->nextblock->used_size;
178 wasted += c->nextblock->wasted_size;
179 unchecked += c->nextblock->unchecked_size;
181 list_for_each_entry(jeb, &c->clean_list, list) {
182 nr_counted++;
183 free += jeb->free_size;
184 dirty += jeb->dirty_size;
185 used += jeb->used_size;
186 wasted += jeb->wasted_size;
187 unchecked += jeb->unchecked_size;
189 list_for_each_entry(jeb, &c->very_dirty_list, list) {
190 nr_counted++;
191 free += jeb->free_size;
192 dirty += jeb->dirty_size;
193 used += jeb->used_size;
194 wasted += jeb->wasted_size;
195 unchecked += jeb->unchecked_size;
197 list_for_each_entry(jeb, &c->dirty_list, list) {
198 nr_counted++;
199 free += jeb->free_size;
200 dirty += jeb->dirty_size;
201 used += jeb->used_size;
202 wasted += jeb->wasted_size;
203 unchecked += jeb->unchecked_size;
205 list_for_each_entry(jeb, &c->erasable_list, list) {
206 nr_counted++;
207 free += jeb->free_size;
208 dirty += jeb->dirty_size;
209 used += jeb->used_size;
210 wasted += jeb->wasted_size;
211 unchecked += jeb->unchecked_size;
213 list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) {
214 nr_counted++;
215 free += jeb->free_size;
216 dirty += jeb->dirty_size;
217 used += jeb->used_size;
218 wasted += jeb->wasted_size;
219 unchecked += jeb->unchecked_size;
221 list_for_each_entry(jeb, &c->erase_pending_list, list) {
222 nr_counted++;
223 free += jeb->free_size;
224 dirty += jeb->dirty_size;
225 used += jeb->used_size;
226 wasted += jeb->wasted_size;
227 unchecked += jeb->unchecked_size;
229 list_for_each_entry(jeb, &c->free_list, list) {
230 nr_counted++;
231 free += jeb->free_size;
232 dirty += jeb->dirty_size;
233 used += jeb->used_size;
234 wasted += jeb->wasted_size;
235 unchecked += jeb->unchecked_size;
237 list_for_each_entry(jeb, &c->bad_used_list, list) {
238 nr_counted++;
239 free += jeb->free_size;
240 dirty += jeb->dirty_size;
241 used += jeb->used_size;
242 wasted += jeb->wasted_size;
243 unchecked += jeb->unchecked_size;
246 list_for_each_entry(jeb, &c->erasing_list, list) {
247 nr_counted++;
248 erasing += c->sector_size;
250 list_for_each_entry(jeb, &c->erase_checking_list, list) {
251 nr_counted++;
252 erasing += c->sector_size;
254 list_for_each_entry(jeb, &c->erase_complete_list, list) {
255 nr_counted++;
256 erasing += c->sector_size;
258 list_for_each_entry(jeb, &c->bad_list, list) {
259 nr_counted++;
260 bad += c->sector_size;
263 #define check(sz) \
264 if (sz != c->sz##_size) { \
265 printk(KERN_WARNING #sz "_size mismatch counted 0x%x, c->" #sz "_size 0x%x\n", \
266 sz, c->sz##_size); \
267 dump = 1; \
269 check(free);
270 check(dirty);
271 check(used);
272 check(wasted);
273 check(unchecked);
274 check(bad);
275 check(erasing);
276 #undef check
278 if (nr_counted != c->nr_blocks) {
279 printk(KERN_WARNING "%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
280 __func__, nr_counted, c->nr_blocks);
281 dump = 1;
284 if (dump) {
285 __jffs2_dbg_dump_block_lists_nolock(c);
286 BUG();
291 * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'.
293 void
294 __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
295 struct jffs2_eraseblock *jeb)
297 spin_lock(&c->erase_completion_lock);
298 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
299 spin_unlock(&c->erase_completion_lock);
302 void
303 __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
304 struct jffs2_eraseblock *jeb)
306 uint32_t my_used_size = 0;
307 uint32_t my_unchecked_size = 0;
308 uint32_t my_dirty_size = 0;
309 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
311 while (ref2) {
312 uint32_t totlen = ref_totlen(c, jeb, ref2);
314 if (ref_offset(ref2) < jeb->offset ||
315 ref_offset(ref2) > jeb->offset + c->sector_size) {
316 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
317 ref_offset(ref2), jeb->offset);
318 goto error;
321 if (ref_flags(ref2) == REF_UNCHECKED)
322 my_unchecked_size += totlen;
323 else if (!ref_obsolete(ref2))
324 my_used_size += totlen;
325 else
326 my_dirty_size += totlen;
328 if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
329 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
330 ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
331 ref_offset(jeb->last_node), jeb->last_node);
332 goto error;
334 ref2 = ref_next(ref2);
337 if (my_used_size != jeb->used_size) {
338 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
339 my_used_size, jeb->used_size);
340 goto error;
343 if (my_unchecked_size != jeb->unchecked_size) {
344 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
345 my_unchecked_size, jeb->unchecked_size);
346 goto error;
349 #if 0
350 /* This should work when we implement ref->__totlen elemination */
351 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
352 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
353 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
354 goto error;
357 if (jeb->free_size == 0
358 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
359 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
360 my_used_size + my_unchecked_size + my_dirty_size,
361 c->sector_size);
362 goto error;
364 #endif
366 if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
367 __jffs2_dbg_superblock_counts(c);
369 return;
371 error:
372 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
373 __jffs2_dbg_dump_jeb_nolock(jeb);
374 __jffs2_dbg_dump_block_lists_nolock(c);
375 BUG();
378 #endif /* JFFS2_DBG_PARANOIA_CHECKS */
380 #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
382 * Dump the node_refs of the 'jeb' JFFS2 eraseblock.
384 void
385 __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
386 struct jffs2_eraseblock *jeb)
388 spin_lock(&c->erase_completion_lock);
389 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
390 spin_unlock(&c->erase_completion_lock);
393 void
394 __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
395 struct jffs2_eraseblock *jeb)
397 struct jffs2_raw_node_ref *ref;
398 int i = 0;
400 printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
401 if (!jeb->first_node) {
402 printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
403 return;
406 printk(JFFS2_DBG);
407 for (ref = jeb->first_node; ; ref = ref_next(ref)) {
408 printk("%#08x", ref_offset(ref));
409 #ifdef TEST_TOTLEN
410 printk("(%x)", ref->__totlen);
411 #endif
412 if (ref_next(ref))
413 printk("->");
414 else
415 break;
416 if (++i == 4) {
417 i = 0;
418 printk("\n" JFFS2_DBG);
421 printk("\n");
425 * Dump an eraseblock's space accounting.
427 void
428 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
430 spin_lock(&c->erase_completion_lock);
431 __jffs2_dbg_dump_jeb_nolock(jeb);
432 spin_unlock(&c->erase_completion_lock);
435 void
436 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
438 if (!jeb)
439 return;
441 printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
442 jeb->offset);
444 printk(JFFS2_DBG "used_size: %#08x\n", jeb->used_size);
445 printk(JFFS2_DBG "dirty_size: %#08x\n", jeb->dirty_size);
446 printk(JFFS2_DBG "wasted_size: %#08x\n", jeb->wasted_size);
447 printk(JFFS2_DBG "unchecked_size: %#08x\n", jeb->unchecked_size);
448 printk(JFFS2_DBG "free_size: %#08x\n", jeb->free_size);
451 void
452 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
454 spin_lock(&c->erase_completion_lock);
455 __jffs2_dbg_dump_block_lists_nolock(c);
456 spin_unlock(&c->erase_completion_lock);
459 void
460 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
462 printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
464 printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size);
465 printk(JFFS2_DBG "used_size: %#08x\n", c->used_size);
466 printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size);
467 printk(JFFS2_DBG "wasted_size: %#08x\n", c->wasted_size);
468 printk(JFFS2_DBG "unchecked_size: %#08x\n", c->unchecked_size);
469 printk(JFFS2_DBG "free_size: %#08x\n", c->free_size);
470 printk(JFFS2_DBG "erasing_size: %#08x\n", c->erasing_size);
471 printk(JFFS2_DBG "bad_size: %#08x\n", c->bad_size);
472 printk(JFFS2_DBG "sector_size: %#08x\n", c->sector_size);
473 printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
474 c->sector_size * c->resv_blocks_write);
476 if (c->nextblock)
477 printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
478 c->nextblock->offset, c->nextblock->used_size,
479 c->nextblock->dirty_size, c->nextblock->wasted_size,
480 c->nextblock->unchecked_size, c->nextblock->free_size);
481 else
482 printk(JFFS2_DBG "nextblock: NULL\n");
484 if (c->gcblock)
485 printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
486 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
487 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
488 else
489 printk(JFFS2_DBG "gcblock: NULL\n");
491 if (list_empty(&c->clean_list)) {
492 printk(JFFS2_DBG "clean_list: empty\n");
493 } else {
494 struct list_head *this;
495 int numblocks = 0;
496 uint32_t dirty = 0;
498 list_for_each(this, &c->clean_list) {
499 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
500 numblocks ++;
501 dirty += jeb->wasted_size;
502 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
503 printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
504 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
505 jeb->unchecked_size, jeb->free_size);
509 printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
510 numblocks, dirty, dirty / numblocks);
513 if (list_empty(&c->very_dirty_list)) {
514 printk(JFFS2_DBG "very_dirty_list: empty\n");
515 } else {
516 struct list_head *this;
517 int numblocks = 0;
518 uint32_t dirty = 0;
520 list_for_each(this, &c->very_dirty_list) {
521 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
523 numblocks ++;
524 dirty += jeb->dirty_size;
525 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
526 printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
527 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
528 jeb->unchecked_size, jeb->free_size);
532 printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
533 numblocks, dirty, dirty / numblocks);
536 if (list_empty(&c->dirty_list)) {
537 printk(JFFS2_DBG "dirty_list: empty\n");
538 } else {
539 struct list_head *this;
540 int numblocks = 0;
541 uint32_t dirty = 0;
543 list_for_each(this, &c->dirty_list) {
544 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
546 numblocks ++;
547 dirty += jeb->dirty_size;
548 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
549 printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
550 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
551 jeb->unchecked_size, jeb->free_size);
555 printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
556 numblocks, dirty, dirty / numblocks);
559 if (list_empty(&c->erasable_list)) {
560 printk(JFFS2_DBG "erasable_list: empty\n");
561 } else {
562 struct list_head *this;
564 list_for_each(this, &c->erasable_list) {
565 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
567 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
568 printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
569 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
570 jeb->unchecked_size, jeb->free_size);
575 if (list_empty(&c->erasing_list)) {
576 printk(JFFS2_DBG "erasing_list: empty\n");
577 } else {
578 struct list_head *this;
580 list_for_each(this, &c->erasing_list) {
581 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
583 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
584 printk(JFFS2_DBG "erasing_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);
590 if (list_empty(&c->erase_checking_list)) {
591 printk(JFFS2_DBG "erase_checking_list: empty\n");
592 } else {
593 struct list_head *this;
595 list_for_each(this, &c->erase_checking_list) {
596 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
598 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
599 printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
600 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
601 jeb->unchecked_size, jeb->free_size);
606 if (list_empty(&c->erase_pending_list)) {
607 printk(JFFS2_DBG "erase_pending_list: empty\n");
608 } else {
609 struct list_head *this;
611 list_for_each(this, &c->erase_pending_list) {
612 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
614 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
615 printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
616 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
617 jeb->unchecked_size, jeb->free_size);
622 if (list_empty(&c->erasable_pending_wbuf_list)) {
623 printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
624 } else {
625 struct list_head *this;
627 list_for_each(this, &c->erasable_pending_wbuf_list) {
628 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
630 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
631 printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
632 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
633 jeb->unchecked_size, jeb->free_size);
638 if (list_empty(&c->free_list)) {
639 printk(JFFS2_DBG "free_list: empty\n");
640 } else {
641 struct list_head *this;
643 list_for_each(this, &c->free_list) {
644 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
646 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
647 printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
648 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
649 jeb->unchecked_size, jeb->free_size);
654 if (list_empty(&c->bad_list)) {
655 printk(JFFS2_DBG "bad_list: empty\n");
656 } else {
657 struct list_head *this;
659 list_for_each(this, &c->bad_list) {
660 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
662 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
663 printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
664 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
665 jeb->unchecked_size, jeb->free_size);
670 if (list_empty(&c->bad_used_list)) {
671 printk(JFFS2_DBG "bad_used_list: empty\n");
672 } else {
673 struct list_head *this;
675 list_for_each(this, &c->bad_used_list) {
676 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
678 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
679 printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
680 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
681 jeb->unchecked_size, jeb->free_size);
687 void
688 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
690 mutex_lock(&f->sem);
691 jffs2_dbg_dump_fragtree_nolock(f);
692 mutex_unlock(&f->sem);
695 void
696 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
698 struct jffs2_node_frag *this = frag_first(&f->fragtree);
699 uint32_t lastofs = 0;
700 int buggy = 0;
702 printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
703 while(this) {
704 if (this->node)
705 printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
706 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
707 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
708 frag_parent(this));
709 else
710 printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
711 this->ofs, this->ofs+this->size, this, frag_left(this),
712 frag_right(this), frag_parent(this));
713 if (this->ofs != lastofs)
714 buggy = 1;
715 lastofs = this->ofs + this->size;
716 this = frag_next(this);
719 if (f->metadata)
720 printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
722 if (buggy) {
723 JFFS2_ERROR("frag tree got a hole in it.\n");
724 BUG();
728 #define JFFS2_BUFDUMP_BYTES_PER_LINE 32
729 void
730 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
732 int skip;
733 int i;
735 printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
736 offs, offs + len, len);
737 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
738 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
740 if (skip != 0)
741 printk(JFFS2_DBG "%#08x: ", offs);
743 while (skip--)
744 printk(" ");
746 while (i < len) {
747 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
748 if (i != 0)
749 printk("\n");
750 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
751 printk(JFFS2_DBG "%0#8x: ", offs);
754 printk("%02x ", buf[i]);
756 i += 1;
759 printk("\n");
763 * Dump a JFFS2 node.
765 void
766 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
768 union jffs2_node_union node;
769 int len = sizeof(union jffs2_node_union);
770 size_t retlen;
771 uint32_t crc;
772 int ret;
774 printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
776 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
777 if (ret || (retlen != len)) {
778 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
779 len, ret, retlen);
780 return;
783 printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
784 printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
785 printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
786 printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
788 crc = crc32(0, &node.u, sizeof(node.u) - 4);
789 if (crc != je32_to_cpu(node.u.hdr_crc)) {
790 JFFS2_ERROR("wrong common header CRC.\n");
791 return;
794 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
795 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
797 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
798 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
799 return;
802 switch(je16_to_cpu(node.u.nodetype)) {
804 case JFFS2_NODETYPE_INODE:
806 printk(JFFS2_DBG "the node is inode node\n");
807 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
808 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
809 printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
810 printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
811 printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
812 printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
813 printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
814 printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
815 printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
816 printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
817 printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
818 printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
819 printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
820 printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
821 printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
822 printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
823 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
825 crc = crc32(0, &node.i, sizeof(node.i) - 8);
826 if (crc != je32_to_cpu(node.i.node_crc)) {
827 JFFS2_ERROR("wrong node header CRC.\n");
828 return;
830 break;
832 case JFFS2_NODETYPE_DIRENT:
834 printk(JFFS2_DBG "the node is dirent node\n");
835 printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
836 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
837 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
838 printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
839 printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
840 printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
841 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
842 printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
844 node.d.name[node.d.nsize] = '\0';
845 printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
847 crc = crc32(0, &node.d, sizeof(node.d) - 8);
848 if (crc != je32_to_cpu(node.d.node_crc)) {
849 JFFS2_ERROR("wrong node header CRC.\n");
850 return;
852 break;
854 default:
855 printk(JFFS2_DBG "node type is unknown\n");
856 break;
859 #endif /* JFFS2_DBG_DUMPS || JFFS2_DBG_PARANOIA_CHECKS */