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