0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0014
0015 #include <linux/kernel.h>
0016 #include <linux/types.h>
0017 #include <linux/pagemap.h>
0018 #include <linux/crc32.h>
0019 #include <linux/jffs2.h>
0020 #include <linux/mtd/mtd.h>
0021 #include <linux/slab.h>
0022 #include "nodelist.h"
0023 #include "debug.h"
0024
0025 #ifdef JFFS2_DBG_SANITY_CHECKS
0026
0027 void
0028 __jffs2_dbg_acct_sanity_check_nolock(struct jffs2_sb_info *c,
0029 struct jffs2_eraseblock *jeb)
0030 {
0031 if (unlikely(jeb && jeb->used_size + jeb->dirty_size +
0032 jeb->free_size + jeb->wasted_size +
0033 jeb->unchecked_size != c->sector_size)) {
0034 JFFS2_ERROR("eeep, space accounting for block at 0x%08x is screwed.\n", jeb->offset);
0035 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
0036 jeb->free_size, jeb->dirty_size, jeb->used_size,
0037 jeb->wasted_size, jeb->unchecked_size, c->sector_size);
0038 BUG();
0039 }
0040
0041 if (unlikely(c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size
0042 + c->wasted_size + c->unchecked_size != c->flash_size)) {
0043 JFFS2_ERROR("eeep, space accounting superblock info is screwed.\n");
0044 JFFS2_ERROR("free %#08x + dirty %#08x + used %#08x + erasing %#08x + bad %#08x + wasted %#08x + unchecked %#08x != total %#08x.\n",
0045 c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size,
0046 c->wasted_size, c->unchecked_size, c->flash_size);
0047 BUG();
0048 }
0049 }
0050
0051 void
0052 __jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c,
0053 struct jffs2_eraseblock *jeb)
0054 {
0055 spin_lock(&c->erase_completion_lock);
0056 jffs2_dbg_acct_sanity_check_nolock(c, jeb);
0057 spin_unlock(&c->erase_completion_lock);
0058 }
0059
0060 #endif
0061
0062 #ifdef JFFS2_DBG_PARANOIA_CHECKS
0063
0064
0065
0066 void
0067 __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f)
0068 {
0069 mutex_lock(&f->sem);
0070 __jffs2_dbg_fragtree_paranoia_check_nolock(f);
0071 mutex_unlock(&f->sem);
0072 }
0073
0074 void
0075 __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f)
0076 {
0077 struct jffs2_node_frag *frag;
0078 int bitched = 0;
0079
0080 for (frag = frag_first(&f->fragtree); frag; frag = frag_next(frag)) {
0081 struct jffs2_full_dnode *fn = frag->node;
0082
0083 if (!fn || !fn->raw)
0084 continue;
0085
0086 if (ref_flags(fn->raw) == REF_PRISTINE) {
0087 if (fn->frags > 1) {
0088 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had %d frags. Tell dwmw2.\n",
0089 ref_offset(fn->raw), fn->frags);
0090 bitched = 1;
0091 }
0092
0093
0094
0095
0096
0097
0098 if (frag->ofs & (PAGE_SIZE-1) && frag_prev(frag)
0099 && frag_prev(frag)->size < PAGE_SIZE && frag_prev(frag)->node) {
0100 JFFS2_ERROR("REF_PRISTINE node at 0x%08x had a previous non-hole frag in the same page. Tell dwmw2.\n",
0101 ref_offset(fn->raw));
0102 bitched = 1;
0103 }
0104
0105 if ((frag->ofs+frag->size) & (PAGE_SIZE-1) && frag_next(frag)
0106 && frag_next(frag)->size < PAGE_SIZE && frag_next(frag)->node) {
0107 JFFS2_ERROR("REF_PRISTINE node at 0x%08x (%08x-%08x) had a following non-hole frag in the same page. Tell dwmw2.\n",
0108 ref_offset(fn->raw), frag->ofs, frag->ofs+frag->size);
0109 bitched = 1;
0110 }
0111 }
0112 }
0113
0114 if (bitched) {
0115 JFFS2_ERROR("fragtree is corrupted.\n");
0116 __jffs2_dbg_dump_fragtree_nolock(f);
0117 BUG();
0118 }
0119 }
0120
0121
0122
0123
0124 void
0125 __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
0126 uint32_t ofs, int len)
0127 {
0128 size_t retlen;
0129 int ret, i;
0130 unsigned char *buf;
0131
0132 buf = kmalloc(len, GFP_KERNEL);
0133 if (!buf)
0134 return;
0135
0136 ret = jffs2_flash_read(c, ofs, len, &retlen, buf);
0137 if (ret || (retlen != len)) {
0138 JFFS2_WARNING("read %d bytes failed or short. ret %d, retlen %zd.\n",
0139 len, ret, retlen);
0140 kfree(buf);
0141 return;
0142 }
0143
0144 ret = 0;
0145 for (i = 0; i < len; i++)
0146 if (buf[i] != 0xff)
0147 ret = 1;
0148
0149 if (ret) {
0150 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",
0151 ofs, ofs + i);
0152 __jffs2_dbg_dump_buffer(buf, len, ofs);
0153 kfree(buf);
0154 BUG();
0155 }
0156
0157 kfree(buf);
0158 }
0159
0160 void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
0161 {
0162 struct jffs2_eraseblock *jeb;
0163 uint32_t free = 0, dirty = 0, used = 0, wasted = 0,
0164 erasing = 0, bad = 0, unchecked = 0;
0165 int nr_counted = 0;
0166 int dump = 0;
0167
0168 if (c->gcblock) {
0169 nr_counted++;
0170 free += c->gcblock->free_size;
0171 dirty += c->gcblock->dirty_size;
0172 used += c->gcblock->used_size;
0173 wasted += c->gcblock->wasted_size;
0174 unchecked += c->gcblock->unchecked_size;
0175 }
0176 if (c->nextblock) {
0177 nr_counted++;
0178 free += c->nextblock->free_size;
0179 dirty += c->nextblock->dirty_size;
0180 used += c->nextblock->used_size;
0181 wasted += c->nextblock->wasted_size;
0182 unchecked += c->nextblock->unchecked_size;
0183 }
0184 list_for_each_entry(jeb, &c->clean_list, list) {
0185 nr_counted++;
0186 free += jeb->free_size;
0187 dirty += jeb->dirty_size;
0188 used += jeb->used_size;
0189 wasted += jeb->wasted_size;
0190 unchecked += jeb->unchecked_size;
0191 }
0192 list_for_each_entry(jeb, &c->very_dirty_list, list) {
0193 nr_counted++;
0194 free += jeb->free_size;
0195 dirty += jeb->dirty_size;
0196 used += jeb->used_size;
0197 wasted += jeb->wasted_size;
0198 unchecked += jeb->unchecked_size;
0199 }
0200 list_for_each_entry(jeb, &c->dirty_list, list) {
0201 nr_counted++;
0202 free += jeb->free_size;
0203 dirty += jeb->dirty_size;
0204 used += jeb->used_size;
0205 wasted += jeb->wasted_size;
0206 unchecked += jeb->unchecked_size;
0207 }
0208 list_for_each_entry(jeb, &c->erasable_list, list) {
0209 nr_counted++;
0210 free += jeb->free_size;
0211 dirty += jeb->dirty_size;
0212 used += jeb->used_size;
0213 wasted += jeb->wasted_size;
0214 unchecked += jeb->unchecked_size;
0215 }
0216 list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) {
0217 nr_counted++;
0218 free += jeb->free_size;
0219 dirty += jeb->dirty_size;
0220 used += jeb->used_size;
0221 wasted += jeb->wasted_size;
0222 unchecked += jeb->unchecked_size;
0223 }
0224 list_for_each_entry(jeb, &c->erase_pending_list, list) {
0225 nr_counted++;
0226 free += jeb->free_size;
0227 dirty += jeb->dirty_size;
0228 used += jeb->used_size;
0229 wasted += jeb->wasted_size;
0230 unchecked += jeb->unchecked_size;
0231 }
0232 list_for_each_entry(jeb, &c->free_list, list) {
0233 nr_counted++;
0234 free += jeb->free_size;
0235 dirty += jeb->dirty_size;
0236 used += jeb->used_size;
0237 wasted += jeb->wasted_size;
0238 unchecked += jeb->unchecked_size;
0239 }
0240 list_for_each_entry(jeb, &c->bad_used_list, list) {
0241 nr_counted++;
0242 free += jeb->free_size;
0243 dirty += jeb->dirty_size;
0244 used += jeb->used_size;
0245 wasted += jeb->wasted_size;
0246 unchecked += jeb->unchecked_size;
0247 }
0248
0249 list_for_each_entry(jeb, &c->erasing_list, list) {
0250 nr_counted++;
0251 erasing += c->sector_size;
0252 }
0253 list_for_each_entry(jeb, &c->erase_checking_list, list) {
0254 nr_counted++;
0255 erasing += c->sector_size;
0256 }
0257 list_for_each_entry(jeb, &c->erase_complete_list, list) {
0258 nr_counted++;
0259 erasing += c->sector_size;
0260 }
0261 list_for_each_entry(jeb, &c->bad_list, list) {
0262 nr_counted++;
0263 bad += c->sector_size;
0264 }
0265
0266 #define check(sz) \
0267 do { \
0268 if (sz != c->sz##_size) { \
0269 pr_warn("%s_size mismatch counted 0x%x, c->%s_size 0x%x\n", \
0270 #sz, sz, #sz, c->sz##_size); \
0271 dump = 1; \
0272 } \
0273 } while (0)
0274
0275 check(free);
0276 check(dirty);
0277 check(used);
0278 check(wasted);
0279 check(unchecked);
0280 check(bad);
0281 check(erasing);
0282
0283 #undef check
0284
0285 if (nr_counted != c->nr_blocks) {
0286 pr_warn("%s counted only 0x%x blocks of 0x%x. Where are the others?\n",
0287 __func__, nr_counted, c->nr_blocks);
0288 dump = 1;
0289 }
0290
0291 if (dump) {
0292 __jffs2_dbg_dump_block_lists_nolock(c);
0293 BUG();
0294 }
0295 }
0296
0297
0298
0299
0300 void
0301 __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c,
0302 struct jffs2_eraseblock *jeb)
0303 {
0304 spin_lock(&c->erase_completion_lock);
0305 __jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
0306 spin_unlock(&c->erase_completion_lock);
0307 }
0308
0309 void
0310 __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
0311 struct jffs2_eraseblock *jeb)
0312 {
0313 uint32_t my_used_size = 0;
0314 uint32_t my_unchecked_size = 0;
0315 uint32_t my_dirty_size = 0;
0316 struct jffs2_raw_node_ref *ref2 = jeb->first_node;
0317
0318 while (ref2) {
0319 uint32_t totlen = ref_totlen(c, jeb, ref2);
0320
0321 if (ref_offset(ref2) < jeb->offset ||
0322 ref_offset(ref2) > jeb->offset + c->sector_size) {
0323 JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n",
0324 ref_offset(ref2), jeb->offset);
0325 goto error;
0326
0327 }
0328 if (ref_flags(ref2) == REF_UNCHECKED)
0329 my_unchecked_size += totlen;
0330 else if (!ref_obsolete(ref2))
0331 my_used_size += totlen;
0332 else
0333 my_dirty_size += totlen;
0334
0335 if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
0336 JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
0337 ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
0338 ref_offset(jeb->last_node), jeb->last_node);
0339 goto error;
0340 }
0341 ref2 = ref_next(ref2);
0342 }
0343
0344 if (my_used_size != jeb->used_size) {
0345 JFFS2_ERROR("Calculated used size %#08x != stored used size %#08x.\n",
0346 my_used_size, jeb->used_size);
0347 goto error;
0348 }
0349
0350 if (my_unchecked_size != jeb->unchecked_size) {
0351 JFFS2_ERROR("Calculated unchecked size %#08x != stored unchecked size %#08x.\n",
0352 my_unchecked_size, jeb->unchecked_size);
0353 goto error;
0354 }
0355
0356 #if 0
0357
0358 if (my_dirty_size != jeb->dirty_size + jeb->wasted_size) {
0359 JFFS2_ERROR("Calculated dirty+wasted size %#08x != stored dirty + wasted size %#08x\n",
0360 my_dirty_size, jeb->dirty_size + jeb->wasted_size);
0361 goto error;
0362 }
0363
0364 if (jeb->free_size == 0
0365 && my_used_size + my_unchecked_size + my_dirty_size != c->sector_size) {
0366 JFFS2_ERROR("The sum of all nodes in block (%#x) != size of block (%#x)\n",
0367 my_used_size + my_unchecked_size + my_dirty_size,
0368 c->sector_size);
0369 goto error;
0370 }
0371 #endif
0372
0373 if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING)))
0374 __jffs2_dbg_superblock_counts(c);
0375
0376 return;
0377
0378 error:
0379 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
0380 __jffs2_dbg_dump_jeb_nolock(jeb);
0381 __jffs2_dbg_dump_block_lists_nolock(c);
0382 BUG();
0383
0384 }
0385 #endif
0386
0387 #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
0388
0389
0390
0391 void
0392 __jffs2_dbg_dump_node_refs(struct jffs2_sb_info *c,
0393 struct jffs2_eraseblock *jeb)
0394 {
0395 spin_lock(&c->erase_completion_lock);
0396 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
0397 spin_unlock(&c->erase_completion_lock);
0398 }
0399
0400 void
0401 __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
0402 struct jffs2_eraseblock *jeb)
0403 {
0404 struct jffs2_raw_node_ref *ref;
0405 int i = 0;
0406
0407 printk(JFFS2_DBG_MSG_PREFIX " Dump node_refs of the eraseblock %#08x\n", jeb->offset);
0408 if (!jeb->first_node) {
0409 printk(JFFS2_DBG_MSG_PREFIX " no nodes in the eraseblock %#08x\n", jeb->offset);
0410 return;
0411 }
0412
0413 printk(JFFS2_DBG);
0414 for (ref = jeb->first_node; ; ref = ref_next(ref)) {
0415 printk("%#08x", ref_offset(ref));
0416 #ifdef TEST_TOTLEN
0417 printk("(%x)", ref->__totlen);
0418 #endif
0419 if (ref_next(ref))
0420 printk("->");
0421 else
0422 break;
0423 if (++i == 4) {
0424 i = 0;
0425 printk("\n" JFFS2_DBG);
0426 }
0427 }
0428 printk("\n");
0429 }
0430
0431
0432
0433
0434 void
0435 __jffs2_dbg_dump_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
0436 {
0437 spin_lock(&c->erase_completion_lock);
0438 __jffs2_dbg_dump_jeb_nolock(jeb);
0439 spin_unlock(&c->erase_completion_lock);
0440 }
0441
0442 void
0443 __jffs2_dbg_dump_jeb_nolock(struct jffs2_eraseblock *jeb)
0444 {
0445 if (!jeb)
0446 return;
0447
0448 printk(JFFS2_DBG_MSG_PREFIX " dump space accounting for the eraseblock at %#08x:\n",
0449 jeb->offset);
0450
0451 printk(JFFS2_DBG "used_size: %#08x\n", jeb->used_size);
0452 printk(JFFS2_DBG "dirty_size: %#08x\n", jeb->dirty_size);
0453 printk(JFFS2_DBG "wasted_size: %#08x\n", jeb->wasted_size);
0454 printk(JFFS2_DBG "unchecked_size: %#08x\n", jeb->unchecked_size);
0455 printk(JFFS2_DBG "free_size: %#08x\n", jeb->free_size);
0456 }
0457
0458 void
0459 __jffs2_dbg_dump_block_lists(struct jffs2_sb_info *c)
0460 {
0461 spin_lock(&c->erase_completion_lock);
0462 __jffs2_dbg_dump_block_lists_nolock(c);
0463 spin_unlock(&c->erase_completion_lock);
0464 }
0465
0466 void
0467 __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c)
0468 {
0469 printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n");
0470
0471 printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size);
0472 printk(JFFS2_DBG "used_size: %#08x\n", c->used_size);
0473 printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size);
0474 printk(JFFS2_DBG "wasted_size: %#08x\n", c->wasted_size);
0475 printk(JFFS2_DBG "unchecked_size: %#08x\n", c->unchecked_size);
0476 printk(JFFS2_DBG "free_size: %#08x\n", c->free_size);
0477 printk(JFFS2_DBG "erasing_size: %#08x\n", c->erasing_size);
0478 printk(JFFS2_DBG "bad_size: %#08x\n", c->bad_size);
0479 printk(JFFS2_DBG "sector_size: %#08x\n", c->sector_size);
0480 printk(JFFS2_DBG "jffs2_reserved_blocks size: %#08x\n",
0481 c->sector_size * c->resv_blocks_write);
0482
0483 if (c->nextblock)
0484 printk(JFFS2_DBG "nextblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0485 c->nextblock->offset, c->nextblock->used_size,
0486 c->nextblock->dirty_size, c->nextblock->wasted_size,
0487 c->nextblock->unchecked_size, c->nextblock->free_size);
0488 else
0489 printk(JFFS2_DBG "nextblock: NULL\n");
0490
0491 if (c->gcblock)
0492 printk(JFFS2_DBG "gcblock: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0493 c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size,
0494 c->gcblock->wasted_size, c->gcblock->unchecked_size, c->gcblock->free_size);
0495 else
0496 printk(JFFS2_DBG "gcblock: NULL\n");
0497
0498 if (list_empty(&c->clean_list)) {
0499 printk(JFFS2_DBG "clean_list: empty\n");
0500 } else {
0501 struct list_head *this;
0502 int numblocks = 0;
0503 uint32_t dirty = 0;
0504
0505 list_for_each(this, &c->clean_list) {
0506 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0507 numblocks ++;
0508 dirty += jeb->wasted_size;
0509 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0510 printk(JFFS2_DBG "clean_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0511 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0512 jeb->unchecked_size, jeb->free_size);
0513 }
0514 }
0515
0516 printk (JFFS2_DBG "Contains %d blocks with total wasted size %u, average wasted size: %u\n",
0517 numblocks, dirty, dirty / numblocks);
0518 }
0519
0520 if (list_empty(&c->very_dirty_list)) {
0521 printk(JFFS2_DBG "very_dirty_list: empty\n");
0522 } else {
0523 struct list_head *this;
0524 int numblocks = 0;
0525 uint32_t dirty = 0;
0526
0527 list_for_each(this, &c->very_dirty_list) {
0528 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0529
0530 numblocks ++;
0531 dirty += jeb->dirty_size;
0532 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0533 printk(JFFS2_DBG "very_dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0534 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0535 jeb->unchecked_size, jeb->free_size);
0536 }
0537 }
0538
0539 printk (JFFS2_DBG "Contains %d blocks with total dirty size %u, average dirty size: %u\n",
0540 numblocks, dirty, dirty / numblocks);
0541 }
0542
0543 if (list_empty(&c->dirty_list)) {
0544 printk(JFFS2_DBG "dirty_list: empty\n");
0545 } else {
0546 struct list_head *this;
0547 int numblocks = 0;
0548 uint32_t dirty = 0;
0549
0550 list_for_each(this, &c->dirty_list) {
0551 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0552
0553 numblocks ++;
0554 dirty += jeb->dirty_size;
0555 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0556 printk(JFFS2_DBG "dirty_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0557 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0558 jeb->unchecked_size, jeb->free_size);
0559 }
0560 }
0561
0562 printk (JFFS2_DBG "contains %d blocks with total dirty size %u, average dirty size: %u\n",
0563 numblocks, dirty, dirty / numblocks);
0564 }
0565
0566 if (list_empty(&c->erasable_list)) {
0567 printk(JFFS2_DBG "erasable_list: empty\n");
0568 } else {
0569 struct list_head *this;
0570
0571 list_for_each(this, &c->erasable_list) {
0572 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0573
0574 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0575 printk(JFFS2_DBG "erasable_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0576 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0577 jeb->unchecked_size, jeb->free_size);
0578 }
0579 }
0580 }
0581
0582 if (list_empty(&c->erasing_list)) {
0583 printk(JFFS2_DBG "erasing_list: empty\n");
0584 } else {
0585 struct list_head *this;
0586
0587 list_for_each(this, &c->erasing_list) {
0588 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0589
0590 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0591 printk(JFFS2_DBG "erasing_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0592 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0593 jeb->unchecked_size, jeb->free_size);
0594 }
0595 }
0596 }
0597 if (list_empty(&c->erase_checking_list)) {
0598 printk(JFFS2_DBG "erase_checking_list: empty\n");
0599 } else {
0600 struct list_head *this;
0601
0602 list_for_each(this, &c->erase_checking_list) {
0603 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0604
0605 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0606 printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0607 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0608 jeb->unchecked_size, jeb->free_size);
0609 }
0610 }
0611 }
0612
0613 if (list_empty(&c->erase_pending_list)) {
0614 printk(JFFS2_DBG "erase_pending_list: empty\n");
0615 } else {
0616 struct list_head *this;
0617
0618 list_for_each(this, &c->erase_pending_list) {
0619 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0620
0621 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0622 printk(JFFS2_DBG "erase_pending_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0623 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0624 jeb->unchecked_size, jeb->free_size);
0625 }
0626 }
0627 }
0628
0629 if (list_empty(&c->erasable_pending_wbuf_list)) {
0630 printk(JFFS2_DBG "erasable_pending_wbuf_list: empty\n");
0631 } else {
0632 struct list_head *this;
0633
0634 list_for_each(this, &c->erasable_pending_wbuf_list) {
0635 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0636
0637 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0638 printk(JFFS2_DBG "erasable_pending_wbuf_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0639 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0640 jeb->unchecked_size, jeb->free_size);
0641 }
0642 }
0643 }
0644
0645 if (list_empty(&c->free_list)) {
0646 printk(JFFS2_DBG "free_list: empty\n");
0647 } else {
0648 struct list_head *this;
0649
0650 list_for_each(this, &c->free_list) {
0651 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0652
0653 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0654 printk(JFFS2_DBG "free_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0655 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0656 jeb->unchecked_size, jeb->free_size);
0657 }
0658 }
0659 }
0660
0661 if (list_empty(&c->bad_list)) {
0662 printk(JFFS2_DBG "bad_list: empty\n");
0663 } else {
0664 struct list_head *this;
0665
0666 list_for_each(this, &c->bad_list) {
0667 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0668
0669 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0670 printk(JFFS2_DBG "bad_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0671 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0672 jeb->unchecked_size, jeb->free_size);
0673 }
0674 }
0675 }
0676
0677 if (list_empty(&c->bad_used_list)) {
0678 printk(JFFS2_DBG "bad_used_list: empty\n");
0679 } else {
0680 struct list_head *this;
0681
0682 list_for_each(this, &c->bad_used_list) {
0683 struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
0684
0685 if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) {
0686 printk(JFFS2_DBG "bad_used_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n",
0687 jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size,
0688 jeb->unchecked_size, jeb->free_size);
0689 }
0690 }
0691 }
0692 }
0693
0694 void
0695 __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f)
0696 {
0697 mutex_lock(&f->sem);
0698 jffs2_dbg_dump_fragtree_nolock(f);
0699 mutex_unlock(&f->sem);
0700 }
0701
0702 void
0703 __jffs2_dbg_dump_fragtree_nolock(struct jffs2_inode_info *f)
0704 {
0705 struct jffs2_node_frag *this = frag_first(&f->fragtree);
0706 uint32_t lastofs = 0;
0707 int buggy = 0;
0708
0709 printk(JFFS2_DBG_MSG_PREFIX " dump fragtree of ino #%u\n", f->inocache->ino);
0710 while(this) {
0711 if (this->node)
0712 printk(JFFS2_DBG "frag %#04x-%#04x: %#08x(%d) on flash (*%p), left (%p), right (%p), parent (%p)\n",
0713 this->ofs, this->ofs+this->size, ref_offset(this->node->raw),
0714 ref_flags(this->node->raw), this, frag_left(this), frag_right(this),
0715 frag_parent(this));
0716 else
0717 printk(JFFS2_DBG "frag %#04x-%#04x: hole (*%p). left (%p), right (%p), parent (%p)\n",
0718 this->ofs, this->ofs+this->size, this, frag_left(this),
0719 frag_right(this), frag_parent(this));
0720 if (this->ofs != lastofs)
0721 buggy = 1;
0722 lastofs = this->ofs + this->size;
0723 this = frag_next(this);
0724 }
0725
0726 if (f->metadata)
0727 printk(JFFS2_DBG "metadata at 0x%08x\n", ref_offset(f->metadata->raw));
0728
0729 if (buggy) {
0730 JFFS2_ERROR("frag tree got a hole in it.\n");
0731 BUG();
0732 }
0733 }
0734
0735 #define JFFS2_BUFDUMP_BYTES_PER_LINE 32
0736 void
0737 __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs)
0738 {
0739 int skip;
0740 int i;
0741
0742 printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n",
0743 offs, offs + len, len);
0744 i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE;
0745 offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1);
0746
0747 if (skip != 0)
0748 printk(JFFS2_DBG "%#08x: ", offs);
0749
0750 while (skip--)
0751 printk(" ");
0752
0753 while (i < len) {
0754 if ((i % JFFS2_BUFDUMP_BYTES_PER_LINE) == 0 && i != len -1) {
0755 if (i != 0)
0756 printk("\n");
0757 offs += JFFS2_BUFDUMP_BYTES_PER_LINE;
0758 printk(JFFS2_DBG "%0#8x: ", offs);
0759 }
0760
0761 printk("%02x ", buf[i]);
0762
0763 i += 1;
0764 }
0765
0766 printk("\n");
0767 }
0768
0769
0770
0771
0772 void
0773 __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs)
0774 {
0775 union jffs2_node_union node;
0776 int len = sizeof(union jffs2_node_union);
0777 size_t retlen;
0778 uint32_t crc;
0779 int ret;
0780
0781 printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs);
0782
0783 ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node);
0784 if (ret || (retlen != len)) {
0785 JFFS2_ERROR("read %d bytes failed or short. ret %d, retlen %zd.\n",
0786 len, ret, retlen);
0787 return;
0788 }
0789
0790 printk(JFFS2_DBG "magic:\t%#04x\n", je16_to_cpu(node.u.magic));
0791 printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype));
0792 printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen));
0793 printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc));
0794
0795 crc = crc32(0, &node.u, sizeof(node.u) - 4);
0796 if (crc != je32_to_cpu(node.u.hdr_crc)) {
0797 JFFS2_ERROR("wrong common header CRC.\n");
0798 return;
0799 }
0800
0801 if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK &&
0802 je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK)
0803 {
0804 JFFS2_ERROR("wrong node magic: %#04x instead of %#04x.\n",
0805 je16_to_cpu(node.u.magic), JFFS2_MAGIC_BITMASK);
0806 return;
0807 }
0808
0809 switch(je16_to_cpu(node.u.nodetype)) {
0810
0811 case JFFS2_NODETYPE_INODE:
0812
0813 printk(JFFS2_DBG "the node is inode node\n");
0814 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.i.ino));
0815 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.i.version));
0816 printk(JFFS2_DBG "mode:\t%#08x\n", node.i.mode.m);
0817 printk(JFFS2_DBG "uid:\t%#04x\n", je16_to_cpu(node.i.uid));
0818 printk(JFFS2_DBG "gid:\t%#04x\n", je16_to_cpu(node.i.gid));
0819 printk(JFFS2_DBG "isize:\t%#08x\n", je32_to_cpu(node.i.isize));
0820 printk(JFFS2_DBG "atime:\t%#08x\n", je32_to_cpu(node.i.atime));
0821 printk(JFFS2_DBG "mtime:\t%#08x\n", je32_to_cpu(node.i.mtime));
0822 printk(JFFS2_DBG "ctime:\t%#08x\n", je32_to_cpu(node.i.ctime));
0823 printk(JFFS2_DBG "offset:\t%#08x\n", je32_to_cpu(node.i.offset));
0824 printk(JFFS2_DBG "csize:\t%#08x\n", je32_to_cpu(node.i.csize));
0825 printk(JFFS2_DBG "dsize:\t%#08x\n", je32_to_cpu(node.i.dsize));
0826 printk(JFFS2_DBG "compr:\t%#02x\n", node.i.compr);
0827 printk(JFFS2_DBG "usercompr:\t%#02x\n", node.i.usercompr);
0828 printk(JFFS2_DBG "flags:\t%#04x\n", je16_to_cpu(node.i.flags));
0829 printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc));
0830 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc));
0831
0832 crc = crc32(0, &node.i, sizeof(node.i) - 8);
0833 if (crc != je32_to_cpu(node.i.node_crc)) {
0834 JFFS2_ERROR("wrong node header CRC.\n");
0835 return;
0836 }
0837 break;
0838
0839 case JFFS2_NODETYPE_DIRENT:
0840
0841 printk(JFFS2_DBG "the node is dirent node\n");
0842 printk(JFFS2_DBG "pino:\t%#08x\n", je32_to_cpu(node.d.pino));
0843 printk(JFFS2_DBG "version:\t%#08x\n", je32_to_cpu(node.d.version));
0844 printk(JFFS2_DBG "ino:\t%#08x\n", je32_to_cpu(node.d.ino));
0845 printk(JFFS2_DBG "mctime:\t%#08x\n", je32_to_cpu(node.d.mctime));
0846 printk(JFFS2_DBG "nsize:\t%#02x\n", node.d.nsize);
0847 printk(JFFS2_DBG "type:\t%#02x\n", node.d.type);
0848 printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc));
0849 printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc));
0850
0851 node.d.name[node.d.nsize] = '\0';
0852 printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name);
0853
0854 crc = crc32(0, &node.d, sizeof(node.d) - 8);
0855 if (crc != je32_to_cpu(node.d.node_crc)) {
0856 JFFS2_ERROR("wrong node header CRC.\n");
0857 return;
0858 }
0859 break;
0860
0861 default:
0862 printk(JFFS2_DBG "node type is unknown\n");
0863 break;
0864 }
0865 }
0866 #endif